You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by "Ben Weidig (Jira)" <ji...@apache.org> on 2026/07/26 07:35:00 UTC

[jira] [Created] (TAP5-2837) Improve JSON serialization performance (toString/toCompactString)

Ben Weidig created TAP5-2837:
--------------------------------

             Summary: Improve JSON serialization performance (toString/toCompactString)
                 Key: TAP5-2837
                 URL: https://issues.apache.org/jira/browse/TAP5-2837
             Project: Tapestry 5
          Issue Type: Improvement
          Components: tapestry-json
    Affects Versions: 5.10.0
            Reporter: Ben Weidig


h3. 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.

h3. Problem

* {{toString()}}/{{toCompactString()}} route output through {{CharArrayWriter}} wrapped in {{PrintWriter}}, both use {{synchronized}} methods on every write. This is pure overhead for single-threaded string building.
* {{JSONObject.quote(String)}} allocates a new {{JSONStringer}} (own {{StringBuilder}} + {{ArrayList}} scope stack) for every quoted string, like keys and string values in a payload.
* Extended-Unicode escaping goes through {{String.format}}, which parses the format string on every call.
* Output buffers start at JDK default capacity with no pre-sizing, causing repeated grow/copy for larger trees.

h3. Proposed changes

Delete {{JSONStringer}} and inline its escaping loop directly into {{JSONObject}} as a static {{escapeInto(...)}} helper, called directly by {{quote()}} and the print sessions.

Replace {{String.format}} hex escaping with manual nibble extraction + lookup table.

Drop {{CharArrayWriter}}/{{PrintWriter}} for {{toString()}}/{{toCompactString()}}.
Instead, build directly into a {{StringBuilder}}.

Pre-size the output buffer based on collection size instead of the JDK default.

All changes are additive/internal/package-private only, without any no signature changes, no behavior changes.
Full test suite plus a new baseline-equivalence test confirmed identical output to 5.9.1 in my sandbox.

h3. Risks

* Low functional risk: escaping logic is a straight extraction/refactor, covered by existing tests.
* Removing {{JSONStringer}} is a *breaking change* for any external caller referencing that class directly (it's currently public): Needs a compatibility/deprecation decision before merge.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)