perf: direct-to-stdout rendering, bypass StringWriter allocation#746
Closed
He-Pin wants to merge 1 commit intodatabricks:masterfrom
Closed
perf: direct-to-stdout rendering, bypass StringWriter allocation#746He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin wants to merge 1 commit intodatabricks:masterfrom
Conversation
f53560f to
a01dc4f
Compare
Eliminate the intermediate StringWriter/StringBuffer path when rendering to stdout. Previously, all CLI output was: Renderer → CharBuilder → StringWriter(StringBuffer) → .toString → println For large outputs (e.g. realistic_2 at 28.5MB), this created ~100MB of intermediate allocations: StringBuffer growth + String copy + encoding. Now renders directly to BufferedOutputStream wrapping stdout: Renderer → CharBuilder → OutputStreamWriter → BufferedOutputStream → stdout This is a single-pass streaming write with only a 64KB buffer. Upstream: jit branch commits b09647c (direct-write stdout concept)
a01dc4f to
902c214
Compare
Contributor
Author
|
Closing: functionality is fully subsumed by PR #745 (byte[] rendering pipeline), which includes the direct-to-stdout rendering from this PR plus additional optimizations (fused materializer, NativeOutputStream for Scala Native, SWAR escape scanning). |
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
When outputting to stdout (no
--output-file), sjsonnet renders JSON into aStringWriterbacked byStringBuffer, callstoString()to create the full output string, thenprintln()to encode and write it. For realistic2 (28.5MB JSON output), this creates ~100MB of intermediate allocations:Stringcopy of the char arrayTotal: 3 traversals of the full output data before it reaches stdout.
Key Design Decision
Stream directly to stdout via
BufferedOutputStream(64KB buffer) +OutputStreamWriter, eliminating all intermediate allocations:writeToFile(previously inmain0viaprintln)Supersedes #680 with a simpler approach: true streaming instead of buffering into
CompactByteArrayOutputStream.Modification
sjsonnet/src-jvm-native/sjsonnet/SjsonnetMainBase.scala:writeToFile: WhenoutputFileisNone, renders directly throughOutputStreamWriter→BufferedOutputStream(stdout, 65536)instead ofStringWriterprintlnbehavior)stdout: PrintStreamthroughmainConfigured→renderNormal→writeToFileBenchmark Results
Environment: Apple M3 Max, macOS 15.4
Scala Native — hyperfine (warmup 3, runs 10,
> /dev/null)JMH (JVM, ms/op, lower is better)
Analysis
References
b09647c0(direct-write stdout concept)Result
Streaming stdout rendering eliminates ~100MB intermediate allocations for large outputs. Improves realistic2 by 12.2% on native, with 17-29% improvements on other output-heavy benchmarks. Zero functional change.