Skip to content

Avoid ArrayList<Integer> boxing when collecting ParNew promotion-failure sizes - #2

Draft
java-dependency-upgrade-fixer[bot] wants to merge 1 commit into
evaluation/gctoolkit-pr-579from
jaipilot/pr-1-QEbHSEmJDv9c
Draft

java-dependency-upgrade-fixer[bot] wants to merge 1 commit into
evaluation/gctoolkit-pr-579from
jaipilot/pr-1-QEbHSEmJDv9c

Conversation

@java-dependency-upgrade-fixer

Copy link
Copy Markdown

What

GenerationalHeapParser.parNewPromotionFailedDetails collected per-thread promotion-failure sizes into an ArrayList (one autoboxed Integer allocation per matched '(N: promotion failure size = X)' block, plus ArrayList's own internal Object[] growth) and then copied/unboxed every element into a final int[]. This companion replaces the ArrayList with a growable primitive int[] (capacity doubling from 4) that is trimmed once via Arrays.copyOf, matching the exact same values, order, and empty-array behavior when the regex finds no promotion-failure-size block (the null-guard already present in the PR head is preserved).

Why

The PR mirrors microsoft#579 and, per the evaluation context, one changed parser path still gathered primitive promotion-failure sizes through ArrayList before allocating/copying an int[]. This is exactly that path (parNewPromotionFailedDetails, lines changed by the same PR to add the block == null guard). No other changed line in this PR (CMSPatterns.java's cached SPLIT_REMARK_REFERENCE_BUG_DURATION regex, or the other null-guard additions in GenerationalHeapParser.java) presented a similarly safe, material allocation/parsing-work reduction, so those were left unchanged.

Behavior preservation

  • The private field promotionFailureSizesForwardReference is set to the identical int[] content, order, and length (0 for no matches, N for N matches) as before.
  • No downstream code reads this field today (confirmed by repository-wide search), so there is no other observable surface; a focused reflection-based characterization test locks its value directly for 0, 1, and 28 (repository-fixture-derived) promotion-failure-size blocks.
  • All other statements in the method (clock, GC cause, garbage collection type, memory pool summary, duration parsing) are untouched.
  • ArrayList remains imported and used elsewhere in the file (an unrelated event queue field), so it was not removed.

Evidence

  • Focused behavior command passed identically before and after the production edit (3/3 tests).
  • Full parser module test suite (124 tests) passed identically before and after.
  • Full repository reactor build (7 modules) passed after the change.
  • Isolated microbenchmark of the exact collection-building logic (28-block case) shows a deterministic drop from 28 boxed allocations + ArrayList growth to 0 boxed allocations + 3 primitive array (re)allocations, with a measured ~27% reduction in median wall time (733.82 ms -> 537.30 ms per 5,000,000 iterations, 5 trials).

Limitations

  • The end-to-end per-line parsing speedup is smaller than the isolated microbenchmark suggests, since regex matching dominates total cost and real GC log promotion-failure records typically contain only a few blocks.
  • promotionFailureSizesForwardReference has no current downstream reader, so this is strictly an internal allocation-efficiency improvement, not a change in externally observable output.

Generated by JAIPilot Cloud for #1 from Anthropic session sesn_01UZHhdPrsSrQEbHSEmJDv9c.

@skrcode

skrcode commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Campaign acceptance microsoft#5 (independently reviewed)

  • Identity: companion commit c49248f has exact input head 2b427ea as its sole parent.
  • Scope: seven production-line changes in the already-changed parser path plus three directly relevant characterization tests.
  • Behavior proof: exact empty, single, and 28-value output arrays and ordering are pinned; 3/3 focused tests and all 124 parser tests pass before/after.
  • Allocation proof: representative 28-block path moves from 28 boxed Integers + ArrayList growth to zero boxing + three primitive-array reallocations; five-trial isolated median 733.82 ms -> 537.30 ms per 5,000,000 iterations (~27%).
  • Final verification: full seven-module repository reactor passed.
  • Cost: Anthropic list $2.37; estimated total $2.40.
  • Independent fork CI did not attach to the generated feature-branch draft; repository-native verification above came from the managed exact-head session.

Accepted as a genuine, reviewable internal allocation improvement; remains draft and unmerged.

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.

1 participant