Skip to content

Commit c17a355

Browse files
planetis-mnarimiran
authored andcommitted
Scan until next special char (", \, \0, \c, \L) and append that slice once. (#25498)
Benchmark comparison (-d:danger --mm:arc --debugger:native -d:useMalloc, OpenAI file benchmark, 5 runs): - Before: 0.196674934, 0.189423191, 0.198763300, 0.197125584, 0.205015032 - After: 0.182827130, 0.183330852, 0.174878542, 0.174360811, 0.181704921 - Median before: 0.197125584s - Median after: 0.181704921s - Improvement: 7.82% faster Callgrind comparison (same build flags): - Total Ir before: 3,219,477,120 - Total Ir after: 2,449,556,167 - Total Ir reduction: 23.91% parseString hotspot: - Before: 1,343,343,723 Ir - After: 573,423,735 Ir - Reduction: 57.31% (cherry picked from commit f4dd00c)
1 parent d6f60ce commit c17a355

1 file changed

Lines changed: 31 additions & 2 deletions

File tree

lib/pure/parsejson.nim

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,23 +175,48 @@ proc parseEscapedUTF16*(buf: cstring, pos: var int): int =
175175
else:
176176
return -1
177177

178+
proc addSpan(dst: var string; src: string; startPos, endPos: int) {.inline.} =
179+
let n = endPos - startPos
180+
if n <= 0:
181+
return
182+
183+
let old = dst.len
184+
dst.setLen old + n
185+
186+
template impl =
187+
for i in 0..<n:
188+
dst[old + i] = src[startPos + i]
189+
190+
when nimvm:
191+
impl
192+
else:
193+
when defined(js) or defined(nimscript):
194+
impl
195+
else:
196+
{.noSideEffect.}:
197+
copyMem dst[old].addr, src[startPos].unsafeAddr, n
198+
178199
proc parseString(my: var JsonParser): TokKind =
179200
result = tkString
180201
var pos = my.bufpos + 1
202+
var spanStart = pos
181203
if my.rawStringLiterals:
182204
add(my.a, '"')
183205
while true:
184206
case my.buf[pos]
185207
of '\0':
186-
my.err = errQuoteExpected
208+
my.err = errInvalidToken
209+
addSpan(my.a, my.buf, spanStart, pos)
187210
result = tkError
188211
break
189212
of '"':
213+
addSpan(my.a, my.buf, spanStart, pos)
190214
if my.rawStringLiterals:
191215
add(my.a, '"')
192216
inc(pos)
193217
break
194218
of '\\':
219+
addSpan(my.a, my.buf, spanStart, pos)
195220
if my.rawStringLiterals:
196221
add(my.a, '\\')
197222
case my.buf[pos+1]
@@ -251,14 +276,18 @@ proc parseString(my: var JsonParser): TokKind =
251276
# don't bother with the error
252277
add(my.a, my.buf[pos])
253278
inc(pos)
279+
spanStart = pos
254280
of '\c':
281+
addSpan(my.a, my.buf, spanStart, pos)
255282
pos = lexbase.handleCR(my, pos)
256283
add(my.a, '\c')
284+
spanStart = pos
257285
of '\L':
286+
addSpan(my.a, my.buf, spanStart, pos)
258287
pos = lexbase.handleLF(my, pos)
259288
add(my.a, '\L')
289+
spanStart = pos
260290
else:
261-
add(my.a, my.buf[pos])
262291
inc(pos)
263292
my.bufpos = pos # store back
264293

0 commit comments

Comments
 (0)