Skip to content

TAP5-2837: Improve JSON serialization performance - #67

Open
benweidig wants to merge 1 commit into
masterfrom
TAP5-2837
Open

TAP5-2837: Improve JSON serialization performance#67
benweidig wants to merge 1 commit into
masterfrom
TAP5-2837

Conversation

@benweidig

Copy link
Copy Markdown
Contributor

Overview

JSONObject/JSONArray's toString() and toCompactString() are slower than necessary due to synchronization overhead and per-String allocation in the print path.

My sandbox implementation at https://github.com/benweidig/tapestry-json-improvements (non-breaking, verified byte-for-byte against current output) shows a ~4-6x speedup across payload sizes and both compact/pretty formatting, with no public API changes.

Changes

  • Deprecated JSONStringer and inlined its escaping loop directly into JSONObject. There is some code duplication, but it keeps the call sites monomorphic and should allow for better C2 optimization in the JVM.
  • Hex escaping is done with manual nibble extraction pls a lookup-table instead of String.format calls
  • Droped CharArrayWriter/PrintWriter and build directlty into StringBuilder
  • Pre-size output buffers

Results

Graphs: JMH Visalizer

End-to-end cost: JSONSerializationBenchmark (toString() / toCompactString())

Payload size compact: baseline (µs/op) compact: improved (µs/op) speedup pretty: baseline (µs/op) pretty: improved (µs/op) speedup
10 15.10 ± 0.34 3.57 ± 0.27 4.2× 33.30 ± 1.03 6.16 ± 0.07 5.4×
100 186.83 ± 22.62 33.14 ± 0.52 5.6× 349.52 ± 4.62 57.95 ± 0.38 6.0×
1000 1777.78 ± 34.98 388.31 ± 4.70 4.6× 3469.37 ± 120.15 629.63 ± 17.88 5.5×

Isolated escaping cost: StringQuotingBenchmark (JSONObject.quote(String))

Profile Baseline (ns/op) Improved (ns/op) Speedup
PLAIN_ASCII 175.74 81.08 2.2×
QUOTES_AND_SLASHES 168.55 82.93 2.0×
CONTROL_CHARS 182.26 80.45 2.3×
UNICODE_HEAVY 611.93 105.65 5.8×

@benweidig benweidig added this to the v5.10.0 milestone Jul 26, 2026
@benweidig
benweidig requested a review from thiagohp July 26, 2026 12:55
@benweidig benweidig self-assigned this Jul 26, 2026
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.

1 participant