[#105882] [Ruby master Bug#18280] Segmentation Fault in rb_utf8_str_new_cstr(NULL) — "ukolovda (Dmitry Ukolov)" <noreply@...>

Issue #18280 has been reported by ukolovda (Dmitry Ukolov).

13 messages 2021/11/01

[#105897] [Ruby master Bug#18282] Rails CI raises Segmentation fault with ruby 3.1.0dev supporting `Class#descendants` — "yahonda (Yasuo Honda)" <noreply@...>

Issue #18282 has been reported by yahonda (Yasuo Honda).

12 messages 2021/11/02

[#105909] [Ruby master Misc#18285] NoMethodError#message uses a lot of CPU/is really expensive to call — "ivoanjo (Ivo Anjo)" <noreply@...>

Issue #18285 has been reported by ivoanjo (Ivo Anjo).

37 messages 2021/11/02

[#105920] [Ruby master Bug#18286] Universal arm64/x86_84 binary built on an x86_64 machine segfaults/is killed on arm64 — "ccaviness (Clay Caviness)" <noreply@...>

Issue #18286 has been reported by ccaviness (Clay Caviness).

16 messages 2021/11/03

[#105928] [Ruby master Feature#18287] Support nil value for sort in Dir.glob — "Strech (Sergey Fedorov)" <noreply@...>

Issue #18287 has been reported by Strech (Sergey Fedorov).

16 messages 2021/11/04

[#105944] [Ruby master Bug#18289] Enumerable#to_a should delegate keyword arguments to #each — "Ethan (Ethan -)" <noreply@...>

Issue #18289 has been reported by Ethan (Ethan -).

8 messages 2021/11/05

[#105967] [Ruby master Bug#18293] Time.at in master branch was 25% slower then Ruby 3.0 — "watson1978 (Shizuo Fujita)" <noreply@...>

Issue #18293 has been reported by watson1978 (Shizuo Fujita).

17 messages 2021/11/08

[#106008] [Ruby master Bug#18296] Custom exception formatting should override `Exception#full_message`. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18296 has been reported by ioquatix (Samuel Williams).

14 messages 2021/11/10

[#106033] [Ruby master Bug#18330] Make failure on 32-bit Linux (Android) with Clang due to implicit 64-to-32-bit integer truncation — "xtkoba (Tee KOBAYASHI)" <noreply@...>

Issue #18330 has been reported by xtkoba (Tee KOBAYASHI).

10 messages 2021/11/11

[#106053] [Ruby master Misc#18335] openindiana ruby 3.1 preview needs --disable-dtrace — "stes (David Stes)" <noreply@...>

Issue #18335 has been reported by stes (David Stes).

14 messages 2021/11/14

[#106069] [Ruby master Feature#18339] GVL instrumentation API — "byroot (Jean Boussier)" <noreply@...>

Issue #18339 has been reported by byroot (Jean Boussier).

13 messages 2021/11/15

[#106145] [Ruby master Misc#18346] DevelopersMeeting20211209Japan — "mame (Yusuke Endoh)" <noreply@...>

Issue #18346 has been reported by mame (Yusuke Endoh).

11 messages 2021/11/18

[#106173] [Ruby master Feature#18349] Let --jit enable YJIT — "k0kubun (Takashi Kokubun)" <noreply@...>

Issue #18349 has been reported by k0kubun (Takashi Kokubun).

8 messages 2021/11/19

[#106175] [Ruby master Feature#18351] Support anonymous rest and keyword rest argument forwarding — "jeremyevans0 (Jeremy Evans)" <noreply@...>

Issue #18351 has been reported by jeremyevans0 (Jeremy Evans).

10 messages 2021/11/19

[#106279] [Ruby master Feature#18364] Add GC.stat_size_pool for Variable Width Allocation — "peterzhu2118 (Peter Zhu)" <noreply@...>

Issue #18364 has been reported by peterzhu2118 (Peter Zhu).

14 messages 2021/11/25

[#106308] [Ruby master Feature#18367] Stop the interpreter from escaping error messages — "mame (Yusuke Endoh)" <noreply@...>

Issue #18367 has been reported by mame (Yusuke Endoh).

13 messages 2021/11/29

[#106314] [Ruby master Feature#18368] Range#step semantics for non-Numeric ranges — "zverok (Victor Shepelev)" <noreply@...>

Issue #18368 has been reported by zverok (Victor Shepelev).

39 messages 2021/11/29

[#106341] [Ruby master Bug#18369] users.detect(:name, "Dorian") as shorthand for users.detect { |user| user.name == "Dorian" } — dorianmariefr <noreply@...>

Issue #18369 has been reported by dorianmariefr (Dorian Mari辿).

14 messages 2021/11/30

[#106347] [Ruby master Feature#18370] Call Exception#full_message to print exceptions reaching the top-level — "Eregon (Benoit Daloze)" <noreply@...>

Issue #18370 has been reported by Eregon (Benoit Daloze).

10 messages 2021/11/30

[ruby-core:106280] [Ruby master Feature#16038] Provide a public WeakMap that compares by equality rather than by identity

From: "Eregon (Benoit Daloze)" <noreply@...>
Date: 2021-11-25 16:30:36 UTC
List: ruby-core #106280
Issue #16038 has been updated by Eregon (Benoit Daloze).


This came up again in https://github.com/rails/rails/pull/43723.

I think adding `WeakKeysMap` and `WeakValuesMap` would be the best.
That's clear and implementable on all Ruby implementations which support weak references in general.

They could be top-level, or nested under `ObjectSpace`, I don't really mind either.

Adding this is *necessary* to have access to a weak-keys map on JVM-based Ruby implementations, since a map that's both weak keys and weak values seems impossible on JVM (and likely other VMs as well).

----------------------------------------
Feature #16038: Provide a public WeakMap that compares by equality rather than by identity 
https://bugs.ruby-lang.org/issues/16038#change-94904

* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
----------------------------------------
I know `ObjectSpace::WeakMap` isn't really supposed to be used, and that the blessed interface is `WeakRef`. However, I'd like to make a case for a better public WeakMap.

### Usage

As described in [Feature #16035], `WeakMap` is useful for deduplicating "value objects". A typical use case is as follows:

```ruby
class Position
  REGISTRY = {}
  private_constant :REGISTRY

  class << self
    def new(*)
      instance = super
      REGISTRY[instance] ||= instance
    end
  end

  attr_reader :x, :y, :z

  def initialize(x, y, z)
    @x = x
    @y = y
    @z = z
    freeze
  end

  def hash
    self.class.hash ^
      x.hash >> 1 ^
      y.hash >> 2 ^
      y.hash >> 3
  end

  def ==(other)
    other.is_a?(Position) &&
      other.x == x &&
      other.y == y &&
      other.z == z
  end
  alias_method :eql?, :==
end

p Position.new(1, 2, 3).equal?(Position.new(1, 2, 3))
```

That's pretty much the pattern [I used in Rails to deduplicate database metadata and save lots of memory](https://github.com/rails/rails/blob/f3c68c59ed57302ca54f4dfad0e91dbff426962d/activerecord/lib/active_record/connection_adapters/deduplicable.rb).

The big downside here is that these value objects can't be GCed anymore, so this pattern is not viable in many case.

### Why not use WeakRef

A couple of reasons. First, when using this pattern, the goal is to reduce memory usage, so having one extra `WeakRef` for every single value object is a bit counter productive. 

Then it's a bit annoying to work with, as you have to constantly check wether the reference is still alive, and/or rescue `WeakRef::RefError`.

Often, these two complications make the tradeoff not worth it.

### Ruby 2.7

Since [Feature #13498] `WeakMap` is a bit more usable as you can now use an interned string as the unique key, e.g.

```ruby
class Position
  REGISTRY = ObjectSpace::WeakMap.new
  private_constant :REGISTRY

  class << self
    def new(*)
      instance = super
      REGISTRY[instance.unique_id] ||= instance
    end
  end

  attr_reader :x, :y, :z, :unique_id

  def initialize(x, y, z)
    @x = x
    @y = y
    @z = z
    @unique_id = -"#{self.class}-#{x},#{y},#{z}"
    freeze
  end

  def hash
    self.class.hash ^
      x.hash >> 1 ^
      y.hash >> 2 ^
      y.hash >> 3
  end

  def ==(other)
    other.is_a?(Position) &&
      other.x == x &&
      other.y == y &&
      other.z == z
  end
  alias_method :eql?, :==
end

p Position.new(1, 2, 3).equal?(Position.new(1, 2, 3))
```

That makes the pattern much easier to work with than dealing with `WeakRef`, but there is still that an extra instance.

### Proposal

What would be ideal would be a `WeakMap` that works by equality, so that the first snippet could simply replace `{}` by `WeakMap.new`. 

Changing `ObjectSpace::WeakMap`'s behavior would cause issues, and I see two possibilities:

  - The best IMO would be to have a new top level `::WeakMap` be the equality based map, and have `ObjectSpace::WeakMap` remain as a semi-private interface for backing up `WeakRef`.
  - Or alternatively, `ObjectSpace::WeakMap` could have a `compare_by_equality` method (inverse of `Hash#compare_by_identity`) to change its behavior post instantiation.

I personally prefer the first one.




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next