-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Use a BOP for Hash#default #6945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This does seem to improve Railsbench a little bit. There are no real changes to YJIT here (just bindgen updates) but it should improve its performance by the same as the interpreter because it also just calls Before
After
|
nitpick: It seems more easier to understand the difference this PR is making if you compare before/after between interpreters and YJITs, not interp/yjit. You could do it like:
If you intentionally do it that way to avoid having multiple build directories, it's okay too :) But I just wanted to make sure you're aware. |
I should do that 😅. When I'm testing just for myself I tend to run the comparison Ruby directly from the source tree, but that has also caused me to make mistakes. |
0b0ee01
to
ff0336a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
On a hash miss we need to call default if it is redefined in order to return the default value to be used. Previously we checked this with rb_method_basic_definition_p, which avoids the method call but requires a method lookup. This commit replaces the previous check with BASIC_OP_UNREDEFINED_P and a new BOP_DEFAULT. We still need to fall back to rb_method_basic_definition_p when called on a subclasss of hash. | |compare-ruby|built-ruby| |:---------------|-----------:|---------:| |hash_aref_miss | 2.692| 3.531| | | -| 1.31x| Co-authored-by: Daniel Colson <danieljamescolson@gmail.com> Co-authored-by: "Ian C. Anderson" <ian@iancanderson.com> Co-authored-by: Jack McCracken <me@jackmc.xyz>
We should always have a T_HASH here, so we can use FL_TEST_RAW to avoid checking whether we may have an immediate value. I expect this to be a very small performance improvement (perf stat ./miniruby benchmark/hash_aref_miss.rb shows a ~1% improvement). It also removes 9 instructions from rb_hash_default_value on x86_64.
ff0336a
to
bf6099b
Compare
Since #6945 the extension dir changed to Gem::BasicSpecification's implementation, we didn't hook that in rubygems_ext.rb. So for universal rubies, we ended up using the universal platform name when installing, but arch replaced platform name when checking. This lead to native extensions can never be correctly installed on universal rubies. Hook Gem::BasicSpecifications so the behavior is consistent on installing and checking. rubygems/rubygems@8d699ed096
On a hash miss we need to call default if it is redefined in order to return the default value to be used. Previously we checked this with rb_method_basic_definition_p, which avoids the method call but requires a method lookup.
This commit replaces the previous check with BASIC_OP_UNREDEFINED_P and a new BOP_DEFAULT. We still need to fall back to rb_method_basic_definition_p when called on a subclass of hash.
On railsbench, before this change I measured how many times we call
rb_method_basic_definition_p
and with what IDs. For 5 iterations:before: 5086076
after: 716854
So this is optimizing ~95% of the checks. Rails does include some subclasses of Hash (ex. HashWithIndifferentAccess), which is why it isn't 100%.
default
was by far the ID most passed to rb_method_basic_definition_p, second wasto_proc
with 273898 calls.