Skip to content

Commit 0560ef5

Browse files
authored
Merge pull request #1715 from fsprojects/repo-assist/perf-json-parsestring-bulk-append-ba53211cf351c3f2
[Repo Assist] perf: bulk-append unescaped character runs in JSON string parser
2 parents 6d65d9c + 79b081a commit 0560ef5

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

RELEASE_NOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release Notes
22

3+
## 8.1.4 - Mar 30 2026
4+
5+
- Performance: `JsonValue.Parse` now copies unescaped string runs in bulk instead of appending character-by-character, reducing `StringBuilder.Append` calls for strings with few or no escape sequences
6+
37
## 8.1.3 - Mar 23 2026
48

59
- Fix JSON `/* ... */` comment parser: `*` or `/` characters inside the comment body no longer cause premature termination and parse failure

src/FSharp.Data.Json.Core/JsonValue.fs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,18 @@ type private JsonParser(jsonText: string) =
315315
ensure (i < s.Length && s.[i] = '"')
316316
i <- i + 1
317317

318+
// Track start of current unescaped run; flush as a bulk chunk when an escape or end is hit.
319+
// This avoids per-character StringBuilder.Append calls for strings with few/no escapes,
320+
// which is the common case in real-world JSON.
321+
let mutable chunkStart = i
322+
323+
let inline flushChunk upTo =
324+
if upTo > chunkStart then
325+
buf.Append(s, chunkStart, upTo - chunkStart) |> ignore
326+
318327
while i < s.Length && s.[i] <> '"' do
319328
if s.[i] = '\\' then
329+
flushChunk i
320330
ensure (i + 1 < s.Length)
321331

322332
match s.[i + 1] with
@@ -371,10 +381,12 @@ type private JsonParser(jsonText: string) =
371381
| _ -> throw ()
372382

373383
i <- i + 2 // skip past \ and next char
384+
chunkStart <- i
374385
else
375-
buf.Append(s.[i]) |> ignore
376386
i <- i + 1
377387

388+
// Flush any remaining unescaped characters
389+
flushChunk i
378390
ensure (i < s.Length && s.[i] = '"')
379391
i <- i + 1
380392
let str = buf.ToString()

0 commit comments

Comments
 (0)