perf: speed up direct long rendering#1087
Open
He-Pin wants to merge 1 commit into
Open
Conversation
a06130e to
5031f7e
Compare
Motivation: Direct long rendering already used scratch buffers and digit-pair lookup tables, but it still looped over /100 for every two digits. The TOML exact-long path also allocated an intermediate String and used a math.round guard that saturated integer doubles above Long.MaxValue. Modification: Introduce a shared FastLongRenderer that writes ASCII long digits with jsoniter-style 1e8/1e16 Math.multiplyHigh chunking plus jeaiii-style digit extraction for int-sized chunks. Wire BaseByteRenderer and BaseCharRenderer through the shared helper, keep TOML exact Long values on StringBuilder.append(Long), and fall back to RenderUtils.renderDouble for non-Long doubles. Result: Char and byte renderers now share one long-rendering implementation with boundary/random regression coverage. JVM, JS, WASM, and Native renderer tests pass for the Math.multiplyHigh path. Local JMH shows byte long rendering 1.22x faster and TOML exact-long rendering 1.92x faster, while char long rendering remains effectively flat.
5031f7e to
2965767
Compare
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.
Motivation
Direct long rendering in sjsonnet was already fairly optimized: it used scratch buffers and digit-pair lookup tables instead of repeatedly allocating
Strings on the hot renderer paths. The remaining cost was the/100loop for every two digits, plus TOML exact-long doubles still went through an intermediate string path and used amath.roundguard that saturates nearLong.MaxValue.This uses the jeaiii integer-formatting idea and jsoniter-scala v2.38.17 as references, but applies them conservatively for sjsonnet: the blog-style
1441151881/100reciprocal is only safe in a bounded range, so the fullLongpath uses jsoniter-styleMath.multiplyHighchunking by1e8/1e16, then digit-pair extraction for int-sized chunks.References:
Modification
FastLongRendererfor ASCIILongrendering.BaseByteRendererandBaseCharRendererthrough that shared helper.StringBuilder.append(Long)and fall back toRenderUtils.renderDoublefor non-exact Long values, avoiding the previousmath.round(...).toLongsaturation case.Result
The PR is squashed to one commit on top of
databricks/master. The shared code lives undersjsonnet/src, so the optimization is used by JVM, Scala.js, Scala Native, and WASM builds. Local checks covered formatting, JVM tests, compile coverage across JVM/JS/WASM/Native, and renderer tests on JS/WASM/Native.JMH command:
./mill bench.runJmh ".*LongRenderingBenchmark.*" -f 1 -wi 5 -i 8 -r 1s -w 1sLocal JMH on JDK 21, Apple Silicon, lower is better:
baseByteRendererLongsbaseCharRendererLongstomlRendererExactLongDoublesThe smaller char-renderer win is expected: the existing char path was already optimized with a scratch buffer and digit-pair tables, so most of the new gain comes from removing repeated division and sharing the full-Long chunking logic.