Bug #20338
closedcertain **kwsplat calls have regressed allocations over past few ruby releases
Description
Given this script:
class Foo
def initialize(**kwargs)
end
end
class Bar
def initialize(y:)
end
end
b = GC.stat[:total_allocated_objects]
1000.times {
Foo.new(y:1)
}
p GC.stat[:total_allocated_objects]-b
b = GC.stat[:total_allocated_objects]
1000.times {
Bar.new(y:1)
}
p GC.stat[:total_allocated_objects]-b
On Ruby 3.2 it prints
(fable-3_3_dead_with_patches) $ ruby --version
ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [arm64-darwin23]
(fable-3_3_dead_with_patches) $ ruby hi.rb
3006
2005
On Ruby 3.3 it prints:
((HEAD detached at v3_3_0)) $ ./ruby --version
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
((HEAD detached at v3_3_0)) $ ./ruby hi.rb
3008
3005
On master:
(master) $ git rev-parse HEAD
83618f2cfa004accdd1514de7dcbba291aa7e831
(master) $ ./ruby --version
ruby 3.4.0dev (2024-03-14T12:33:30Z master 83618f2cfa) [arm64-darwin23]
(master) $ ./ruby hi.rb
3006
4005
so that is: since Ruby 3.2 .new
ing an object with static keyword args has grown from 2 allocations per object to 4 allocations per object.
I have a pull request which introduces a new instruction to the VM opt_new
which basically inlines calling allocate and initialize directly, avoiding a lot of what is causing these extra objects to be allocated. My PR is here: https://github.com/ruby/ruby/pull/10254. With my patch the script prints 2006 and 1005 respectively. This is the smallest number of objects that can be allocated for such calls.
Updated by kjtsanaktsidis (KJ Tsanaktsidis) 11 months ago
I haven’t looked at this at all myself, but it tingled my “this is familiar” sense. Is this the same problem as https://github.com/ruby/ruby/pull/10151 ?
Updated by kjtsanaktsidis (KJ Tsanaktsidis) 11 months ago
Ah nope never mind, that PR is about methods called with a kwarg splat, which your example is not doing.
Updated by alanwu (Alan Wu) 11 months ago
- Subject changed from calling new has regressed allocations over past few ruby releases to certain **kwsplat calls have regressed allocations over past few ruby releases
- Status changed from Open to Closed
After aceee71c35e0b387691836e756b4e008efd84cf1 and 15dc3aaa311b32203d8ffb414bcf9b8e55ce5691, it's now back down to 3.2 levels on the master branch:
$ ./miniruby -v test.rb
ruby 3.4.0dev (2024-03-21T17:20:32Z master 15dc3aaa31) [arm64-darwin23]
3006
2005
The extra allocations were general issues with kwsplat calls which Class#new
uses internally.