[#114181] [Ruby master Bug#19767] [Not really a bug, but more a not ideal notification] "historical binary regexp match" when using the "n" modifier in a ruby regex — "rubyFeedback (robert heiler) via ruby-core" <ruby-core@...>
SXNzdWUgIzE5NzY3IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IHJ1YnlGZWVkYmFjayAocm9iZXJ0IGhl
3 messages
2023/07/14
[ruby-core:114277] [Ruby master Feature#19783] Weak References in the GC
From:
"byroot (Jean Boussier) via ruby-core" <ruby-core@...>
Date:
2023-07-25 10:04:16 UTC
List:
ruby-core #114277
Issue #19783 has been updated by byroot (Jean Boussier).
I believe this would fix [Bug #19436] (Call Cache for singleton methods can=
lead to "memory leaks")
----------------------------------------
Feature #19783: Weak References in the GC
https://bugs.ruby-lang.org/issues/19783#change-103972
* Author: peterzhu2118 (Peter Zhu)
* Status: Open
* Priority: Normal
----------------------------------------
GitHub PR: https://github.com/ruby/ruby/pull/8113
I'm proposing support for weak references in the Ruby garbage collector. Th=
is
feature adds a new function called `void rb_gc_mark_weak(VALUE *ptr)` which
marks `*ptr` as weak, meaning that if no other object strongly marks `*ptr`
(using `rb_gc_mark` or `rb_gc_mark_movable`), then it will be overwritten w=
ith
`*ptr =3D Qundef`.
Weak references are implemented using a buffer in `objspace` that stores all
the `ptr` in the latest marking phase. After marking has finished, we itera=
te
over the buffer and check if the `*ptr` is a dead object. If it is, then we
set `*ptr =3D Qundef`.
Weak references are implemented on the callable method entry (CME) of
callcaches, which fixes issue #19436.
Weak references are also implemented on `ObjectSpace::WeakMap` and
`ObjectSpace::WeakKeyMap`, which have:
- Significantly simpler implementations because we no longer need to have
multiple tables and do not need to define finalizers on the objects.
- Support for compaction because finalizers pin objects and we no longer ne=
ed
to define finalizers on the objects.
- Much faster performance (see [benchmarks](#microbenchmarks)).
## Metrics
This patch also adds two metrics, `GC.latest_gc_info(:weak_references_count=
)`
and `GC.latest_gc_info(:retained_weak_references_count)`. These two metrics
returns information about the number of weak references registered and the
number of weak references retained (references that did not point to a dead
object) in the last GC cycle.
## Benchmark results
### YJIT-bench
We see largely no change in performance or memory usage after this feature.
```
-------------- --------- ---------- --------- ----------- ---------- =
--------- -------------- -----------
bench base (ms) stddev (%) RSS (MiB) branch (ms) stddev (%) =
RSS (MiB) branch 1st itr base/branch
activerecord 72.3 2.2 51.9 72.9 2.2 =
51.9 0.99 0.99
chunky-png 889.2 0.3 43.9 874.5 0.3 =
42.5 1.02 1.02
erubi-rails 21.2 13.5 90.7 21.0 13.3 =
90.9 1.01 1.01
hexapdf 2557.0 0.8 157.1 2559.2 0.7 =
197.1 1.01 1.00
liquid-c 65.2 0.4 34.5 65.4 0.4 =
34.5 0.99 1.00
liquid-compile 62.5 0.4 30.9 62.2 0.4 =
31.0 1.00 1.01
liquid-render 164.6 0.4 33.1 162.6 0.3 =
33.1 1.01 1.01
mail 133.3 0.1 46.4 134.4 0.2 =
46.4 1.03 0.99
psych-load 2066.6 0.2 31.6 2083.6 0.1 =
31.6 0.99 0.99
railsbench 2027.0 0.5 88.8 2019.4 0.5 =
89.0 1.01 1.00
ruby-lsp 65.6 3.0 90.1 65.4 3.1 =
88.5 1.00 1.00
sequel 73.1 1.1 36.6 73.1 1.1 =
36.6 1.00 1.00
-------------- --------- ---------- --------- ----------- ---------- =
--------- -------------- -----------
```
### Microbenchmarks
We can see signficantly improved performance in `ObjectSpace::WeakMap`, with
`ObjectSpace::WeakMap#[]=3D` being nearly 3x faster.
Base:
```
ObjectSpace::WeakMap#[]=3D
1.037M (=B1 0.5%) i/s - 5.262M in 5.072833s
ObjectSpace::WeakMap#[]
12.367M (=B1 0.9%) i/s - 62.479M in 5.052365s
```
Branch:
```
ObjectSpace::WeakMap#[]=3D
3.054M (=B1 0.3%) i/s - 15.448M in 5.058783s
ObjectSpace::WeakMap#[]
15.796M (=B1 4.8%) i/s - 79.245M in 5.028583s
```
Code:
```ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "benchmark-ips"
end
wmap =3D ObjectSpace::WeakMap.new
key =3D Object.new
val =3D Object.new
wmap[key] =3D val
Benchmark.ips do |x|
x.report("ObjectSpace::WeakMap#[]=3D") do |times|
i =3D 0
while i < times
wmap[Object.new] =3D Object.new
i +=3D 1
end
end
x.report("ObjectSpace::WeakMap#[]") do |times|
i =3D 0
while i < times
wmap[key]
wmap[val] # does not exist
i +=3D 1
end
end
end
```
--=20
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- [email protected]
To unsubscribe send an email to [email protected]
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-c=
ore.ml.ruby-lang.org/