perf: achieve measured 1:1 standard Perl throughput after #1850
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 20/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Lĩnh vực
- performance, testing-qa
Hướng nghiên cứu
Start with #1846, #1196, and #1850, then inspect the design documents under dev/design/ and the benchmark and test entry points named in those issues or PRs. First establish the durable benchmark baseline and pinned Perl references described here; the recent runner and raw results are only noted as residing under /private/tmp. Done means each fixed workload meets its stated parity criterion, memory use is quantified, regression coverage and the full make gate pass, and reproducible evidence is published.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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 #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 #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
- #1846 — method-call throughput parity
- #1196 — closure calls and bit-packed Life
- #1850 — current memory/allocation improvements and regression coverage
- Ngôn ngữ chính
- Perl
- Star
- 65
- Fork
- 8
- Merge trung bình
- 5 giờ 56 phút
- Pull request đã merge (30 ngày)
- 184
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của fglock/PerlOnJava
-
area:runtime documentation enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
fglock/PerlOnJava#1579 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Port Devel::Size for PerlOnJavaĐang mởarea:cpan-port enhancement help wanted
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
fglock/PerlOnJava#1880 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area:memory area:performance area:runtime bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 52/100
fglock/PerlOnJava#1860 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area:performance enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
fglock/PerlOnJava#1846 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area:parser enhancement
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 45/100
fglock/PerlOnJava#1808 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của fglock/PerlOnJava
Issue tương tự
-
✏️ Editing - Tags
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
openfoodfacts/openfoodfacts-server#15127 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
FIDO2 (ecdsa-sk / ed25519-sk) ingress keys rejected: missing in get_supported_ssh_algorithms_listĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
ovh/the-bastion#695 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
darold/pgFormatter#425 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
observablt-ci
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
elastic/golang-crossbuild#840 ·
Maintainer thường phản hồi trong vòng 1 ngày