perf: reduce warm jit coordination overhead - #119
Conversation
📝 WalkthroughWalkthroughThe PR caches interpreter cancellation state, replaces entry-fallback anchor lookups with a per-function slice, precomputes JIT function lookups, reuses slices in tracer cloning, and adds benchmark documentation for a JIT coordination workload. ChangesInterpreter fast-path optimizations
Estimated code review effort: 4 (Complex) | ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
docs/benchmarks.md (1)
174-183: 📐 Maintainability & Code Quality | 🔵 TrivialKeep this subsection factual and reproducible.
Before/Currentdoes not identify the baseline, and the final sentence attributes the win to internal mechanisms that the benchmark table itself does not establish. Rename the columns to the actual modes (threaded/JIT) and either cite the profiling evidence or move the mechanism explanation todocs/jit-internals.md.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/benchmarks.md` around lines 174 - 183, The benchmark subsection mixes an unclear baseline label and an unsupported mechanism claim, so make it factual and reproducible. Update the table headers in the `BenchmarkJITIssue101` section to use the actual modes (`threaded` and `JIT`) instead of `Before`/`Current`, and remove or relocate the final sentence about warm-entry fallback checks and no-op safepoints unless you can cite profiling evidence for it. If the explanation is needed, move it to `docs/jit-internals.md` and keep `docs/benchmarks.md` limited to the measured results.interp/jit.go (1)
221-244: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winCache the address→function map
emit()still rebuildsfuncsby scanning every livei.instrsslot on each compile. Cache that lookup on the interpreter/compiler and invalidate it frombind/remove; rename the inneraddr/fnvariables to avoid shadowing the parameters.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@interp/jit.go` around lines 221 - 244, The emit method is rebuilding the address-to-function lookup on every call by scanning all live i.instrs entries, so move that map into a cached field on the Interpreter or compiler and reuse it across emits. Update the cache from bind and remove so it stays correct when instructions change, and adjust emit plus its inner loop to stop shadowing the addr and fn parameters by using distinct local names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@docs/benchmarks.md`:
- Around line 174-183: The benchmark subsection mixes an unclear baseline label
and an unsupported mechanism claim, so make it factual and reproducible. Update
the table headers in the `BenchmarkJITIssue101` section to use the actual modes
(`threaded` and `JIT`) instead of `Before`/`Current`, and remove or relocate the
final sentence about warm-entry fallback checks and no-op safepoints unless you
can cite profiling evidence for it. If the explanation is needed, move it to
`docs/jit-internals.md` and keep `docs/benchmarks.md` limited to the measured
results.
In `@interp/jit.go`:
- Around line 221-244: The emit method is rebuilding the address-to-function
lookup on every call by scanning all live i.instrs entries, so move that map
into a cached field on the Interpreter or compiler and reuse it across emits.
Update the cache from bind and remove so it stays correct when instructions
change, and adjust emit plus its inner loop to stop shadowing the addr and fn
parameters by using distinct local names.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a5558543-b79f-408a-a6c3-e12cb45d80ea
📒 Files selected for processing (4)
docs/benchmarks.mdinterp/interp.gointerp/jit.gointerp/trace.go
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #119 +/- ##
==========================================
- Coverage 46.80% 46.79% -0.02%
==========================================
Files 77 77
Lines 17319 17340 +21
==========================================
+ Hits 8107 8114 +7
- Misses 8297 8307 +10
- Partials 915 919 +4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
fallbacks[anchor{addr, 0}]map lookup with a dense per-function entry fallback slice.BenchmarkJITIssue101results.Why
BenchmarkJITIssue101is a branch-heavy batch workload with many tiny tree-score functions over a mutablef64feature row. After traces are installed, the remaining cost was dominated by interpreter coordination rather than useful VM work. The prior profile showedsafepointandruntime.mapaccess1as the main overhead on the JIT path.This keeps the existing design intact: the threaded interpreter remains the correctness source, JIT behavior stays speculative with fallback, and ARM64-specific lowering remains unchanged.
Results
Measured on
darwin/arm64, Apple M4 Pro:BenchmarkJITIssue101BenchmarkJITIssue101Additional checks:
BenchmarkJITIssue60remained within expected noise; focused A/B forclosure_counter_loop/jitwas 1,076 ns/op on this branch vs 1,132 ns/op onmainunder the same command.BenchmarkFib35/minivm_jitremained around 49 ms/op under the planned regression command.safepointat 0.65% cumulative and removedruntime.mapaccess1as the JIT coordination hotspot.Validation
make lintgo test -count=1 -race ./interp ./asm/...go test -count=1 ./...cd benchmarks && go test -run='^$' -bench='BenchmarkJITIssue101/(interp|jit)$' -benchmem -benchtime=3s ./...cd benchmarks && go test -run='^$' -bench='BenchmarkJITIssue60|BenchmarkFib35/minivm_(interp|jit)$' -benchmem -benchtime=3s ./...Summary by CodeRabbit
Documentation
Performance Improvements
Bug Fixes
Refactor