Skip to content

Use local pointer in UTF8StreamJsonParser fraction and long-name loops - #1778

Draft
pjfanning wants to merge 1 commit into
FasterXML:3.xfrom
pjfanning:utf8-parser-local-ptr
Draft

pjfanning wants to merge 1 commit into
FasterXML:3.xfrom
pjfanning:utf8-parser-local-ptr

Conversation

@pjfanning

@pjfanning pjfanning commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Not yet ready for merge: needs re-measuring with more forks (results below are noisy) and review.

Applies the hot-loop lesson from #1775 / #1682 to UTF8StreamJsonParser: C2 doesn't keep a field in a register across loop iterations, so a scan loop that advances _inputPtr directly stores it on every byte.

  • _parseFloat(): the fraction-digit loop now scans the current buffer with a local pointer (the outer loop still handles _loadMore()).
  • parseLongName(): local pointer and local quad buffer; _inputPtr is written back before each exit (parseEscapedName() continues from it).
  • _parseUnsignedNumber() / _parseSignedNumber(): deliberately not changed, with a comment. With a local pointer C2 treats the integer loop as a counted loop and unrolls it: 13-digit longs got 10-17% faster, but typical 1-10 digit ints got 6-12% slower on JDK 25 (perfnorm: fewer instructions, but DSB->MITE shift and 2x branch misses; the gap reversed with -XX:LoopUnrollLimit=0).

String value loops (_finishString() etc.) already use local pointers.

Results

ParseBench, nextToken() over a whole document: 2000 ints (1-10 digits), 2000 13-digit longs, 2000 doubles (123.4567891), and 100 objects with 40 property names of 16-40 bytes. i7-8550U/WSL2, 5 forks, us/op:

JDK doc 3.x this PR change
17 doubles 132.36 ± 2.99 125.46 ± 2.60 -5.2%
17 names 782.04 ± 29.35 636.22 ± 40.76 -18.6%
25 doubles 140.59 ± 3.51 119.66 ± 5.25 -14.9%
25 names 709.83 ± 19.74 731.71 ± 36.09 +3.1%

Caveats:

  • This benchmark moves between runs. 3.x on JDK 25 ints scored 88-93 in four runs and 73 in one, with all forks agreeing within each run. The ints/longs docs run unchanged code (identical bytecode and inlining decisions, checked with PrintInlining), so they are left out of the table.
  • Names on JDK 17 was -4.4% in an earlier run of the same parseLongName() change, so the size of that gain is uncertain. JDK 25 doubles was -14% in both runs.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📈 Overall Code Coverage

Metric Coverage Change
Instructions coverage 86.52% 📉 -0.010%
Branches branches 80.60% 📉 -0.020%

Overall project coverage from JaCoCo test results. Change values compare against the latest base branch build.

@pjfanning pjfanning added the performance Issue related to performance problems or enhancements label Oct 16, 2026

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

performance Issue related to performance problems or enhancements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant