Skip to content

Copy runs of unescaped characters in JSON.stringify - #1845

Open
Huy-Hieuu wants to merge 1 commit into
quickjs-ng:masterfrom
Huy-Hieuu:json-stringify-run-copy
Open

Huy-Hieuu wants to merge 1 commit into
quickjs-ng:masterfrom
Huy-Hieuu:json-stringify-run-copy

Conversation

@Huy-Hieuu

Copy link
Copy Markdown

JS_ToQuotedString (used for every string value and key JSON.stringify writes) reads and writes one character at a time (string_getc, a switch, string_buffer_putc). Most characters in a JSON string need no escape.

This scans the run of code units that need no escape (>= 0x20, not ", not \, and in a two-byte string not a surrogate) and appends it with a single string_buffer_write8/string_buffer_write16. The code unit that ends the run goes through the existing per-character path unchanged (escapes, \u00XX controls, surrogate pairs copied as is, lone surrogates as \udXXX), so the output is identical.

Measured on macOS arm64 (Release build, retired instructions per JSON.stringify call):

input before after
6 KB ASCII string 416 k 77 k
6 KB string with many ", \n, \\ 426 k 215 k
15.6 KB chat request object (long message strings) 1,831 k 949 k
20 Vietnamese chat messages (two-byte strings) 722 k 344 k

Test: test_json in tests/test_builtin.js now checks every code unit at the start, middle and end of a one-byte and a two-byte string, as a value and as a key, against QuoteJSONString written in plain JS. run-test262 -c tests.conf gives the same result as on master in Release and Debug (here the only failure is the existing test_std.js:254, which also fails without this change on macOS).

JS_ToQuotedString read and wrote one character at a time. Scan the run
of code units that need no escape and append it with one
string_buffer_write8/16; the code unit that ends the run takes the
existing per-character path. The output is unchanged.

On a 6 KB plain string this cuts the retired instructions of
JSON.stringify by 81%, and by about half on chat-shaped JSON bodies
(macOS arm64, Release build).

This branch has not been deployed

No deployments
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