perf(bytecode): VM list-iterate with the counted for pass (#482) #520

Merged
argus merged 2 commits from loop/482-vm-list-iterate into main 2026-10-27 09:33:45 +00:00
Collaborator

Closes #482

The counted for loop over a list ran 3x slower in the VM than before #475 (issue #482). Commit 1 widens the guard of tools/collection-cost.sh to compiler/src/backend/bytecode and compiler/src/vm, so this PR's tier B measures the VM, and prints the bytecode of benchmarks/list-iterate.trb for base and head. Commit 2 is the fix.

Root cause. The bytecode of the new loop is minimal (less, branch, one load with the list-item step, three adds), so the emitter is not at fault. kernelCall (compiler/src/vm/interpret.trb) turned the KernelOperation into its number with kernelNumberOf (compiler/src/backend/bytecode/format.trb), a linear scan over allKernelOperations. ElementAddress (what list-index uses) sits near the front of the table, ListItemAddress (operation 68, added late) near the back, so every item read scanned ~68 entries before the kernel ran: ~500 ns per read, 80M reads, 62 s - 20 s.

Fix. kernelNumberOf is a match, generated from the table in the table's order, so the C TORB_OPERATION_* numbering and the table are unchanged. compiler/tests/bytecode.test.trb already pinned "every operation maps to its index"; it now also pins that the table's last operation stays below kernelNativeBase.

Test. Tier B (tools/collection-cost.sh), VM fastest of 3, criteria: list-iterate <= ~22 400 ms (pre-#475 baseline in the issue: 20 339-20 828 ms), list-index <= 1.10x, native <= 1.7x, allocations 22/22.

  • Before (run 1987, head 8cd52b0f, merge base already carries #475): list-index 22 672 -> 23 177 ms, list-iterate 62 358 -> 61 511 ms (noise floor; native 1.48x / 1.58x; allocations 22/22).
  • After (run 2004, head 00a63378, the same two commits before the rebase onto the current main; forge CI green, tier A/B and gates): list-index 23 217 -> 23 476 ms (1.011x), list-iterate 62 321 -> 12 143 ms (5.1x faster; the pre-#475 baseline was 20 339-20 828 ms, so the fix also beats it: the item read no longer scans the table at all, #475's smaller loop now pays off); native ratios unchanged (list-iterate 1.60x, list-index 6.19x -> 6.41x with the usual noise); allocations 22/22; hello-world native size 0 bytes; bytes-pass 0.860; round trip 0.971 of the one before.
  • tools/collection-cost.sh compares to the merge base, which already carries #475, so its "base" row is the slow one; the pre-#475 numbers come from the issue.
  • tools/check-commits.sh origin/main HEAD: clean.
Closes #482 The counted `for` loop over a list ran 3x slower in the VM than before #475 (issue #482). Commit 1 widens the guard of `tools/collection-cost.sh` to `compiler/src/backend/bytecode` and `compiler/src/vm`, so this PR's tier B measures the VM, and prints the bytecode of `benchmarks/list-iterate.trb` for base and head. Commit 2 is the fix. **Root cause.** The bytecode of the new loop is minimal (`less`, `branch`, one `load` with the list-item step, three adds), so the emitter is not at fault. `kernelCall` (`compiler/src/vm/interpret.trb`) turned the `KernelOperation` into its number with `kernelNumberOf` (`compiler/src/backend/bytecode/format.trb`), a linear scan over `allKernelOperations`. `ElementAddress` (what `list-index` uses) sits near the front of the table, `ListItemAddress` (operation 68, added late) near the back, so every item read scanned ~68 entries before the kernel ran: ~500 ns per read, 80M reads, 62 s - 20 s. **Fix.** `kernelNumberOf` is a `match`, generated from the table in the table's order, so the C `TORB_OPERATION_*` numbering and the table are unchanged. `compiler/tests/bytecode.test.trb` already pinned "every operation maps to its index"; it now also pins that the table's last operation stays below `kernelNativeBase`. **Test.** Tier B (`tools/collection-cost.sh`), VM fastest of 3, criteria: `list-iterate` <= ~22 400 ms (pre-#475 baseline in the issue: 20 339-20 828 ms), `list-index` <= 1.10x, native <= 1.7x, allocations 22/22. - Before (run 1987, head 8cd52b0f, merge base already carries #475): `list-index` 22 672 -> 23 177 ms, `list-iterate` 62 358 -> 61 511 ms (noise floor; native 1.48x / 1.58x; allocations 22/22). - After (run 2004, head 00a63378, the same two commits before the rebase onto the current `main`; forge CI green, tier A/B and gates): `list-index` 23 217 -> 23 476 ms (1.011x), **`list-iterate` 62 321 -> 12 143 ms** (5.1x faster; the pre-#475 baseline was 20 339-20 828 ms, so the fix also beats it: the item read no longer scans the table at all, #475's smaller loop now pays off); native ratios unchanged (`list-iterate` 1.60x, `list-index` 6.19x -> 6.41x with the usual noise); allocations 22/22; hello-world native size 0 bytes; bytes-pass 0.860; round trip 0.971 of the one before. - `tools/collection-cost.sh` compares to the merge base, which already carries #475, so its "base" row is the slow one; the pre-#475 numbers come from the issue. - `tools/check-commits.sh origin/main HEAD`: clean.
chore(tools): measure the bytecode and the VM in collection-cost.sh
All checks were successful
ci / commit messages (pull_request) Successful in 7s
ci / what the change touches (pull_request) Successful in 6s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 16s
ci / the playground (torb as WebAssembly) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 15m41s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 3m0s
ci / tier A (linux-x64) (pull_request) Successful in 29m16s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
9030a853d8
The guard now also fires for a branch that touches compiler/src/backend/bytecode or compiler/src/vm, and the
script prints the bytecode of the chunks of benchmarks/list-iterate.trb for the merge base and this checkout
(#482).
orion force-pushed loop/482-vm-list-iterate from 9030a853d8
All checks were successful
ci / commit messages (pull_request) Successful in 7s
ci / what the change touches (pull_request) Successful in 6s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 16s
ci / the playground (torb as WebAssembly) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 15m41s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 3m0s
ci / tier A (linux-x64) (pull_request) Successful in 29m16s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
to f9acf31b5f
Some checks failed
ci / commit messages (pull_request) Has been cancelled
ci / what the change touches (pull_request) Has been cancelled
ci / gates (pull_request) Has been cancelled
2026-10-27 00:36:37 +00:00
Compare
orion force-pushed loop/482-vm-list-iterate from f9acf31b5f
Some checks failed
ci / commit messages (pull_request) Has been cancelled
ci / what the change touches (pull_request) Has been cancelled
ci / gates (pull_request) Has been cancelled
to 8cd52b0f72
All checks were successful
ci / commit messages (pull_request) Successful in 7s
ci / what the change touches (pull_request) Successful in 6s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 2s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 16s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 29m2s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 3m8s
ci / tier B (linux-x64) (pull_request) Successful in 29m9s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
2026-10-27 01:02:43 +00:00
Compare
orion force-pushed loop/482-vm-list-iterate from 8cd52b0f72
All checks were successful
ci / commit messages (pull_request) Successful in 7s
ci / what the change touches (pull_request) Successful in 6s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 2s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 16s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 29m2s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 3m8s
ci / tier B (linux-x64) (pull_request) Successful in 29m9s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
to 00a63378d5
All checks were successful
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 9s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m43s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 24m51s
ci / tier A (linux-x64) (pull_request) Successful in 27m25s
ci / pack the seed (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m32s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m22s
ci / every host emits the same C (pull_request) Successful in 5m7s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
2026-10-27 03:23:45 +00:00
Compare
orion force-pushed loop/482-vm-list-iterate from 00a63378d5
All checks were successful
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 9s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m43s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 24m51s
ci / tier A (linux-x64) (pull_request) Successful in 27m25s
ci / pack the seed (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m32s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m22s
ci / every host emits the same C (pull_request) Successful in 5m7s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
to 24803ba850
All checks were successful
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 9s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 7m4s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 26m38s
ci / tier B (linux-x64) (pull_request) Successful in 24m25s
ci / pack the seed (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m30s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m22s
ci / every host emits the same C (pull_request) Successful in 5m10s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
2026-10-27 06:31:51 +00:00
Compare
orion changed title from WIP: perf(bytecode): VM list-iterate with the counted for pass (#482) to perf(bytecode): VM list-iterate with the counted for pass (#482) 2026-10-27 06:32:23 +00:00
orion requested review from argus 2026-10-27 06:32:24 +00:00
argus approved these changes 2026-10-27 09:33:44 +00:00
argus left a comment

Approved.

  • Tests: ok. bytecode.test.trb already pinned "every operation maps to its index"; the new test pins the last operation and last < kernelNativeBase. CI green on this head (tier A/B, gates, pdisc, commit messages).
  • Correctness: ok. I checked the 91 match arms against allKernelOperations: same order, same numbers, and the set equals the KernelOperation cases, so the C TORB_OPERATION_* numbering is unchanged and the match is exhaustive.
  • Scope: ok. Issue #482 only: the fix plus the measurement guard in tools/collection-cost.sh (measurement only, exits 0).
  • Security/data/docs/architecture: no findings; no boundary change.
  • Performance: PR body documents before/after on tier B (list-iterate 62 s to 12 s, list-index within noise, allocations 22/22).

Non-blocking: the match must be extended by hand when an operation is added; the index-equals-table test catches a missing or wrong arm.

Approved. - Tests: ok. `bytecode.test.trb` already pinned "every operation maps to its index"; the new test pins the last operation and `last < kernelNativeBase`. CI green on this head (tier A/B, gates, pdisc, commit messages). - Correctness: ok. I checked the 91 `match` arms against `allKernelOperations`: same order, same numbers, and the set equals the `KernelOperation` cases, so the C `TORB_OPERATION_*` numbering is unchanged and the match is exhaustive. - Scope: ok. Issue #482 only: the fix plus the measurement guard in `tools/collection-cost.sh` (measurement only, exits 0). - Security/data/docs/architecture: no findings; no boundary change. - Performance: PR body documents before/after on tier B (`list-iterate` 62 s to 12 s, `list-index` within noise, allocations 22/22). Non-blocking: the match must be extended by hand when an operation is added; the index-equals-table test catches a missing or wrong arm.
argus merged commit 70cddb4324 into main 2026-10-27 09:33:45 +00:00
argus deleted branch loop/482-vm-list-iterate 2026-10-27 09:33:45 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!520
No description provided.