Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Improve parseInt throughput for short numbers - #285

#285
Closed
trevorprater wants to merge 1 commit into
buger:masterbuger/jsonparser:masterfrom
trevorprater:codex/parseint-short-fast-pathtrevorprater/jsonparser:codex/parseint-short-fast-pathCopy head branch name to clipboard
Closed

Improve parseInt throughput for short numbers#285
trevorprater wants to merge 1 commit into
buger:masterbuger/jsonparser:masterfrom
trevorprater:codex/parseint-short-fast-pathtrevorprater/jsonparser:codex/parseint-short-fast-pathCopy head branch name to clipboard

Conversation

@trevorprater

Copy link
Copy Markdown

This adds a fast path for parseInt when the numeric portion is shorter than
19 decimal digits. In that case the value cannot overflow int64, so the loop
only needs to validate digits and accumulate into the named int64 return
value. Longer inputs continue through the existing uint64 overflow-checked
path.

Validation:

go test -count=1 ./...
ok  	github.com/buger/jsonparser	0.163s

Benchmark command:

go test -run '^$' -bench 'BenchmarkParseInt$' -benchmem -count=20 .
benchstat baseline-bench.txt after-bench.txt

Result on my machine (darwin/arm64, Apple M4, Go 1.25.1):

            │ baseline-bench.txt │ after-bench.txt │
            │       sec/op       │     sec/op      vs base
ParseInt-10       3.129n ± 4%       2.163n ± 5%  -30.90% (p=0.000 n=20)

            │ baseline-bench.txt │ after-bench.txt │
            │        B/op        │      B/op       vs base
ParseInt-10       0.000 ± 0%        0.000 ± 0%    ~ (p=1.000 n=20)

            │ baseline-bench.txt │ after-bench.txt │
            │      allocs/op     │   allocs/op     vs base
ParseInt-10       0.000 ± 0%        0.000 ± 0%    ~ (p=1.000 n=20)

I also checked the final implementation against the previous implementation
with a temporary differential test over fixed edge cases and deterministic
random byte slices, including boundaries and malformed inputs.

I found the candidate direction while experimenting with Sleepy -
https://sleepy.run/mcp, then manually simplified and validated it before
submitting.

@buger

buger commented Jul 27, 2026

Copy link
Copy Markdown
Owner

@trevorprater — triaged your PR against the current master + our in-flight #283 (L3 strict proof review).

Verdict: correct optimization, safe to merge with one carry-over

Correctness: ✅ Behaviorally identical to baseline across 15M fuzz iterations + a full edge-case sweep (-9223372036854775808..9223372036854775807, leading zeros, -0, 1.5, 12345x, every single byte 0x00-0xFF). The if l-i < 19 bound is provably safe: max 18-digit value (999999999999999999) < maxInt64.

Performance: ✅ Real gain on the hot path — 22–37% faster on typical 1–10 digit integers (timestamps, IDs, counts), no allocations.

One carry-over for our L3 posture: the fast path steals coverage from the slow path's final if neg branch in bytes.go:parseInt. The fix is one test row in bytes_test.go (parseIntTests):

{in: "-9223372036854775807", out: -9223372036854775807}, // = -math.MaxInt64 — slow path, neg=T

This restores code-level MC/DC to 100% under #283's strict posture.

Recommendation

Two options:

  1. Rebase against master after fix(parser): guard Delete leading-comma panic + empty-string key path components; L3 strict proof review #283 lands and add the test row above — then this is merge-ready as-is.
  2. If you'd prefer not to wait, I'm happy to cherry-pick your bytes.go change into a follow-up commit on fix(parser): guard Delete leading-comma panic + empty-string key path components; L3 strict proof review #283 with the witness test + MC/DC annotation, credited to you. Just say the word.

Either way — nice catch on the optimization. The fast-path-for-provably-safe-subdomain pattern is exactly right.

@buger

buger commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Thanks @trevorprater — your parseInt fast-path has been merged into #283 (the L3 strict proof review), which already landed on master (merge commit f26958f). The MC/DC witness test (-9223372036854775807 slow-path coverage) was added alongside it to keep code-level MC/DC at 100% under the strict posture. Credited to your change in bytes.go.

Nice optimization — the 22–37% gain on short integers is confirmed and shipping. Closing as merged.

@buger buger closed this Jul 27, 2026
buger added a commit that referenced this pull request Jul 27, 2026
…ETish

- bytes.go: parseInt fast path for <=18-digit numbers (from PR #285 by
  @trevorprater, 22-37% faster on short integers)
- bytes_test.go: -9223372036854775807 MC/DC witness for the slow-path
  neg branch that the fast path made unreachable for short numbers
- SYS-REQ-061/062: aligned FRETish variable with the U+FFFD substitution
  behavior (was 'returns_error_for_missing_low_surrogate', now
  'substitutes_replacement_for_missing_low_surrogate' — matches the
  actual DEFECT-260727-SNGT fix and encoding/json behavior)
- MC/DC witnesses updated to match the new variable names
- KI-2 evidence freshness re-stamped after bytes.go edit
buger added a commit that referenced this pull request Jul 27, 2026
Merge parseInt fast-path (PR #285) + align SYS-REQ-061/062 surrogate FRETish
@trevorprater

Copy link
Copy Markdown
Author

Thank you!

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.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.