Repository navigation
perf: achieve measured 1:1 standard Perl throughput after #1850 #1863
Description
Goal
Reach at least 1.00x standard Perl throughput on a reproducible portfolio of method calls, closure calls, and bit-packed Life workloads while preserving Perl semantics and controlling memory use. Continue #1846 and #1196 after the focused memory improvements in PR #1850.
Parity must describe the measured workloads and configuration. It does not establish equal performance for every Perl program. Keep #1846 open until its method-call acceptance criterion is met.
Starting point and evidence
PR #1850 is currently open. Its reviewed candidate is 46ca082dacb6991edaf530d36e94749715f286f1, based on master 8bc1c9d1708de1381be6c042d6530c0c318e24f4. Treat this as a candidate baseline until the PR is merged; record the eventual merge commit separately.
The candidate retains four changes:
- Pack method-cache guard keys into one array, removing one array header per code object while retaining the same 32 KiB payload.
- Move rare scalar watcher and live-substring metadata into lazy extension state.
- Prevent shared immutable primitive scalars from retaining their last container, fixing the branch's reproduced retention failure.
- Store common zero- and one-argument JVM method-call arguments in two inline slots, promoting to ordinary storage when needed.
A matched candidate-versus-master method_anchor run on 2026-10-22 produced 1.03685x throughput, or 3.68% faster, across six stable pairs out of seven. The 95% bootstrap interval was 1.02495–1.04924x. All six included pairs favored the candidate; one pair was excluded because the master measurement failed stability. See the measurement report.
This comparison measures improvement over master, not parity with standard Perl. The historical 0.786x system-Perl result in #1846 was a single run on older code and must not be presented as the current gap. Obtain a new stable reference before estimating the remaining work.
Earlier short JFR evidence for the compact argument change estimated roughly 161 to 151 allocated bytes per method call, about 6.6% less. That was sampled evidence from an earlier candidate, not a matched total-memory comparison of the final pruned branch with master. Current peak RSS, live heap, and allocation savings versus master remain unquantified. Passing the full build without heap exhaustion is correctness evidence, not proof of reduced memory use.
Phase 1: establish a durable baseline
- Check in a reproducible runner and workload definitions. The recent matched runner and raw results currently reside under
/private/tmp; local temporary files are not durable review evidence. Recover the corrected stability logic from the preserved pre-prune history as needed, review it independently, and record its source hash. - Pin the standard Perl reference by source revision, configure options, compiler and optimization flags. Preserve perf: close method-call throughput gap to blead Perl #1846's optimized blead comparison as the primary method acceptance reference; also report a pinned stable Perl release so users can interpret the result. Do not silently substitute the installed Perl or compare threaded and unthreaded builds without documenting the difference.
- Record candidate/master source commits and JAR hashes, JDK, JVM flags, heap limits, OS/CPU, environment, workload hashes, commands, checksums, operation counts, and host load. Archive a reproducible Perl build recipe.
- Measure three distinct comparisons: candidate versus its exact parent for attribution, integrated candidate versus master for release value, and integrated candidate versus pinned standard Perl for parity.
- Use deterministic equal work, warmup to stability, balanced randomized launch order, at least seven requested pairs, and confidence intervals calculated over independent pairs. Predeclare stability thresholds, minimum accepted pairs, exclusion rules, and the statistical method; report every attempted pair and rejection. Do not treat windows from one process as independent runs.
- Define a fixed acceptance portfolio before optimization: the original method benchmark, the closure benchmark, and bit-packed Life with rendering disabled. Keep diagnostic variants separate. Ensure results cannot be explained by eliminated work or a changed checksum.
Report throughput, CPU time, elapsed time, allocated bytes per operation, GC time/counts, live heap after equivalent collection points, and peak RSS. Normalize allocation by completed work: allocation per second can rise when a faster program completes more operations. Use identical JVM memory settings for candidate/master comparisons and distinguish Java heap from total process memory.
Phase 2: identify the remaining dominant costs
- Split diagnostics into empty/trivial calls, ordinary direct subroutine calls, method calls, coderef/closure calls, argument aliasing/mutation, scalar/list/void returns, hash-field reads, integer updates, and equivalent inline bodies. Exercise both backends and include observable
caller/argument cases. - Profile the stable acceptance workloads using JFR CPU/allocation/GC evidence and HotSpot inlining/deoptimization evidence. Separate dispatch, frame bookkeeping, argument storage, scalar construction/coercion, and body execution. Report inclusive and exclusive costs.
- Estimate the maximum end-to-end benefit of each proposed change from its measured share. Prioritize costs that explain a material part of the remaining gap across ordinary programs.
Phase 3: implement general call and allocation improvements
The leading hypothesis is that the size and bookkeeping in RuntimeCode.apply() prevent efficient HotSpot inlining even for ordinary calls. A signature check inside the same large method may not address that limitation.
- Separate dispatch resolution from a small ordinary invocation path. Outline uncommon signature, warning, debugger, closure, and exceptional work only where metadata and runtime guards prove that work is unnecessary. Preserve a complete general fallback.
- Preserve required argument, caller, recursion, warning, and return-context behavior on ordinary calls. Generate direct invocation where justified, and verify actual JIT inlining rather than assuming smaller source code guarantees it.
- Guard callee identity and invalidate cached assumptions when subroutines or methods are redefined, including glob assignment. Cover changes during loops, inheritance/MRO changes, lookup and AUTOLOAD behavior, and aliased code references. Compile-time knowledge alone cannot freeze a Perl call target.
- Investigate lazy frame/materialization and scalar/primitive-result allocation only after profiles justify them. Define how observable state is materialized and how escaping values retain valid lifetime and aliasing.
- Evaluate ordinary scalar footprint and cache locality, small argument containers, and unnecessary intermediate arrays/lists. Account for padding, compressed-reference settings, and cold extension overhead. Avoid unbounded caches or pools that trade allocation reductions for retention.
Target ordinary call shapes broadly. Do not restrict the project to bodies containing only literal returns or hashes containing only plain integer cells. Such diagnostics may isolate costs; they do not satisfy the general goal.
Required semantic and memory regression coverage
Add focused permanent tests before each behavior-changing optimization. Validate Perl-level tests with system Perl first; retain failure evidence on the unfixed parent for reproduced regressions, then require JVM and interpreter success.
Coverage must include @_ aliases, mutation and escape; caller, recursion and wantarray; scalar/list/void context and lvalue returns; closures and captured lexical lifetime; named signatures; lexical/dynamic warnings; eval, exceptions and non-local control flow; debugger hooks; tied/overloaded values; dynamic lookup/AUTOLOAD; and glob-based subroutine/method redefinition. Test fallback transitions in the same running program.
Master did not exhibit the branch's heap-exhaustion problem. Treat recurrence as a regression to fix, not a reason to increase the heap or skip the workload. Include repeated calls and escaping/released argument containers under a fixed heap budget, checking bounded live state and collection of released owners. Keep the ownership regression coverage from #1850.
Acceptance and review gates
- For the original method anchor, achieve at least 1.00x pinned optimized blead Perl, with the lower bound of the 95% throughput-ratio interval at least 1.00x, as required by perf: close method-call throughput gap to blead Perl #1846.
- Apply the same criterion to each predeclared portfolio workload before claiming portfolio parity. Publish each result and the portfolio geometric mean; an average must not hide a workload below parity. Report stable-release comparisons separately.
- Quantify allocation, live heap and peak RSS versus master. Demonstrate no unbounded retention or heap exhaustion under the fixed acceptance budget; investigate material memory regressions even if throughput improves.
- Retain optimizations only with reproducible throughput or memory benefit. Keep the tests and correctness fixes required to make those retained changes safe; they do not need independent throughput gains. Document memory/throughput tradeoffs explicitly.
- Pass focused system-Perl/JVM/interpreter checks and the full repository
makegate on the immutable final source commit. Preserve full logs and update the design document underdev/design/, including completed phases and next steps. - Publish raw pair/window data, excluded runs and reasons, environment/build manifests, workload commands, profile summaries and final validation evidence as durable repository or issue/PR artifacts.
Shared-host execution
Bundle related fixes before expensive builds. Reuse verified artifacts when source/JAR hashes match. Run builds with nice -n 19, verify priority changes actually succeed, and wrap every investigative jperl/jcpan/prove run in timeout. Keep benchmark runs sequential, record competing host load, and schedule measurements when the host is quiet. Poll long-running jobs no more often than every ten minutes unless intervention is required. Do not mutate a checkout while its build or validation gate runs.
Related work
- perf: close method-call throughput gap to blead Perl #1846 — method-call throughput parity
- perf: surpass Perl on hot closure calls and bit-packed Life loops #1196 — closure calls and bit-packed Life
- perf: reduce method cache and scalar memory overhead #1850 — current memory/allocation improvements and regression coverage
Activity
fglock commentedon Oct 22, 2026
Performance baseline vs optimized blead
I measured the exact
origin/masterartifact (eaf1bfdb697c81999cf8bcc65b75e611fd6ead3b, JAR SHA-256e38b5feeda9aaa0fe26b829631f9f900618eda52cade59f757cf9a7d5e2a5bad) against optimized blead Perl83a6c8b26a8823eb966652414864eb07a3d2c6d4(Perl 5.45.5,-O3). The run used seven randomized pairs per workload, stable warmup, 15 one-second measurement windows, and checksum validation.The existing branch candidate before the method fast-path experiment (JAR SHA-256
4bfa54bc2ea90d38d001c5bcc845b6de44f8e78576b9f7b9eb6afe104835a6bd) measured 0.655x on the method anchor against blead (95% interval 0.649–0.660). Those separate-run results do not establish improvement over origin/master.The first method-fast-path attempt was not active at the actual named-sub call boundary and was removed. I fixed metadata propagation from the lazy compiler result to the stable named-sub placeholder, then verified that the guarded fast path activates in scalar context. The corrected candidate JAR SHA-256 is
4aaed76f272844d53dc6db293ccc8278d8bedee849a3eb54ae8b4ada8248784b. A short three-pair method run measured 0.683x blead (candidate median rates 4.66–4.80M calls/s; blead 6.88–7.01M) and 1.007x the exact origin artifact in a same-run comparison. This is a small directional gain over the origin baseline’s 0.672x, not an acceptance result. The comparison runs used five one-second measurement windows and could not verify requestednice -n 19priority.The required full
nice -n 19 makegate passed after the overload-guard and argument-array reuse changes. The 19-check Perl regression passes on system Perl, the JVM backend, and the interpreter. It covers aliased hash cells, list and void contexts, statically and dynamically added%{}overloads, and an escaped@_array surviving later calls.The latest candidate caches the receiver overload decision per runtime and recycles the two-slot method argument array only after a compiler-proven non-escaping method returns. Its JAR SHA-256 is
1aaba79da113588d0bdd907d0a4603ca8e30529fca64ea711e078aeccd060a89. The full method-only protocol requested seven randomized pairs with 15 one-second measurement windows; six complete stable pairs remained. Recomputing them while excluding only unverifiable priority gives 1.113x over the exact origin JAR (95% interval 1.032–1.215) and 0.720x blead (0.677–0.762). The origin artifact comparison's seventh candidate pair did not stabilize; the blead comparison's seventh Perl pair did not stabilize. Host load was high. These are directional results, not acceptance results, and the method anchor remains about 28% slower than blead at this candidate.A 30-second JFR run of the pooled-argument candidate completed 146.94M method calls with the expected checksum. Its allocation samples contained no
RuntimeArrayorInlineMethodArgumentListevents, while the preceding profile sampled both repeatedly. The raw profile is retained asissue-1863-method-pooled-args-active.jfr.Measurement limitation: macOS denied requested
nice -n 19priority (setpriority: Operation not permitted), so the harness marks these runs diagnostic-only. The origin intervals above were recomputed from all seven stable, checksum-matched pairs while excluding only the unavailable priority-verification check. Shared-host load also rose during the longer baseline run. These values establish directional baselines, not acceptance results.Raw paired windows and metadata are in
dev/bench/reports/on the performance branch:issue-1863-origin-master-eaf1bfdb-blead-83a6c8b.json,issue-1863-blead-83a6c8b-1217aeed.json,issue-1863-candidate-fastpath-blead-83a6c8b.json,issue-1863-candidate-fastpath-vs-origin-method.json,issue-1863-candidate-registered-fastpath-blead-method.json, andissue-1863-candidate-registered-fastpath-method.json,issue-1863-candidate-pooled-method-args-vs-origin-full-method.json,issue-1863-candidate-pooled-method-args-vs-blead-full-method.json, andissue-1863-method-pooled-args-active.jfr.Latest full-portfolio candidate
The latest candidate JAR (
9169517e9bede6d967fbaa9dba78f3c4486451c6db8511cef4a546a2eddbbb1a) was measured against the same pinned blead revision across method, closure, and Life: seven randomized pairs, 15 one-second windows per pair, all stable and checksum-matched. Recomputed paired ratios excluding only the unverified priority check are:This remains diagnostic: macOS could not verify
nice -n 19, and shared-host load was high before and during the run. The method anchor is still about 25% slower than blead, so the 1:1 goal is not met even though the other workloads and portfolio mean are above parity. Raw results and per-pair logs are retained indev/bench/reports/issue-1863-current-candidate-pooled-full-portfolio-blead.jsonand its sibling-logs/directory.Latest method-path experiment
A JFR hotspot showed repeated checks of call-local hash cells in the guarded generated method body. The candidate now reads a cell directly after the call boundary validates and caches it; ordinary calls retain the checked lookup. The required
nice -n 19 makegate passed.The resulting JAR (SHA-256
4bf3bbd3432211d853319466924699b2fc12188d804d7bef77804f47e6a58e16) completed seven stable, checksum-matched method pairs against each reference. Excluding only unverifiable process priority, it measured 1.137x the exact origin/master JAR (95% interval 1.064–1.191), but 0.743x blead (0.712–0.773). Host load was high, and macOS still denied requestednice -n 19, so this remains diagnostic. The change shows progress against the origin artifact but does not improve the latest blead ratio materially; the method anchor remains about 26% slower and the 1:1 goal remains unmet.Raw windows and per-pair logs are retained in
dev/bench/reports/issue-1863-candidate-active-verified-cells-method.json,dev/bench/reports/issue-1863-candidate-active-verified-cells-method-logs/,dev/bench/reports/issue-1863-candidate-active-verified-cells-blead-method.json, and the matching-logs/directory.Latest full-portfolio candidate
The generated method entry guard had been repeating generic argument and field checks after the method call boundary had already established the same proof. The new entry path verifies that the active proof matches the method’s argument indices and hash keys, then loads the cached cells directly. The required full
nice -n 19 makegate passed on this source.The resulting JAR (SHA-256
af0dd535614a9afa91da9aa36ccfa81c3e351ed1a03941d431dc92d74b111131) completed seven pairs each for method, closure, and Life. All 21 pairs stabilized and matched checksums. Recomputed paired ratios excluding only unavailable priority verification are:The method-only seven-pair run for the same JAR measured 0.790x blead (0.771–0.814) and 1.225x the exact origin/master JAR (1.180–1.286). The full-portfolio method ratio is the scored value for that run; the method-only result is from a separate comparison. macOS could not verify requested
nice -n 19, and host load rose during the portfolio run. Both results are diagnostic. The method anchor remains below parity, so issue #1863 remains open.The full-portfolio report and pair logs are in
dev/bench/reports/issue-1863-candidate-active-entry-guard-full-portfolio-blead.jsonand the matching-logs/directory. The isolated method reports aredev/bench/reports/issue-1863-candidate-active-entry-guard-origin-method.jsonanddev/bench/reports/issue-1863-candidate-active-entry-guard-blead-method.json. The post-change JFR profile isdev/bench/reports/issue-1863-method-active-entry-guard.jfr; its samples no longer show the repeated generic entry-guard and verified-cell getter paths.Latest argument-lifecycle optimization
JFR showed root-snapshot reachability checks when adding the blessed invocant to and clearing the temporary two-slot argument array. For compiler-proven stable methods, the temporary array now suppresses root-mutation tracking during the non-escaping call. If runtime validation fails, tracking resumes before the generic fallback; exceptional exits also restore tracking. The full
nice -n 19 makegate passed, and the post-change JFR no longer samplesMortalList.invalidateFullRootSnapshotIfReachableon this path.The resulting JAR (SHA-256
3a98fe0aa492f7a5fda7b1ab8d31e8c21e868959448278952e51208f2ac2d0ec) completed seven pairs per workload and seven additional method pairs against the exact origin JAR. All 28 pairs were stable and checksum-matched. Recomputed excluding only unverified process priority:These remain diagnostic because macOS could not verify requested
nice -n 19; load was high during the origin comparison. The authoritative method result for the complete portfolio is 0.845x blead, still about 15% below parity. The 1:1 target is not met.Raw portfolio and exact-origin method reports are in
dev/bench/reports/issue-1863-candidate-arg-root-track-full-portfolio-blead.jsonanddev/bench/reports/issue-1863-candidate-arg-root-track-origin-method.json, with matching per-pair log directories. The post-change JFR isdev/bench/reports/issue-1863-method-args-root-tracking.jfr.Current candidate measurement
The latest committed candidate is
cc2d6155f53e512eb966129943c45a24a2f3e688; its JAR SHA-256 is2b527ef3cb3eff880c196f61941aba8091da60e3f6adcdddb7903aa45251649e. Against optimized blead83a6c8b26a8823eb966652414864eb07a3d2c6d4, all seven randomized pairs stabilized and matched checksums:A separate balanced seven-pair method comparison against the exact
origin/masterJAR (eaf1bfdb697c81999cf8bcc65b75e611fd6ead3b, SHA-256e38b5feeda9aaa0fe26b829631f9f900618eda52cade59f757cf9a7d5e2a5bad) measured 1.349x (95% interval 1.325–1.375). The blead method ratio has moved from the exact origin baseline of 0.672x to 0.903x; the current method remains about 9.7% slower than blead.This increment directly clears recycled inline argument slots only when tracking was suppressed for a compiler-proven non-escaping stable method. Other arrays retain normal clearing, and package-root arrays are excluded. The 24-assertion regression passes on system Perl, JVM, and interpreter; the full
nice -n 19 makegate passed on the committed source.make check-linksalso passed.These comparisons are diagnostic, not acceptance evidence: the run did not request priority because this macOS host reports a
nice -n 19child aspsniceness 20, while the harness requires an exact verified 19. The full report has seven complete portfolio pairs and low-to-moderate load, but the required priority condition is unmet. Issue #1863 remains open until the method anchor reaches validated 1:1 parity under the acceptance protocol.Raw reports and pair logs:
dev/bench/reports/issue-1863-cc2d6155-blead-full-portfolio.jsondev/bench/reports/issue-1863-cc2d6155-vs-origin-method.jsonLatest validated source and hash-cell cache experiment
The branch source remains at validated commit
9473c37b9. Its full seven-pair blead portfolio measured method 0.903x (95% interval 0.891–0.914), closure 1.565x (1.553–1.582), Life 1.077x (1.052–1.099), and portfolio 1.151x (1.139–1.162). The method anchor is still about 9.7% below blead; 1:1 parity is not met.I tested moving the stable hash-cell cache from weak references owned by each code object to a strong cache owned by the hash. Seven balanced method pairs against a freshly built
9473c37b9artifact measured 1.005x (95% interval 0.988–1.027), which does not establish a throughput gain. A separate seven-pair run against blead measured 0.908x (0.889–0.922), consistent with the preceding candidate's 0.903x result. I reverted the cache-ownership change and kept the validated9473c37b9source.These comparisons remain diagnostic: macOS could not verify the requested
nice -n 19priority. The experiment does not change the parity status; the method anchor remains below blead.Stable method argument insertion follow-up
I tested skipping redundant storage bookkeeping when adding the invocant to the private, non-escaping stable-method argument list, while retaining the container-owner edge and excluding
@ISAarrays. Seven balanced method pairs against the preceding validated artifact measured 1.003x (95% interval 0.959–1.047). The interval includes parity with the reference, so this does not establish an improvement; I reverted the change. The direct comparison report is retained locally asdev/bench/reports/issue-1863-inline-store-vs-9473-method.json.A separate six-pair blead run measured 0.845x (0.761–0.944), but host load varied and the interval is too wide to use as a progress claim. It remains diagnostic only. The method anchor is still below 1:1 parity.
Hosted pinned portfolio run for commit
38cf359dThe acceptance workflow completed on Ubuntu 24.04 / AMD EPYC 7763, with seven randomized pairs per workload, 15 one-second measurement windows, priority verified at nice 19, and all pairs stable and checksum-matched. Candidate JAR SHA-256:
058cdf9fff5d1256e735b314189e7bbf441f9f901dc6432a24e2af5763aef416. The pinned references were blead83a6c8b26a8823eb966652414864eb07a3d2c6d4and Perl 5.42.2b62845c7186b0b6a8e4e83419e6b5ef64ceef3ed.The method result is effectively unchanged from the pinned origin/master measurement above (0.676x vs 0.672x). The fresh-scalar result fast path also showed no attributable improvement against the exact PR parent: method 0.996x (0.965–1.036), portfolio 1.015x (0.987–1.045). I’m removing that fast path because this run does not demonstrate a throughput gain. The candidate is not at 1:1 parity: method and Life remain below both Perl references.
Attribution against exact origin/master
eaf1bfdb697c81999cf8bcc65b75e611fd6ead3bmeasured method 1.204x (1.158–1.247), closure 1.311x (1.273–1.365), Life 0.924x (0.773–1.138), and portfolio 1.134x (1.062–1.219). This comparison is useful for branch attribution; it is not Perl parity evidence.The full run, environment manifest, per-pair raw JSON, and worker logs are retained in the 90-day GitHub Actions artifact (
issue-1863-performance-38cf359daf2a721362a85e9e5ebfaa8a3d07a33d). Workflow and candidate commit: 38cf359d.Clean candidate measurement after dropping the no-gain fast path
PR #1870 now removes the fresh-scalar result experiment. The cleaned head
85487069bf773710f2a385632b7bb5e3e342f4adpassed the fullmakegate and the pinned measurement workflow. It ran on the same Ubuntu 24.04 / AMD EPYC 7763 runner with seven randomized pairs per workload, 15 one-second measurement windows, verified nice 19, and all pairs stable and checksum-matched. Candidate JAR SHA-256:be815543d13244c2a82ef7681a1c2405608ab87d4ae34932476870e06228be74.The clean candidate compared with the exact preceding PR parent (the fast-path experiment) measured method 0.993x (0.977–1.010), closure 1.034x (0.996–1.083), Life 1.011x (0.991–1.035), and portfolio 1.013x (0.996–1.032). This confirms that experiment did not show a reproducible gain. Against the exact
origin/masterbase commiteaf1bfdb697c81999cf8bcc65b75e611fd6ead3bin the same run, the clean candidate measured method 1.393x (1.371–1.413), closure 1.186x (1.113–1.265), Life 0.996x (0.980–1.011), and portfolio 1.181x (1.154–1.207). That is branch-attribution evidence, not Perl parity evidence.The clean candidate's method throughput is about 31.6% below pinned blead, and Life is also below parity. The 1:1 goal remains unmet. Raw JSON, environment manifest, and per-pair logs are in the 90-day Actions artifact (
issue-1863-performance-85487069bf773710f2a385632b7bb5e3e342f4ad).Latest candidate: retain the recycled argument ThreadLocal entry
The method profile sampled
ThreadLocalMap.setInitialValuewhile returning the recycled method argument array: borrowing removed the ThreadLocal entry, then every completed call inserted a new entry. The candidate keeps that entry with a null value while the array is borrowed, so recycling updates the existing entry. The fullnice -n 19 makegate passed; the hosted runner passed checksum and stability checks for all seven randomized pairs per workload, with requested priority verified.Against the exact preceding PR candidate
85487069bf773710f2a385632b7bb5e3e342f4ad, the paired results were:This supports retaining the change: method and portfolio intervals are above 1.00x in the direct paired run. Compared with optimized blead, method is 0.719x (0.707–0.731), closure 1.315x (1.273–1.365), Life 0.812x (0.806–0.818), and portfolio 0.915x (0.904–0.929). Compared with stable Perl 5.42.2, method is 0.731x (0.721–0.741), closure 1.356x (1.304–1.410), Life 0.810x (0.800–0.822), and portfolio 0.930x (0.917–0.944). The method anchor remains about 28% below blead; 1:1 parity is not met.
The same-run comparison with exact
origin/mastermeasured method 1.408x (1.375–1.445), closure 1.252x (1.187–1.318), Life 0.984x (0.968–1.002), and portfolio 1.202x (1.180–1.224). This is branch-attribution evidence. Allocation, GC, live-heap, and peak-RSS per-operation gates remain to be reported; this throughput run does not establish those memory results.The candidate is commit
d32be183, JAR SHA-256188ff8d1992966f49990c85cca739cf3a53fadbc1b1e70729165981232a5a284. The complete raw reports and per-pair logs are retained in the 90-day Actions artifact.Current
origin/masterbaseline and synced candidateAfter resolving the merge conflict with current
origin/master, PR #1870 was measured ata7950abce0c323ca8f51fdc25b47205c8a36d072. The exact master comparison used45f6f0c283bb128b95940c8b4af01b66c7413448(JAR SHA-256aec84d55ace9ce7e9cf5cf71b14455c9de73bd30ac57f0232c56c2c1965e55a1). The candidate JAR SHA-256 was2a6f4249e95b20af3129ad0b2902872f8c0b913aade0e9d27247f6863ab0718d.The hosted workflow passed
nice -n 19 make, the JFR capture, all checksum and stability checks, and all four seven-pair comparisons. Measurements ran on a four-vCPU Intel Xeon Platinum 8573C runner. Ratios are throughput (candidate ÷ reference); each interval is a paired 95% bootstrap interval.45f6f0cThe synced candidate is 33.1% below blead on the portfolio and 40.9% below on method throughput. It is 13.2% faster than the exact current master artifact on the portfolio, driven by a 40.7% method gain; Life is statistically inconclusive in this comparison. The old exact-master-versus-blead figures above refer to the earlier master commit
eaf1bfdb; do not treat them as the baseline for current master45f6f0c. This run measures the current branch against both references, but does not directly benchmark the current master JAR against Perl.Against the exact pre-merge branch parent
ebb7b3b90f913e7717b9ce04eb734b0e1d3d8d6b, the synced candidate measured method 1.008x (0.992–1.022), closure 1.000x (0.996–1.003), Life 1.000x (0.913–1.089), and portfolio 1.002x (0.968–1.036). This merge-sync comparison shows no material throughput change from the previous branch candidate on this runner.Against Perl 5.42.2, the synced candidate measured method 0.570x (0.558–0.583), closure 0.851x (0.830–0.876), Life 0.611x (0.582–0.648), and portfolio 0.667x (0.653–0.683). The 1:1 parity goal remains unmet.
The successful run, JFR profile, environment, raw reports, and per-pair logs are retained in the 90-day GitHub Actions artifact (
issue-1863-performance-a7950abce0c323ca8f51fdc25b47205c8a36d072). The candidate is commita7950abc; PR #1870 is now mergeable (CLEAN).Integer scalar cache experiment: reverted after regression
The unscored method-anchor JFR sampled
RuntimeScalarCache.getScalarIntas a major allocation site. I tested expanding its upper bound from 1,024 to 65,535, then compared against the exact parent on the same hosted runner. The experiment regressed method throughput to 0.976x (95% interval 0.968–0.983), closure throughput to 0.948x (0.921–0.976), and portfolio throughput to 0.971x (0.955–0.986). The measured regression outweighs the allocation-site observation, so the range expansion was reverted in5540cc38ef78f5e67683b6cf80a1fb57740b4294.The full benchmark and JFR artifact for this experiment is run 40039256381. The revert restores the previously measured runtime source from
a7950abce0c323ca8f51fdc25b47205c8a36d072; its validation workflow is running for the updated PR head.Reverted-source confirmation and refreshed paired results
The revert commit
5540cc38ef78f5e67683b6cf80a1fb57740b4294restores the previously measured source. Against the exact experimental parent with the wider cache (a17befcf), it recovered method throughput to 1.021x (95% interval 1.013–1.030) and portfolio throughput to 1.027x (1.005–1.046). The full build, Windows and Linux CI, and four-reference hosted workflow passed.In this run, the restored candidate measured against optimized blead Perl 5.45.5 at method 0.600x (0.592–0.607), closure 0.863x (0.854–0.870), Life 0.578x (0.515–0.625), and portfolio 0.669x (0.644–0.685). Against exact current master
45f6f0c283bb128b95940c8b4af01b66c7413448, it measured method 1.431x (1.403–1.455), closure 1.146x (1.106–1.189), Life 1.016x (0.968–1.065), and portfolio 1.186x (1.170–1.203). Against stable Perl 5.42.2, it measured method 0.598x (0.593–0.603), closure 0.872x (0.859–0.884), Life 0.624x (0.606–0.638), and portfolio 0.688x (0.682–0.694).These remain branch-versus-reference results; the current master's own direct comparison to optimized blead is now included in the workflow and is running in run 40058854465. The completed reverted-source results and per-pair logs are in run 40049802377.
Direct current
origin/masterbaseline vs optimized bleadThe added exact-master comparison has completed on the same hosted runner protocol: seven randomized pairs per workload, 15 one-second measurement windows after stable warmup, verified nice 19, and checksum-matched pairs. It directly compares master commit
45f6f0c283bb128b95940c8b4af01b66c7413448(JAR SHA-2563d6554626a4014104480046e879af5af213854125096dce8f756501743df6d1e) with optimized blead Perl 5.45.5 at83a6c8b26a8823eb966652414864eb07a3d2c6d4(-O3). The pinned workflow reports this run as acceptance-protocol eligible.origin/master÷ bleadThis is the current master baseline, replacing the older
eaf1bfdbbaseline as the reference for PR progress. The exact master report and all paired logs are in Actions run 40058854465, artifactissue-1863-performance-992aad22b2df8fb6edbb7484de00dc3d230ddcdc. The candidate branch's method interval remains below 1.00x against blead, so the 1:1 goal is still unmet.Current candidate paired in the direct-baseline workflow
The same completed workflow measured PR head
992aad22b2df8fb6edbb7484de00dc3d230ddcdc(candidate JAR SHA-2561740ec3d175befbf4451ec2de232527c4b07a78e465b46653998e1a9b9b2d30f). Against pinned optimized blead, the candidate measured method 0.921x (95% interval 0.880–0.948), closure 1.739x (1.641–1.866), Life 1.012x (1.006–1.018), and portfolio 1.175x (1.148–1.209). Against the exact current-master JAR, it measured method 1.288x (1.253–1.324), closure 1.321x (1.300–1.346), Life 0.842x (0.731–1.018), and portfolio 1.127x (1.071–1.206).Each candidate comparison used seven complete, stable, checksum-matched pairs. These are separate sequential paired runs; do not combine their confidence intervals algebraically. The candidate is ahead of current master on the portfolio, while method remains statistically below blead, so 1:1 parity is not met. Use this exact-head run for the current baseline; earlier entries retain their historical commit and environment attribution.
Method argument pool experiment and current PR head
The method argument pool experiment at
b44eafb9bcd14ae2048b431912e64e1e13a28431completed the full hosted performance workflow (run 40068981076). It used seven randomized pairs per workload, stable warmup, 15 one-second windows, matching checksums, and verified nice 19.Against the exact parent JAR, the candidate's portfolio ratio was 1.036x (95% interval 0.964–1.097). Method was 1.016x (0.971–1.063), closure 1.054x (0.950–1.182), and Life 1.039x (0.910–1.184). Every interval includes 1.0, so these data do not establish a gain; the pool optimization was reverted in
e48cb82810686b8df4de6a6653727f91b88766a5.For context, that experiment measured 1.265x method (1.242–1.297), 1.230x closure (1.163–1.291), 1.091x Life (0.940–1.239), and 1.193x portfolio (1.135–1.250) versus exact
origin/master. Against optimized blead, it measured 0.687x method (0.666–0.707), 1.656x closure (1.591–1.718), 0.764x Life (0.696–0.859), and 0.954x portfolio (0.918–0.995). These are sequential paired comparisons; do not combine their intervals. Method remains below Perl, so 1:1 performance parity is not met.The revert restores the source measured as candidate commit
992aad22b2df8fb6edbb7484de00dc3d230ddcdc; its hosted comparisons remain recorded above. The reverted heade48cb82810686b8df4de6a6653727f91b88766a5passed the full localmakegate. CI has started for that new head.Final measurements for reverted PR head
The reverted head
e48cb82810686b8df4de6a6653727f91b88766a5has now passed its complete CI and performance workflow (run 40079441983); PR #1870 is cleanly mergeable. This exact-head run used the same seven-pair, stable-warmup, 15-window protocol with checksum validation and verified nice 19. These fresh comparisons supersede the earlier candidate/reference rows above for current-head status.origin/masterorigin/master÷ optimized bleadThe pool change has no established parent-relative gain: its fresh portfolio interval also crosses 1.0, so reverting it remains appropriate. The method anchor is 0.903x blead, with the whole interval below 1.0; the 1:1 method-performance goal remains unmet. The exact-master baseline was remeasured in this run and is shown here to keep the comparison on the same runner session as the candidate results. The complete reports and per-pair logs are available in the run artifact
issue-1863-performance-e48cb82810686b8df4de6a6653727f91b88766a5.Current-head profile for the next optimization
The same run captured a 30-second unscored method-anchor JFR. Of 1,264 execution samples, 149 were in
HashMap.getNodeunderRuntimeCode.prepareStableHashMutationMethodArguments(the per-call lookups for the guardedx/yhash cells), 123 inThreadLocalMap.setunderRuntimeArray.recycleMethodCallArguments, and 54 inThreadLocalMap.getEntryunderPerlRuntime.current. Allocation samples most often came fromRuntimeScalarCache.getScalarIntwhile computing the method's returned sum. This narrows the next investigation to the guarded method entry and per-call runtime lookup costs; the broader ThreadLocal argument-pool change was already tested and did not show a portfolio gain. Raw JFR, summary, and samples are in the run artifact linked above.Next measured optimization candidate
Commit
d8cc1c5621a2159bdd3233694a35424e0445584dadds a cache for the guarded method's hash-cell pair. It reuses cells only while the exact backing map and key bindings remain stable; ordinary map writes invalidate it, while exposed mutable views and less common map mutation APIs disable caching. Focused Java tests cover reuse and these invalidation paths. The existing Perl regression for field reassignment and delete/recreate passes on system Perl, the JVM backend, and the interpreter. The full localmakegate also passed. Exact-parent and blead measurements are running in workflow run 40091795286; retain this candidate only if the paired results show a useful gain without a regression.Hash-cell cache result
The cache candidate
d8cc1c5621a2159bdd3233694a35424e0445584dcompleted its full hosted workflow (run 40091795286). Against its exact parent, method throughput was 0.967x (95% interval 0.937–0.999), a measured regression on the target workload; portfolio was 1.011x (0.966–1.052). Against blead it measured method 0.704x (0.683–0.719), closure 1.732x (1.698–1.774), Life 0.688x (0.657–0.745), and portfolio 0.943x (0.921–0.978).The cache was reverted in
f179d4607and the full localmakegate passed on the restored source. The PR now retains only the previously measured implementation. This experiment rules out carrying this cache as a path to 1:1; the method workload remains below blead, and further changes need to improve method throughput itself.Refreshed baseline for restored head
f179d4607The post-revert exact-head workflow passed (run 40104029507). It remeasured the restored candidate, exact parent, current master, blead, and stable Perl with seven randomized pairs and the pinned protocol. Use these values for the current head; earlier runs remain historical comparisons.
origin/masterorigin/master÷ optimized bleadThe method anchor remains below 1:1 blead throughput. The exact candidate-versus-parent result is effectively neutral, and the candidate is ahead of master in this same-run comparison. The failed hash-cell cache is reverted.
The current-head JFR still shows time in
RuntimeCode.callCachedInnerandMyVarCleanupStack.popMark, with additional samples inHashMap.getNode,ThreadLocalMap.set/getEntry, andRuntimeCode.coerceScalarCallResult. Allocation samples remain dominated byRuntimeScalarCache.getScalarInt. The next implementation batch will focus on method-call cleanup/result handling with focused coverage, then use one full local gate and the hosted paired workflow to decide whether to keep it.Boxed-integer payload cache experiment (rejected)
Candidate
e0cdbaf94e9ecb9377d403ba0e923d4d0fba21d7completed the pinned seven-pair workflow (run 40116673827). It cached only immutable JavaIntegerpayloads while keeping Perl scalar cells distinct and writable. The local fullnice -n 19 makegate passed; the added Perl mutability regression passed on system Perl, JVM, and interpreter.origin/masterorigin/master÷ optimized bleadThe candidate regressed against its exact parent in all three workloads and in the portfolio; this optimization is rejected and will be removed from the PR branch. Its method ratio remains below 1.00x against blead, so it does not advance the 1:1 goal. The benchmark workflow succeeded. Ubuntu CI passed; Windows CI reported one failure in the unrelated
unit\file_path_remove_tree.ttest. The PR remained conflict-free (mergeStateStatus: CLEANbefore checks began); the laterUNSTABLEstate reflected pending/failed checks, not a merge conflict.The raw JSON reports, per-pair logs, environment manifest, and method JFR are in the run artifact
issue-1863-performance-e0cdbaf94e9ecb9377d403ba0e923d4d0fba21d7.Fresh-scalar return fast-path experiment (not retained)
Candidate
6a351c7851c3bb641e61417f03036d671b9cc749completed the seven-pair workflow (run 40133234593). It bypasses generic call-result copying only for a compiler-marked, one-element non-reference fresh scalar; list-context read-only literal copying remains intact. The full localnice -n 19 makegate passed, as did the new Perl regression on system Perl, JVM, and interpreter.origin/masterorigin/master÷ optimized bleadThe exact-parent intervals span 1.0 for every workload and the portfolio, so this run does not establish a gain. The method anchor remains 0.700x blead, with its full interval below 1.0; the 1:1 goal remains unmet. This candidate will be removed from the PR branch.
The performance workflow succeeded. Windows CI passed. Ubuntu's external Thread::Queue compatibility gate failed in
perl5/dist/Thread-Queue/t/01_basic.t: a worker terminated withConcurrentModificationExceptionwhile joining (threads.pmline 49), followed by 11 queue assertions. The normal Ubuntu build and test gate had passed. The local focused tests did not exercise this path; its connection to the scalar-result change is unestablished.Raw paired JSON, per-pair logs, and JFR are in run artifact
issue-1863-performance-6a351c7851c3bb641e61417f03036d671b9cc749.Hosted evaluation of the stable-method batch
The batch was tested on PR #1870 at exact source head
b5338accbffa9dac173765ec7c39550a25c7d0adwith the pinned seven-pair, 15-window full-portfolio workflow (performance run 40150003634). All pairs stabilized and passed checksums; the run used the requested nice priority.83a6c8borigin/masterThe candidate did not establish a gain over its exact PR parent: all exact-parent intervals include 1.0. Its method anchor is only 0.597x blead, with the entire interval below parity. This PR-source measurement supersedes the separate local WIP result above for judging this batch on PR #1870. I removed the batch from the PR branch, restoring head
f179d4607aec86755defba9fbe28ac0e863608a2, and will continue from that source with another profiled hypothesis.The Java CI run 40150008081 passed on both Windows and Ubuntu. The performance run passed. PR #1870 was
OPENandMERGEABLE; there was no CI-blocking conflict. The revert has triggered fresh CI for the restored head; its results are pending.Raw paired reports, logs, and JFR are in the run artifact
issue-1863-performance-b5338accbffa9dac173765ec7c39550a25c7d0ad.Empty method cleanup walk guard
The restored-head method JFR contained repeated samples in
MyVarCleanupStack.popMark. IncallCached, the cleanup boundary is necessary when a called method registers lexical variables, but its normal method-call benchmark path often has no registrations to discard. The runtime now checks the per-runtime cleanup stack size and enterspopMarkonly when it grew past the saved mark; the existing cleanup behavior remains for nonempty calls.The full
nice -n 19 makecommand passed in 6m43 on commit1baa072fe(20 Gradle tasks; all unit/Joni/integration gates succeeded). The host denied setting the requested niceness, so priority was not independently verified. This commit is pushed to PR #1870 for hosted exact-parent and blead measurements; results are pending.Local method-anchor checkpoint (diagnostic only)
A local seven-pair method-anchor comparison against pinned blead
83a6c8b26a8823eb966652414864eb07a3d2c6d4used JAR SHA-2569865d8a7f5cfd23574eba417ee031cec5f35834092b6d32e81798b3e2d2a9255(the local stable-cell arithmetic batch atop PR head1baa072fe). All seven warmups and checksums were stable. The paired ratios were 0.939x, 0.942x, 0.943x, 0.952x, 0.932x, 0.941x, and 1.090x; their geometric mean is 0.961x, with a diagnostic 95% paired bootstrap interval of 0.938–1.003.macOS denied
nice -n 19, and host load rose from 5.5 to 13.7 during the run. The interval crosses 1.0, so this does not establish 1:1 parity. The local source now also caches the stable method's immutable eligibility checks; its fullmakegate passed, but a low-load comparison of that newer JAR is still needed. No CI result is being used to claim local parity.Newer local method-anchor run (diagnostic only)
The newer local JAR SHA-256
3d6d781428e653c11e72c55343eca8812f77696ba08cc53dcde07b4574bce39dcompleted seven checksum-matched, stable pairs against the same pinned blead, using 15 one-second windows per measurement pair. It measured 0.922x blead (95% paired bootstrap interval 0.893–0.954). The method anchor remains below 1:1 parity. This is not a direct before/after comparison to the prior local JAR because the runs occurred at different times and under different load.The run deliberately did not request process niceness, and host load rose from 6.7 to 15.5 during measurement. It is diagnostic-only; the full acceptance protocol remains unmet. The local full
makegate for this JAR passed in 7m18.Local method-anchor attempt (diagnostic only; 2026-10-25)
The seven-pair method-anchor attempt against optimized blead
83a6c8b26a8823eb966652414864eb07a3d2c6d4used source commit71b5a6fa20d2e17b553d2294ca0d64065a6e00dband JAR SHA-256164e4b4ac988618a155aab2c54146144fcc3a3a0230e1d3b641758f73f10c853. Six pairs have complete 15-window measurements; pair 5 has no Perl measurements. Their descriptive geometric mean is 0.989x, with no confidence interval calculated. The run requestednice 0; sandboxedpsreturned no observed process priority, so all pairs are excluded. Host load averages rose from 4.96/8.00/12.12 to 24.64/18.88/15.37. This is not parity evidence. The archived report and all pair logs are here.A separate check under extended access confirmed the benchmark can observe a worker at
nice 19. The later argument-cache cleanup in PR #1870 commita5f95a42dhas not yet been benchmarked. The method lower-bound criterion and the closure/Life portfolio remain unmet.Verified-priority method-anchor rerun (diagnostic only; 2026-10-25)
A seven-pair method-anchor comparison against optimized blead
83a6c8b26a8823eb966652414864eb07a3d2c6d4used candidate source commit7c5e3c50af3b0d2222901c1d781f8cc2b668171fand JAR SHA-256baaf94e293dedb0f4683956144fe0da0a0a3a17048930f505736982c7e6356f0. All seven pairs completed 15 stable windows with matching checksums, and both engines were observed at nice 19. The paired geometric mean was 0.981x (95% bootstrap interval 0.955–1.014). The lower bound remains below 1.00x. Host load averages increased from 9.06/11.12/14.67 to 21.31/19.53/17.73; the run is method-only and does not establish portfolio parity. Raw windows and worker logs are archived in PR #1870.Local method-anchor screen after argument-array optimization (2026-10-25)
The current locally built candidate JAR (SHA-256
9ba2028280fbe4e3e19dfd5701f352e0e214f889772beec55eb9dfed56d06900) completed all seven method-anchor pairs against pinned optimized blead83a6c8b26a8823eb966652414864eb07a3d2c6d4. Checksums matched, pairs were stable, and process priority was verified; on this Darwin hostpsreportsnice -n 19asNI=20, which the runner now normalizes.The method ratio was 0.986x blead (95% paired interval 0.954–1.017). The lower bound remains below 1.00x, so the 1:1 method goal is not met. This is a method-only screen, not the full method/closure/Life acceptance portfolio. Host load averaged 28.46/19.09/21.14 before and 20.96/26.34/24.99 after the run, so treat the result as diagnostic. Full local
makepassed for this candidate. The raw local report isdev/bench/reports/issue-1863-invocant-args-method-screen-blead-83a6c8b.json.Current stable-method candidate screen (diagnostic only; 2026-10-25)
Candidate source commit
2aa86b8fcd85d864184fc9fdc25aaa92d8c1820awas measured against optimized blead83a6c8b26a8823eb966652414864eb07a3d2c6d4. The pinned candidate JAR SHA-256 is20ff0b8c39596de5a04a732e3e99ecf69a31c2b5b72dcfb36cc04147d90c928c. All seven method pairs stabilized and matched checksums. Requested nice 19 was independently observed as DarwinNI=20for both engines and accepted by the corrected runner.The method ratio was 0.957x blead (95% paired interval 0.921–0.994). The interval is fully below 1.00x, so this candidate does not meet the method parity gate. This remains a method-only diagnostic, not the full method/closure/Life acceptance portfolio. Host load averages changed from 6.12/7.61/11.88 before to 9.63/8.98/10.94 after. The candidate's full local test results were recorded from the same tested working-tree contents; its JAR embeds the parent build identity
15df1dac7, while the report pins the exact JAR bytes and source commit. Raw report and worker logs:dev/bench/reports/issue-1863-2aa-method-blead-83a6c8b-quiet.jsonand its-logs/directory.Same-run method comparison against exact origin/master (diagnostic only; 2026-10-25)
The current candidate runtime source is
2aa86b8fcd85d864184fc9fdc25aaa92d8c1820a, with JAR SHA-25620ff0b8c39596de5a04a732e3e99ecf69a31c2b5b72dcfb36cc04147d90c928c. In a randomized seven-pair method comparison against the exactorigin/masterJAR (eaf1bfdb697c81999cf8bcc65b75e611fd6ead3b, SHA-256e38b5feeda9aaa0fe26b829631f9f900618eda52cade59f757cf9a7d5e2a5bad), the candidate measured 1.511x (95% paired interval 1.447–1.579). All pairs stabilized, matched checksums, and verified requested priority (DarwinNI=20). Load averages were 23.55/35.35/25.32 before and 8.55/17.80/20.52 after.This confirms method-anchor progress over exact origin/master. The separate seven-pair comparison against pinned blead for the same candidate measured 0.957x (95% interval 0.921–0.994), so 1:1 Perl parity remains unmet. This JAR-to-JAR comparison is diagnostic attribution evidence, not acceptance. Raw report and logs:
dev/bench/reports/issue-1863-2aa-method-vs-origin.jsonand its-logs/directory. The report's captured Git HEAD is93e60347c(documentation/reporting commit after the runtime source commit); the candidate JAR hash pins the measured artifact.Latest local method-anchor screen after cached-hit split (diagnostic only; 2026-10-25)
The local candidate separates stable-hash method hits from the general cached-method invocation path. Its JAR SHA-256 is
7555c39c73e79453399e3ecf9ebf2446317c31d0766956f8fa4e45a6f47488df. Against optimized blead83a6c8b26a8823eb966652414864eb07a3d2c6d4, seven randomized method-anchor pairs completed with stable warmup, matching checksums, and verified requestednice 19priority (Darwin reportsNI=20). The candidate measured 1.006x blead (95% paired interval 0.967–1.045), compared with 0.957x (0.921–0.994) for the previous local candidate. This is a 5.1% higher central estimate, but the interval crosses 1.00x, so it does not establish 1:1 parity. Host load remained high (16.70/23.69/29.65 before and 15.55/17.70/24.36 after), making this diagnostic progress pending a lower-load repeat. The method result is not full-portfolio acceptance; closure and Life still need to meet the criterion. Report and pair logs:dev/bench/reports/issue-1863-cached-hit-split-method-blead.jsonand its-logs/directory.The local
makecompiled the candidate and completed 2,995 unit tests, but the parallel run had one loopbacktcp_bindfailure inanyevent_server_accept_scope_exit.t. That test passed all three assertions when rerun alone with extended access. No hosted CI result is used for this local measurement.Lower-load repeat for the cached-hit split
A second seven-pair screen used the same candidate JAR and pinned blead revision. All pairs were stable, checksum-matched, and priority-verified. It measured 0.985x blead (95% paired interval 0.968–1.003), with load averages 8.63/9.57/16.02 before and 4.84/6.35/12.20 after. Pooling the fourteen paired ratios from the two cached-hit-split sessions descriptively gives 0.996x (95% interval 0.974–1.018). The pooled estimate is close to parity, but its lower bound remains below 1.00x; this is not acceptance evidence. The second run is
dev/bench/reports/issue-1863-cached-hit-split-method-blead-rerun.jsonand its-logs/directory. Next local work is to profile the current hot call boundaries and allocation sites before selecting another optimization.Cache-miss extraction candidate
The next locally tested candidate moves hash-map lookup and cache creation out of the stable method validator's hot cache-hit path. Its JAR SHA-256 is
dc7c73dc0e8ffafe08da37b76e01e5d69bce38ea4ed2e78cba14bbe7e9e9f3f6; the full localmakepassed in 6m26. Seven stable, checksum-matched, priority-verified method pairs against pinned blead measured 0.986x (95% interval 0.964–1.007). This is essentially unchanged from the prior lower-load screen and does not establish a gain or parity. The JIT validator shrank from 415 to 336 bytes, but still does not inline. Raw results and logs aredev/bench/reports/issue-1863-cache-miss-extraction-method-blead.jsonand its-logs/directory; the inlining summary isdev/bench/reports/issue-1863-cache-miss-extraction-inlining.txt.Unit coverage for the checked fallback transition
Added three assertions to
simple_stable_hash_method.t: a numeric-string field uses checked semantics, is normalized by+=, and the stable integer method path resumes on the next call. All 27 assertions pass under system Perl and the current PerlOnJava JAR. The completemakegate has not yet been rerun after this test-only addition; it will be included in the next full local gate.Invocant-prepend candidate
The next locally validated candidate replaces generic list insertion of the method invocant with a compact-array prepend path; the ordinary-list fallback is unchanged. The focused alias-order unit test and full
nice -n 19 makegate pass. The exact candidate JAR SHA-256 isb308a2964cea2baf89a3900392871cc33a4ab42a9823005b2ebbb8d990528216.A method-only seven-pair screen measured 0.998x blead (95% interval 0.966–1.043). In the full seven-pair #1863 portfolio, the method anchor measured 0.941x (95% interval 0.852–1.011), Closure 1.671x (1.576–1.794), and Life 1.093x (1.043–1.165); the equal-weight portfolio geometric mean was 1.198x (1.152–1.236). The full-run load rose from 6.71/8.83/11.47 to 15.27/19.90/19.27. Although all workloads had seven complete, checksum-matched pairs and the report is protocol-eligible, the method interval still crosses 1.00x and the run was affected by rising host load. The portfolio mean therefore does not establish the #1863 method criterion or full parity. Raw reports and logs are
dev/bench/reports/issue-1863-invocant-prepend-method-blead.json,dev/bench/reports/issue-1863-invocant-prepend-full-blead.json, and their-logs/directories.Next: continue local profiling and compare any candidate against the exact pre-change JAR in a same-run paired screen. No CI result is used for this update.
Same-run attribution for the invocant-prepend change
A balanced seven-pair method comparison against the exact pre-change JAR measured the candidate at 1.006x (95% interval 0.972–1.043). All seven pairs were checksum-matched, priority-verified, and eligible. Candidate JAR SHA-256:
b308a2964cea2baf89a3900392871cc33a4ab42a9823005b2ebbb8d990528216; reference JAR SHA-256:14572d75138dfc19fb3d44c388765a975b32faa492d82d953d8cb43fe16402fc. The interval crosses 1.00x, so this suggests a small gain but does not establish it or blead parity. Full raw results are indev/bench/reports/issue-1863-invocant-prepend-vs-parent-method.jsonand its-logs/directory.Guarded prepend bookkeeping follow-up
A follow-up skips
prepareStoredValuebookkeeping only while the stable-method path has root tracking suppressed; container-owner marking and ordinary storage fallback remain. Its full localmakegate passed. In a seven-pair candidate/reference method comparison, the candidate measured 0.990x (95% interval 0.943–1.032); all pairs were eligible. Load rose from 5.87/12.35/19.77 to 13.90/15.05/18.58. The interval overlaps the earlier prepend-only result of 1.006x, so these separate runs cannot establish whether the extra shortcut helps or hurts. Candidate SHA-256:b838691f4d2914757711c2bd989a835c129db9316c65d95906594004e74b0def; reference SHA-256:14572d75138dfc19fb3d44c388765a975b32faa492d82d953d8cb43fe16402fc. Raw results:dev/bench/reports/issue-1863-invocant-prepend-root-skip-vs-parent-method.jsonand its-logs/directory.Second full portfolio for the current JAR
A second 14-pair full portfolio on the same candidate JAR had 14 eligible pairs per workload. Method measured 1.010x blead (95% interval 0.990–1.033), Closure 1.671x (1.593–1.760), Life 1.070x (1.010–1.138), and the equal-weight portfolio geometric mean was 1.218x (1.187–1.250). The method lower bound still misses 1.00x; Closure and Life clear it. Load rose from 6.51/10.90/12.88 to 36.11/27.22/23.83. Pooling the matching seven-pair method screen with both full portfolios gives an exploratory 1.031x across 33 eligible pairs (95% interval 1.003–1.069), but this combines separate sessions and is not parity acceptance evidence. Raw report:
dev/bench/reports/issue-1863-root-skip-14pair-full-blead-rerun.jsonand its-logs/directory.First 14-pair portfolio for this candidate
The first 14-pair full run on candidate JAR
b838691f4d2914757711c2bd989a835c129db9316c65d95906594004e74b0defhad 12 complete method pairs (two were unstable) and 14 pairs each for Closure and Life. Method measured 1.070x (95% interval 0.997–1.167), Closure 1.584x (1.549–1.625), Life 1.076x (1.010–1.122), and portfolio geometric mean 1.236x (1.208–1.269). The method lower bound misses 1.00x. Raw data:dev/bench/reports/issue-1863-root-skip-14pair-full-blead.jsonand its-logs/directory.Local parity candidate: pooled method arguments
JFR showed that pooled method argument arrays were cleared both when recycled and again on checkout. Since recycling is the only path that stores an array in the pool and clears it before storage, the redundant checkout reset was removed. The focused reuse test verifies aliased elements and alias state are cleared.
nice -n 19 timeout 3600 makepassed in 8m38.Against the exact prior candidate JAR, a balanced seven-pair method comparison measured 1.051x (95% interval 1.016–1.100); all pairs were eligible and checksum-matched. Candidate JAR SHA-256:
7387f191eafab020ad3af8f1b1b30bef2e5f64d7119c348d919a667e458524aa. The attribution report isdev/bench/reports/issue-1863-pool-checkout-clear-vs-before-method.json.The full 14-pair portfolio on this exact JAR had 13 eligible method pairs and 14 each for Closure and Life. Method measured 1.087x blead (95% interval 1.007–1.187), Closure 1.565x (1.522–1.615), Life 1.058x (1.005–1.113), and the equal-weight portfolio geometric mean 1.219x (1.188–1.249). One method pair was excluded by checksum/eligibility checks. All three workload lower bounds clear 1.00x in this single full run, meeting the local parity criterion. Report:
dev/bench/reports/issue-1863-pool-checkout-clear-14pair-full-blead.jsonand its-logs/directory. The benchmark is tied to the measured candidate JAR; PR-source alignment and its build/CI checks are still pending.PR-source parity candidate
I validated the current PR source separately because it had diverged from the earlier local candidate. Before porting the latest optimizations, the PR-head candidate measured 0.973x blead (95% interval 0.940–0.995) after rechecking recorded niceness; that source did not meet parity.
The PR candidate now includes the revisioned stable-hash field-cell cache with mutation/view invalidation, compact invocant prepend, execution-state argument-array reuse, removal of the duplicate pool-checkout reset, and the priority-verification fix. The full
nice -n 19 timeout 3600 makegate passed in 8m17. On JAR SHA-25624e93fd8e555725c7291ac306d86fe10c155604e5f85d9a8e8ac859c6023e490, the 14-pair pinned blead portfolio measured method 1.059x (95% interval 1.040–1.088), Closure 1.547x (1.524–1.564), and Life 1.100x (1.058–1.167). All 42 engine runs had matching checksums and verified priority; portfolio geometric mean was 1.217x (1.197–1.243). Report and raw logs:dev/bench/reports/issue-1863-pr-port-full-14pair-blead.jsonand its-logs/directory. This candidate meets the local criterion. Commit548eb9f533414011e298ea3f90e2e8fff2496d8cis pushed to PR #1870; its build and pinned-portfolio checks are in progress.perf: pursue measured 1:1 Perl throughput (#1863) (#1870)
fglock commentedon Oct 26, 2026
The throughput acceptance checks are met by merged PR #1870: the 14-pair pinned blead report has lower 95% bounds above 1.00x for method, closure, and bit-packed Life. The broader memory accounting and call-shape profiling are unfinished; follow-up #1885 tracks them. Reopening this issue keeps that remaining scope visible.
fglock commentedon Oct 26, 2026
Merged the performance investigation workflow in PR #1886: dev/bench/README.md — Performance investigation workflow. It documents pinned baselines, exact-parent attribution, equal-work checks, JFR outside scored runs, paired measurements, and batching expensive validation. The
profile-perlonjavaskill now follows the same process.The default
examples/life_bitpacked.plterminal-output path is now called out as a separate I/O performance dimension from compute-only Life. The reported ~0.5x Perl result should be measured with matching sinks and output-byte verification; PTY and redirected-output runs should be reported separately.