Skip to content

Allocate ByteArrayBuilder past-block list lazily - #1675

Open
pjfanning wants to merge 3 commits into
FasterXML:3.xfrom
pjfanning:perf-bytearraybuilder-3x
Open

Allocate ByteArrayBuilder past-block list lazily#1675
pjfanning wants to merge 3 commits into
FasterXML:3.xfrom
pjfanning:perf-bytearraybuilder-3x

Conversation

@pjfanning

@pjfanning pjfanning commented Aug 24, 2026

Copy link
Copy Markdown
Member

ByteArrayBuilder allocated _pastBlocks = new ArrayList<>() in its field
initializer, for every instance. The list is only needed once content overflows
the first block — which for most instances never happens (ParserBase's binary
decoding buffer, JsonStringEncoder's fromInitial(...) slow path,
Base64Variant.decode(String)), since the first block is 500 bytes or a
recycled BYTE_WRITE_CONCAT_BUFFER.

Now created on first _allocMore(). reset(), toByteArray() and the
isEmpty() check are null-guarded; once created, the list survives reset() so
a reused builder does not re-allocate it.

Size of the win — deliberately modest

Worth stating plainly: new ArrayList<>() does not eagerly allocate a
backing array — it uses the shared DEFAULTCAPACITY_EMPTY_ELEMENTDATA sentinel
until the first add(). So what is saved per instance is the ArrayList object
header itself, ~24 bytes, not a 40-element array. This is an allocation-count /
young-gen-pressure change, not something a throughput benchmark will show
clearly. I have not benchmarked it and am not claiming a measurable speedup.

The case for it is that it is free: no API change, no behaviour change, and the
null checks are on paths that are either cold (toByteArray(), reset()) or
already doing an allocation (_allocMore()).

Test

New test testMultipleBlocksAndReuse() covers the paths this change alters:
single block (list never created), overflow across several blocks, and reuse of
the same builder afterwards.

Full suite green (1837 tests).

No release-notes entry, as there is no issue number for this yet.

Most instances never overflow the first block, so the list was allocated
and never used.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0161vnbY6rGfPFAYBMnbv64c
@pjfanning
pjfanning force-pushed the perf-bytearraybuilder-3x branch from d205e38 to 1b5ae50 Compare August 24, 2026 09:52
@cowtowncoder

Copy link
Copy Markdown
Member

Sounds good, just needs release-notes/VERSION entry.

Added new feature contributions and updates for version 3.3.0.
@pjfanning

Copy link
Copy Markdown
Member Author

Sounds good, just needs release-notes/VERSION entry.

I have now added an entry to the file

@github-actions

Copy link
Copy Markdown
Contributor

📈 Overall Code Coverage

Metric Coverage Change
Instructions coverage 83.89% 📉 -0.010%
Branches branches 76.90% 📈 +0.020%

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

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