A few frozen string and symbol optimizations#8177
Merged
headius merged 7 commits intojruby:9.5-devfrom Apr 2, 2024
Merged
Conversation
Other flags needed to be shifted, which I was afraid of before but now I have no fear.
Member
Author
|
This seemed like a great idea until I realized you can't add new internal variables to a frozen object (or even update them if they have been allocated already). Still feels like there's some value in having fstrings cache common products like symbols and regexp. |
enebo
reviewed
Apr 1, 2024
Member
enebo
left a comment
There was a problem hiding this comment.
We probably need a comment about how the CR values cannot change.
These values are originally from CRuby, and now hardcoded as part of the Prism parser, so they must continue to have the same values or it will break codranges coming out of Prism. This also makes the value check a hard check rather than an assert since that will help ensure they do not accidentally get changed.
This improves the performance of Integer#to_s for this range of values by a good 50%, based on the attached benchmark.
An FString is a frozen string that has additionally been de-
duplicated and cached. Since such strings are often later
converted to symbols, integers, or floats, the FString class adds
fields to lazily cache those converted values. This helps, for
example, when using APIs that can take either strings or symbols
but need a symbol internally; if the incoming string is an FString
the symbol created from it will be cached and more readily
accessible.
Performance of FString conversions is many times faster with this
change at the cost of all FStrings having three additional
reference fields.
Warming up --------------------------------------
intern normal 6.203M i/100ms
intern fstring 25.811M i/100ms
to_i normal 9.876M i/100ms
to_i fstring 27.629M i/100ms
to_f normal 14.780M i/100ms
to_f fstring 27.612M i/100ms
Calculating -------------------------------------
intern normal 62.499M (± 0.5%) i/s - 316.353M in 5.061824s
intern fstring 274.520M (± 1.0%) i/s - 1.394B in 5.077736s
to_i normal 97.868M (± 1.3%) i/s - 493.824M in 5.046716s
to_i fstring 273.394M (± 1.3%) i/s - 1.381B in 5.053858s
to_f normal 146.627M (± 1.2%) i/s - 739.006M in 5.040805s
to_f fstring 271.105M (± 1.5%) i/s - 1.381B in 5.093658s
This helps cases where an fstring (born frozen and dedup'ed) is used in a symbol API where it must be interned. For example see the benchmark and discussion in jruby#3419.
Member
Author
|
The original FString idea has been implemented with a subclass of RubyString that aggregates lazy fields for symbol, integer, and float. Performance is greatly improved for cases that request those conversions from FStrings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This cleans up some object flags in order to start flagging fstrings as such and use that to cache any symbol they might intern.