Optimize Float#to_s with Ryu algorithm to achieve 2-4x performance #15627
+953
−1
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 PR integrates the Ryu algorithm for float-to-string conversion, replacing Ruby's current dtoa implementation (David M. Gay's algorithm from 1991) with a modern, faster approach.
Key improvements:
Background
The Ryu algorithm (2018, Ulf Adams) uses precomputed 128-bit multiplication tables to achieve O(1) shortest-representation conversion. It has been adopted by:
Reference paper: "Ryū: Fast Float-to-String Conversion" (PLDI 2018)
Benchmark Results
Comparison against unmodified Ruby master (same commit) with 2,000,000 iterations:
Fast Path for Exact Integers
The implementation includes a fast path that detects exact integers in the range [1, 10^15) and converts them directly without invoking the full Ryu algorithm. This ensures no performance regression for common cases like
1e10.to_swhile still providing massive speedups for decimal and scientific notation values.Technical Notes
__uint128_ton platforms that support it, falls back to portable 64-bit multiplication otherwise-DRYU_OPTIMIZE_SIZE)ruby_ryu_dtoa()returns a malloc'd string (same asruby_dtoa()), caller freesWho Benefits
Any Ruby code that converts floats to strings:
JSON.generate,to_json)puts,p,inspect)"Value: #{float}")Note
I am not familiar with the contribution patterns to Ruby core. Please let me know if any changes are needed to align with the project's coding standards or if additional tests are required.
Note 2
I did not remove
dtoa.ccompletely because its used in few other places. If this PR is something that could potentially be accepted I can do sprintf and marshal next.