<feed xmlns='http://www.w3.org/2005/Atom'>
<title>delta/ruby.git/variable.c, branch maximecb-patch-2</title>
<subtitle>github.com: ruby/ruby.git
</subtitle>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/'/>
<entry>
<title>allow to access ivars of classes/modules</title>
<updated>2021-10-22T16:32:55+00:00</updated>
<author>
<name>Koichi Sasada</name>
<email>ko1@atdot.net</email>
</author>
<published>2021-10-22T08:24:34+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=acb23454e57e1bbe828e7f3114430cab2d5db44c'/>
<id>acb23454e57e1bbe828e7f3114430cab2d5db44c</id>
<content type='text'>
if an ivar of a class/module refer to a shareable object, this ivar
can be read from non-main Ractors.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
if an ivar of a class/module refer to a shareable object, this ivar
can be read from non-main Ractors.
</pre>
</div>
</content>
</entry>
<entry>
<title>Extract yjit_force_iv_index and make it work when object is frozen</title>
<updated>2021-10-20T22:19:43+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2021-10-18T21:01:40+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=b74d6563a665f225f182c4921db68852bbb7e1f1'/>
<id>b74d6563a665f225f182c4921db68852bbb7e1f1</id>
<content type='text'>
In an effort to simplify the logic YJIT generates for accessing instance
variable, YJIT ensures that a given name-to-index mapping exists at
compile time. In the case that the mapping doesn't exist, it was created
by using rb_ivar_set() with Qundef on the sample object we see at
compile time. This hack isn't fine if the sample object happens to be
frozen, in which case YJIT would raise a FrozenError unexpectedly.

To deal with this, make a new function that only reserves the mapping
but doesn't touch the object. This is rb_obj_ensure_iv_index_mapping().
This new function superceeds the functionality of rb_iv_index_tbl_lookup()
so it was removed.

Reported by and includes a test case from John Hawthorn &lt;john@hawthorn.email&gt;

Fixes: GH-282
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In an effort to simplify the logic YJIT generates for accessing instance
variable, YJIT ensures that a given name-to-index mapping exists at
compile time. In the case that the mapping doesn't exist, it was created
by using rb_ivar_set() with Qundef on the sample object we see at
compile time. This hack isn't fine if the sample object happens to be
frozen, in which case YJIT would raise a FrozenError unexpectedly.

To deal with this, make a new function that only reserves the mapping
but doesn't touch the object. This is rb_obj_ensure_iv_index_mapping().
This new function superceeds the functionality of rb_iv_index_tbl_lookup()
so it was removed.

Reported by and includes a test case from John Hawthorn &lt;john@hawthorn.email&gt;

Fixes: GH-282
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove autoload for constant if the autoload fails</title>
<updated>2021-10-08T21:54:26+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2021-10-08T21:54:26+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=08759edea8fb75d46c3e75217e6613465426a0d2'/>
<id>08759edea8fb75d46c3e75217e6613465426a0d2</id>
<content type='text'>
Previously, if an autoload failed (the file was loaded, but the
constant was not defined by the autoloaded file). Ruby will try
to autoload again if you delete the autoloaded file from
$LOADED_FEATURES.  With this change, the autoload and the
constant itself are removed as soon as it fails.

To handle cases where multiple threads are autoloading, when
deleting an autoload, handle the case where another thread
already deleted it.

Fixes [Bug #15790]</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, if an autoload failed (the file was loaded, but the
constant was not defined by the autoloaded file). Ruby will try
to autoload again if you delete the autoloaded file from
$LOADED_FEATURES.  With this change, the autoload and the
constant itself are removed as soon as it fails.

To handle cases where multiple threads are autoloading, when
deleting an autoload, handle the case where another thread
already deleted it.

Fixes [Bug #15790]</pre>
</div>
</content>
</entry>
<entry>
<title>Merge if statement</title>
<updated>2021-10-07T06:18:46+00:00</updated>
<author>
<name>S-H-GAMELINKS</name>
<email>gamelinks007@gmail.com</email>
</author>
<published>2021-10-06T11:18:35+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=323e7a6744a18a729d8011e237e64291cb6c02bd'/>
<id>323e7a6744a18a729d8011e237e64291cb6c02bd</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Return fstrings from `build_const_pathname`.</title>
<updated>2021-09-25T06:19:20+00:00</updated>
<author>
<name>Samuel Williams</name>
<email>samuel.williams@oriontransfer.co.nz</email>
</author>
<published>2021-09-23T20:17:56+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=9151ed2fb2fa8c0648666cdfdb56e38ec3b15815'/>
<id>9151ed2fb2fa8c0648666cdfdb56e38ec3b15815</id>
<content type='text'>
It's possible for `build_const_pathname` to be called when `rb_cString` is
still NULL. There is a fix-up step when `rb_cString` is initialized, but
it only applies to `fstring` instances.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
It's possible for `build_const_pathname` to be called when `rb_cString` is
still NULL. There is a fix-up step when `rb_cString` is initialized, but
it only applies to `fstring` instances.
</pre>
</div>
</content>
</entry>
<entry>
<title>Refactor and Using RBOOL macro</title>
<updated>2021-09-14T23:11:05+00:00</updated>
<author>
<name>S.H</name>
<email>gamelinks007@gmail.com</email>
</author>
<published>2021-09-14T23:11:05+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=b8c3a84bddac7366c4e391234b2535253869e885'/>
<id>b8c3a84bddac7366c4e391234b2535253869e885</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Use Module#ancestors order in recursive constant lookup</title>
<updated>2021-06-30T01:49:27+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2021-06-17T21:47:11+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=3dd3ea092acead6179033f2c95525ffc5b8bb6ff'/>
<id>3dd3ea092acead6179033f2c95525ffc5b8bb6ff</id>
<content type='text'>
Before this commit, const_get with inherit=true and constant lookup
expressions searched the ancestors of the starting point in an order
different from `starting_point.ancestors`.

Items in the ancestry list introduced through prepend were searched
after searching the module they were prepended into. This oddity allowed
for situations where constant lookups gave different results even though
`starting_point.ancestors` is the same.

Do the lookup in the same order as `starting_point.ancestors` by
skipping classes and modules that have an origin iclass. The origin
iclass is in the super chain after the prepended modules.

Note that just like before this commit, the starting point of the
constant lookup is always the first item that we search, regardless of
the presence of any prepended modules.

[Bug #17887]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Before this commit, const_get with inherit=true and constant lookup
expressions searched the ancestors of the starting point in an order
different from `starting_point.ancestors`.

Items in the ancestry list introduced through prepend were searched
after searching the module they were prepended into. This oddity allowed
for situations where constant lookups gave different results even though
`starting_point.ancestors` is the same.

Do the lookup in the same order as `starting_point.ancestors` by
skipping classes and modules that have an origin iclass. The origin
iclass is in the super chain after the prepended modules.

Note that just like before this commit, the starting point of the
constant lookup is always the first item that we search, regardless of
the presence of any prepended modules.

[Bug #17887]
</pre>
</div>
</content>
</entry>
<entry>
<title>Get rid of pointer casting</title>
<updated>2021-06-23T01:55:23+00:00</updated>
<author>
<name>Nobuyoshi Nakada</name>
<email>nobu@ruby-lang.org</email>
</author>
<published>2021-06-23T01:50:09+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=def7b3ee091781c61e8a30d1b63949dfe3654b51'/>
<id>def7b3ee091781c61e8a30d1b63949dfe3654b51</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Refactor class variable cache functions</title>
<updated>2021-06-23T01:55:22+00:00</updated>
<author>
<name>Nobuyoshi Nakada</name>
<email>nobu@ruby-lang.org</email>
</author>
<published>2021-06-23T00:39:04+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=0700ee0e946ff278699eb9aa068e7abbc3700dda'/>
<id>0700ee0e946ff278699eb9aa068e7abbc3700dda</id>
<content type='text'>
Extracted repeated code as update_classvariable_cache.  When cvc
table is not set in getclassvariable, an empty table was created
but it has no id and would cause [BUG], so made the code same as
setclassvariable.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Extracted repeated code as update_classvariable_cache.  When cvc
table is not set in getclassvariable, an empty table was created
but it has no id and would cause [BUG], so made the code same as
setclassvariable.
</pre>
</div>
</content>
</entry>
<entry>
<title>Add a cache for class variables</title>
<updated>2021-06-18T17:02:44+00:00</updated>
<author>
<name>eileencodes</name>
<email>eileencodes@gmail.com</email>
</author>
<published>2021-06-01T17:34:06+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/ruby.git/commit/?id=b91b3bc7717a97f4f1cdf6131b1688e1958dcfed'/>
<id>b91b3bc7717a97f4f1cdf6131b1688e1958dcfed</id>
<content type='text'>
Redo of 34a2acdac788602c14bf05fb616215187badd504 and
931138b00696419945dc03e10f033b1f53cd50f3 which were reverted.

GitHub PR #4340.

This change implements a cache for class variables. Previously there was
no cache for cvars. Cvar access is slow due to needing to travel all the
way up th ancestor tree before returning the cvar value. The deeper the
ancestor tree the slower cvar access will be.

The benefits of the cache are more visible with a higher number of
included modules due to the way Ruby looks up class variables. The
benchmark here includes 26 modules and shows with the cache, this branch
is 6.5x faster when accessing class variables.

```
compare-ruby: ruby 3.1.0dev (2021-03-15T06:22:34Z master 9e5105c) [x86_64-darwin19]
built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be009) [x86_64-darwin19]

|         |compare-ruby|built-ruby|
|:--------|-----------:|---------:|
|vm_cvar  |      5.681M|   36.980M|
|         |           -|     6.51x|
```

Benchmark.ips calling `ActiveRecord::Base.logger` from within a Rails
application. ActiveRecord::Base.logger has 71 ancestors. The more
ancestors a tree has, the more clear the speed increase. IE if Base had
only one ancestor we'd see no improvement. This benchmark is run on a
vanilla Rails application.

Benchmark code:

```ruby
require "benchmark/ips"
require_relative "config/environment"

Benchmark.ips do |x|
  x.report "logger" do
    ActiveRecord::Base.logger
  end
end
```

Ruby 3.0 master / Rails 6.1:

```
Warming up --------------------------------------
              logger   155.251k i/100ms
Calculating -------------------------------------
```

Ruby 3.0 with cvar cache /  Rails 6.1:

```
Warming up --------------------------------------
              logger     1.546M i/100ms
Calculating -------------------------------------
              logger     14.857M (± 4.8%) i/s -     74.198M in   5.006202s
```

Lastly we ran a benchmark to demonstate the difference between master
and our cache when the number of modules increases. This benchmark
measures 1 ancestor, 30 ancestors, and 100 ancestors.

Ruby 3.0 master:

```
Warming up --------------------------------------
            1 module     1.231M i/100ms
          30 modules   432.020k i/100ms
         100 modules   145.399k i/100ms
Calculating -------------------------------------
            1 module     12.210M (± 2.1%) i/s -     61.553M in   5.043400s
          30 modules      4.354M (± 2.7%) i/s -     22.033M in   5.063839s
         100 modules      1.434M (± 2.9%) i/s -      7.270M in   5.072531s

Comparison:
            1 module: 12209958.3 i/s
          30 modules:  4354217.8 i/s - 2.80x  (± 0.00) slower
         100 modules:  1434447.3 i/s - 8.51x  (± 0.00) slower
```

Ruby 3.0 with cvar cache:

```
Warming up --------------------------------------
            1 module     1.641M i/100ms
          30 modules     1.655M i/100ms
         100 modules     1.620M i/100ms
Calculating -------------------------------------
            1 module     16.279M (± 3.8%) i/s -     82.038M in   5.046923s
          30 modules     15.891M (± 3.9%) i/s -     79.459M in   5.007958s
         100 modules     16.087M (± 3.6%) i/s -     81.005M in   5.041931s

Comparison:
            1 module: 16279458.0 i/s
         100 modules: 16087484.6 i/s - same-ish: difference falls within error
          30 modules: 15891406.2 i/s - same-ish: difference falls within error
```

Co-authored-by: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Redo of 34a2acdac788602c14bf05fb616215187badd504 and
931138b00696419945dc03e10f033b1f53cd50f3 which were reverted.

GitHub PR #4340.

This change implements a cache for class variables. Previously there was
no cache for cvars. Cvar access is slow due to needing to travel all the
way up th ancestor tree before returning the cvar value. The deeper the
ancestor tree the slower cvar access will be.

The benefits of the cache are more visible with a higher number of
included modules due to the way Ruby looks up class variables. The
benchmark here includes 26 modules and shows with the cache, this branch
is 6.5x faster when accessing class variables.

```
compare-ruby: ruby 3.1.0dev (2021-03-15T06:22:34Z master 9e5105c) [x86_64-darwin19]
built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be009) [x86_64-darwin19]

|         |compare-ruby|built-ruby|
|:--------|-----------:|---------:|
|vm_cvar  |      5.681M|   36.980M|
|         |           -|     6.51x|
```

Benchmark.ips calling `ActiveRecord::Base.logger` from within a Rails
application. ActiveRecord::Base.logger has 71 ancestors. The more
ancestors a tree has, the more clear the speed increase. IE if Base had
only one ancestor we'd see no improvement. This benchmark is run on a
vanilla Rails application.

Benchmark code:

```ruby
require "benchmark/ips"
require_relative "config/environment"

Benchmark.ips do |x|
  x.report "logger" do
    ActiveRecord::Base.logger
  end
end
```

Ruby 3.0 master / Rails 6.1:

```
Warming up --------------------------------------
              logger   155.251k i/100ms
Calculating -------------------------------------
```

Ruby 3.0 with cvar cache /  Rails 6.1:

```
Warming up --------------------------------------
              logger     1.546M i/100ms
Calculating -------------------------------------
              logger     14.857M (± 4.8%) i/s -     74.198M in   5.006202s
```

Lastly we ran a benchmark to demonstate the difference between master
and our cache when the number of modules increases. This benchmark
measures 1 ancestor, 30 ancestors, and 100 ancestors.

Ruby 3.0 master:

```
Warming up --------------------------------------
            1 module     1.231M i/100ms
          30 modules   432.020k i/100ms
         100 modules   145.399k i/100ms
Calculating -------------------------------------
            1 module     12.210M (± 2.1%) i/s -     61.553M in   5.043400s
          30 modules      4.354M (± 2.7%) i/s -     22.033M in   5.063839s
         100 modules      1.434M (± 2.9%) i/s -      7.270M in   5.072531s

Comparison:
            1 module: 12209958.3 i/s
          30 modules:  4354217.8 i/s - 2.80x  (± 0.00) slower
         100 modules:  1434447.3 i/s - 8.51x  (± 0.00) slower
```

Ruby 3.0 with cvar cache:

```
Warming up --------------------------------------
            1 module     1.641M i/100ms
          30 modules     1.655M i/100ms
         100 modules     1.620M i/100ms
Calculating -------------------------------------
            1 module     16.279M (± 3.8%) i/s -     82.038M in   5.046923s
          30 modules     15.891M (± 3.9%) i/s -     79.459M in   5.007958s
         100 modules     16.087M (± 3.6%) i/s -     81.005M in   5.041931s

Comparison:
            1 module: 16279458.0 i/s
         100 modules: 16087484.6 i/s - same-ish: difference falls within error
          30 modules: 15891406.2 i/s - same-ish: difference falls within error
```

Co-authored-by: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
</feed>
