Age | Commit message (Collapse) | Author |
|
Previously when checking ancestors, we would walk all the way up the
ancestry chain checking each parent for a matching class or module.
I believe this was especially unfriendly to CPU cache since for each
step we need to check two cache lines (the class and class ext).
This check is used quite often in:
* case statements
* rescue statements
* Calling protected methods
* Class#is_a?
* Module#===
* Module#<=>
I believe it's most common to check a class against a parent class, to
this commit aims to improve that (unfortunately does not help checking
for an included Module).
This is done by storing on each class the number and an array of all
parent classes, in order (BasicObject is at index 0). Using this we can
check whether a class is a subclass of another in constant time since we
know the location to expect it in the hierarchy.
Notes:
Merged: https://github.com/ruby/ruby/pull/5568
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5576
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5455
|
|
On 32-bit systems, VWA causes class_serial to not be aligned (it only
guarantees 4 byte alignment but class_serial is 8 bytes and requires 8
byte alignment). This commit uses a hack to allocate class_serial
through malloc. Once VWA allocates with 8 byte alignment in the future,
we will revert this commit.
Notes:
Merged: https://github.com/ruby/ruby/pull/5442
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5398
|
|
This is to allow Module subclasses that include modules before
calling super in the subclass's initialize.
Remove rb_module_check_initializable from Module#initialize.
Module#initialize only calls module_exec if a block is passed,
it doesn't have other issues that would cause problems if
called multiple times or with an already initialized module.
Move initialization of super to Module#allocate, though I'm not
sure it is required there. However, it's needed to be removed
from Module#initialize for this to work.
Fixes [Bug #18292]
Notes:
Merged: https://github.com/ruby/ruby/pull/5398
|
|
RMODULE_SUPER is initialized to 0, as the uninitialized module
flag is used since b929af430c39df6597d2f3f53b82c38b1d76217b.
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5272
|
|
I don't have a display enough for 170 columns, and it is hard to
use small fonts for my eyes. :(
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5309
|
|
This commit adds a Ractor cache for every size pool. Previously, all VWA
allocated objects used the slowpath and locked the VM.
On a micro-benchmark that benchmarks String allocation:
VWA turned off:
29.196591 0.889709 30.086300 ( 9.434059)
VWA before this commit:
29.279486 41.477869 70.757355 ( 12.527379)
VWA after this commit:
16.782903 0.557117 17.340020 ( 4.255603)
Notes:
Merged: https://github.com/ruby/ruby/pull/5151
|
|
Implements [Feature #18273]
Returns an array containing the receiver's direct subclasses without
singleton classes.
Notes:
Merged: https://github.com/ruby/ruby/pull/5045
|
|
Updating RCLASS_PARENT_SUBCLASSES and RCLASS_MODULE_SUBCLASSES while
compacting can trigger the read barrier. This commit makes
RCLASS_SUBCLASSES a doubly linked list with a dedicated head object so
that we can add and remove entries from the list without having to touch
an object in the Ruby heap
Notes:
Merged: https://github.com/ruby/ruby/pull/5125
|
|
With RVARGC we always store the rb_classext_t in the same slot as the
RClass struct that refers to it. So we don't need to store the pointer
or access through the pointer anymore and can switch the RCLASS_EXT
macro to use an offset
Notes:
Merged: https://github.com/ruby/ruby/pull/5101
|
|
... to allow class.c to use the function
Notes:
Merged: https://github.com/ruby/ruby/pull/5097
|
|
Follow up of 428227472fc6563046d8138aab17f07bef6af753. The previous fix
uses `rb_ary_new_from_values` to create the result array, but it may
trigger the GC.
This second try is to create the result array by `rb_ary_new_capa`
before the second iteration, and assume that `rb_ary_push` does not
trigger GC. This assumption is very fragile, so should be improved in
future.
[Bug #18282] [Feature #14394]
Notes:
Merged: https://github.com/ruby/ruby/pull/5097
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5070
|
|
It is theoretically possible if a finalizer creates a subclass.
Notes:
Merged: https://github.com/ruby/ruby/pull/5070
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5070
|
|
GC must not be triggered during callback of rb_class_foreach_subclass.
To prevent GC, we can not use rb_ary_push. Instead, this changeset calls
rb_class_foreach_subclass twice: first counts the subclasses, then
allocates a buffer (which may cause GC and reduce subclasses, but not
increase), and finally stores the subclasses to the buffer.
[Bug #18282] [Feature #14394]
Notes:
Merged: https://github.com/ruby/ruby/pull/5070
|
|
Doesn't include receiver or singleton classes.
Implements [Feature #14394]
Co-authored-by: fatkodima <[email protected]>
Co-authored-by: Benoit Daloze <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/4974
Merged-By: jeremyevans <[email protected]>
|
|
Otherwise, singleton methods of Module are not inherited unless
Refinement.singleton_class is called.
|
|
The allocation functions no longer assume that one RVALUE needs to be
allocated.
Notes:
Merged: https://github.com/ruby/ruby/pull/4933
|
|
instead
Refinement#import_methods imports methods from modules.
Unlike Module#include, it copies methods and adds them into the refinement,
so the refinement is activated in the imported methods.
[Bug #17429] [ruby-core:101639]
|
|
Make `Module#ancestors` not to include `BasicObject`.
Notes:
Merged: https://github.com/ruby/ruby/pull/4883
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4883
|
|
The module that is about to be included is considered initialized.
Notes:
Merged: https://github.com/ruby/ruby/pull/4868
|
|
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4858
|
|
Must not be a bad idea to improve documents. [ci skip]
Notes:
Merged: https://github.com/ruby/ruby/pull/4815
|
|
Must not be a bad idea to improve documents. [ci skip]
In fact many functions declared in the header file are already
documented more or less. They were just copy & pasted, with applying
some style updates.
Notes:
Merged: https://github.com/ruby/ruby/pull/4815
|
|
Must not be a bad idea to improve documents. [ci skip]
In fact many functions declared in the header file are already
documented more or less. They were just copy & pasted, with applying
some style updates.
Notes:
Merged: https://github.com/ruby/ruby/pull/4815
|
|
Must not be a bad idea to improve documents. [ci skip]
Notes:
Merged: https://github.com/ruby/ruby/pull/4815
|
|
Any defined methods, bound to any classes/modules and not being
UNDEFINED_METHOD_ENTRY_P, should not be METHOD_VISI_UNDEF.
|
|
This commits implements size classes in the GC for the Variable Width
Allocation feature. Unless `USE_RVARGC` compile flag is set, only a
single size class is created, maintaining current behaviour. See the
redmine ticket for more details.
Co-authored-by: Aaron Patterson <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/4773
|
|
This reverts commits 48ff7a9f3e47bffb3e4d067a12ba9b936261caa0
and b2e2cf2dedd104acad8610721db5e4d341f135ef because it is causing
crashes in SPARC solaris and i386 debian.
Notes:
Merged: https://github.com/ruby/ruby/pull/4764
|
|
This commits implements size classes in the GC for the Variable Width
Allocation feature. Unless `USE_RVARGC` compile flag is set, only a
single size class is created, maintaining current behaviour. See the
redmine ticket for more details.
Co-authored-by: Aaron Patterson <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/4680
|
|
|
|
[ruby-core:86949] [Bug #14744]
Reported by Eregon (Benoit Daloze). Thanks!
|
|
|
|
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 <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/4544
|
|
This reverts commit 08de37f9fa3469365e6b5c964689ae2bae0eb9f3.
This reverts commit e8ae922b62adb00a80d3d4c49f7d7b0e6026eaba.
|
|
Instead of on read. Once it's in the inline cache we never have to make
one again. We want to eventually put the value into the cache, and the
best opportunity to do that is when you write the value.
Notes:
Merged: https://github.com/ruby/ruby/pull/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 9e5105ca45) [x86_64-darwin19]
built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be0093ae) [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 <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/4340
|
|
To invalidate some callable method entries, we replace the entry in the
class. Most types of method entries are on the method table of the
origin class, but refinement entries without an orig_me are housed in
the method table of the class itself. They are there because refinements
take priority over prepended methods.
By unconditionally inserting a copy of the refinement entry into the
origin class, clearing the method cache created situations where there
are refinement entry duplicates in the lookup chain, leading to infinite
loops and other problems.
Update the replacement logic to use the right class that houses the
method entry. Also, be more selective about cache invalidation when
moving refinement entries for prepend. This avoids calling
clear_method_cache_by_id_in_class() before refinement entries are in the
place it expects.
[Bug #17806]
Notes:
Merged: https://github.com/ruby/ruby/pull/4386
Merged-By: XrXr
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4391
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4269
Merged-By: nobu <[email protected]>
|
|
In every caller of `rb_class_ivar_set` it checks for the `RCLASS_IV_TBL`
and then creates it if it doesn't exist. Instead of repeating this in
every caller, this can be done once in `rb_class_ivar_set`.
Notes:
Merged: https://github.com/ruby/ruby/pull/4254
|
|
It's important to only make the origin when the prepend goes
through, as the precense of the origin informs whether to do an
origin backfill.
This plus 2d877327e fix [Bug #17590].
Notes:
Merged: https://github.com/ruby/ruby/pull/4181
|
|
Check for cyclic prepend before making any changes. This requires
scanning the module ancestor chain twice, but in general modules
do not have large numbers of ancestors.
Notes:
Merged: https://github.com/ruby/ruby/pull/4165
|