Skip to content
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

A few frozen string and symbol optimizations #8177

Merged
merged 7 commits into from Apr 2, 2024

Conversation

headius
Copy link
Member

@headius headius commented Mar 30, 2024

This cleans up some object flags in order to start flagging fstrings as such and use that to cache any symbol they might intern.

Other flags needed to be shifted, which I was afraid of before but
now I have no fear.
@headius headius added this to the JRuby 10.0.0.0 milestone Mar 30, 2024
@headius
Copy link
Member Author

headius commented Mar 30, 2024

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.

Copy link
Member

@enebo enebo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need a comment about how the CR values cannot change.

core/src/main/java/org/jruby/util/StringSupport.java Outdated Show resolved Hide resolved
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.
@headius
Copy link
Member Author

headius commented Apr 2, 2024

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.

@headius headius merged commit d72301c into jruby:9.5-dev Apr 2, 2024
45 of 60 checks passed
@headius headius deleted the fstring_opt branch April 2, 2024 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants