Skip to content

ci(benchmark): compare PR against a same-runner main build#886

Merged
frostney merged 6 commits into
mainfrom
claude/beautiful-feistel-ce5255
Jun 27, 2026
Merged

ci(benchmark): compare PR against a same-runner main build#886
frostney merged 6 commits into
mainfrom
claude/beautiful-feistel-ce5255

Conversation

@frostney

@frostney frostney commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fixes the unreliable PR "Benchmark Results" verdicts (Benchmark PR comparison is unreliable — baseline is a cached run from a different runner, so deltas reflect runner variance, not the diff #815). The comparison previously measured the PR run against a main baseline cached from a different job, on a different GitHub-hosted runner, at a different time. Cross-runner variance is systematically larger than each run's own min/max spread, so the range-overlap classifier flipped large numbers of unrelated benchmarks to 🟢 improved / 🔴 regressed — e.g. perf(regexp): memoize the decoded subject across regex VM calls #805 (regex-decode only) reported arraybuffer.js/arrays.js, which use no regex, as broadly improved.
  • Same-runner A/B: a new build-main job builds the benchmark runner from the PR's base commit (github.event.pull_request.base.sha), and the benchmark job benchmarks that main build and the PR build back-to-back on the same runner, after a warm-up discard of both binaries. The range-overlap classifier is unchanged — it now compares two runs measured under the same conditions, so the systematic between-runner offset cancels.
  • Self-contained: the deterministic profile diff is regenerated from the same main build; the dead cross-runner benchmark-*-baseline-* and profile-baseline-* caches (ci.yml saves + pr.yml restores) are removed. The separate test262-baseline cache is untouched.
  • Testability: the ~200-line inline github-script comparison moved to scripts/benchmark-compare.js with unit tests (scripts/test-benchmark-compare.ts) wired into both cli jobs; the comment now reports the measured median per-run variance as a noise floor.

Key constraints / non-goals (confirmed via grilling):

  • Cost: building + benchmarking main in every PR run roughly doubles the benchmark job's CI time — the accepted price of a trustworthy comparison.
  • Advisory, not gating: the comparison stays comment-only (never merge-blocking). Even same-runner measurement has a noise floor; VISION.md deprioritizes raw throughput; test262 remains the gating regression check.
  • Graceful degradation: the main-base run is continue-on-error so a PR that adds/changes a benchmark main cannot run is not blocked — such benchmarks degrade to 🆕 new. The whole main build is optional too: if build-main fails, benchmark still runs (if: !cancelled() && needs.build.result == 'success') and posts PR-only numbers rather than going silent.
  • No engine/Pascal behavior change. Rationale recorded in ADR 0076. Per-file interleaving is noted as a possible future refinement.

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
  • Updated documentation
    • ADR 0076 (+ index), docs/build-system.md, docs/benchmarks.md; corrected stale cache-save descriptions in both docs.
  • Optional: native Pascal tests — N/A (no AST/scope/evaluator/value-type change).
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change
    • This change is the benchmark-comparison methodology; the new comparator is unit-tested.

Closes #815

The PR "Benchmark Results" comment classified benchmarks by comparing the
PR run against a cached `main` baseline measured on a different runner at a
different time. Cross-runner variance dwarfs each run's own min/max spread,
so the range-overlap classifier flipped large numbers of unrelated
benchmarks to improved/regressed (e.g. #805, a regex-only change, reported
non-regex benchmarks as improved). The verdicts were not actionable.

Build the PR's base commit in a new `build-main` job and benchmark that
`main` build and the PR build back-to-back on the same runner, after a
warm-up discard of both binaries, so deltas reflect the diff rather than
infrastructure. The range-overlap classifier is unchanged; it now compares
two runs measured under the same conditions. The `main`-base run is
`continue-on-error` so a PR that adds a benchmark `main` cannot run is not
blocked (it degrades to new). The comparison stays advisory (comment-only).

- Extract the ~200-line inline comparison into scripts/benchmark-compare.js
  with unit tests (scripts/test-benchmark-compare.ts), wired into both cli
  jobs; report the measured median per-run variance as a noise floor.
- Regenerate the deterministic profile diff from the same `main` build and
  remove the dead cross-runner benchmark/profile baseline caches.
- Add ADR 0076 and update docs/build-system.md and docs/benchmarks.md.

Closes #815

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview Jun 27, 2026 2:13pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c1526ccc-b47d-4731-b115-a35d35b08fb8

📥 Commits

Reviewing files that changed from the base of the PR and between 4275c38 and e30b90b.

📒 Files selected for processing (1)
  • .github/workflows/pr.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pr.yml

📝 Walkthrough

Walkthrough

The PR moves benchmark comparison to a same-runner main-versus-PR flow, adds a shared comparison script and tests, updates CI and PR workflows to produce and consume main artifacts, and refreshes related docs and ADR references.

Changes

Same-runner benchmark comparison

Layer / File(s) Summary
Comparison script and tests
scripts/benchmark-compare.js, scripts/test-benchmark-compare.ts
Adds the benchmark comparison module and unit tests for range-overlap classification, variance calculation, aggregation, and Markdown output.
Build and publish main artifacts
.github/workflows/pr.yml
Adds a base-commit build job and extends the PR benchmark job to run same-runner benchmarks, capture main-side profiles, and upload main benchmark artifacts.
Comment flow and profile diffs
.github/workflows/pr.yml, scripts/profile-diff.js
Downloads the main artifacts in the comment job, generates deterministic profile diffs from the main and current profiles, and compares current benchmark data against optional main baselines.
CI validation steps
.github/workflows/ci.yml, .github/workflows/pr.yml
Updates the CI benchmark job to validate JSON output and stop saving benchmark/profile baselines, and adds the benchmark-comparison test step to the CI and PR CLI jobs.
Docs and ADR references
docs/adr/0076-same-runner-benchmark-comparison.md, docs/adr/README.md, docs/benchmarks.md, docs/build-system.md
Adds the ADR entry and updates benchmark and build-system documentation to describe same-runner benchmark comparison and the new profile wording.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • frostney/GocciaScript#55: Both PRs adjust benchmark comparison and comment generation across main-versus-PR benchmark modes.
  • frostney/GocciaScript#144: Related through the range-based benchmark comparison flow and comment formatting logic that this PR replaces.
  • frostney/GocciaScript#500: Related through deterministic profile handling and profile-diff behavior in benchmark CI.

Suggested labels

documentation, new feature

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly describes the main change: comparing PR benchmarks against a same-runner main build.
Description check ✅ Passed The description matches the template well, covering Summary and Testing with key constraints, non-goals, and the linked issue.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

430 benchmarks · PR vs same-runner main build

Interpreted: 🟢 33 improved · 🔴 30 regressed · 367 unchanged · avg +1.1%
Bytecode: 🟢 41 improved · 🔴 46 regressed · 343 unchanged · avg +1.8%

Typical per-run noise (median variance): interpreted ±2.8%, bytecode ±2.1%. Deltas within noise overlap and read as unchanged.

arraybuffer.js — Interp: 🔴 2, 12 unch. · avg -1.4% · Bytecode: 🟢 2, 🔴 1, 11 unch. · avg +2.2%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
create ArrayBuffer(0) 124,001 ops/sec [106,465..146,193] → 123,457 ops/sec [117,840..131,820] ~ overlap (-0.4%) 160,817 ops/sec [146,148..252,761] → 158,159 ops/sec [149,096..167,266] ~ overlap (-1.7%)
create ArrayBuffer(64) 120,345 ops/sec [114,278..134,680] → 122,810 ops/sec [118,992..125,525] ~ overlap (+2.0%) 152,254 ops/sec [150,487..160,768] → 184,787 ops/sec [165,314..217,984] 🟢 +21.4%
create ArrayBuffer(1024) 105,051 ops/sec [58,203..106,563] → 108,739 ops/sec [103,592..152,079] ~ overlap (+3.5%) 133,970 ops/sec [132,905..182,664] → 138,444 ops/sec [137,288..139,377] ~ overlap (+3.3%)
create ArrayBuffer(8192) 69,717 ops/sec [66,754..78,161] → 64,756 ops/sec [63,526..65,663] 🔴 -7.1% 87,680 ops/sec [81,411..91,487] → 81,286 ops/sec [78,339..88,412] ~ overlap (-7.3%)
slice full buffer (64 bytes) 98,319 ops/sec [95,434..122,247] → 96,301 ops/sec [95,946..96,647] ~ overlap (-2.1%) 119,417 ops/sec [118,192..122,668] → 123,163 ops/sec [122,285..123,752] ~ overlap (+3.1%)
slice half buffer (512 of 1024 bytes) 91,752 ops/sec [90,799..95,560] → 90,402 ops/sec [88,359..100,285] ~ overlap (-1.5%) 113,298 ops/sec [72,716..119,534] → 113,252 ops/sec [113,020..114,730] ~ overlap (-0.0%)
slice with negative indices 88,291 ops/sec [85,134..93,846] → 83,618 ops/sec [82,806..84,691] 🔴 -5.3% 115,134 ops/sec [114,484..115,639] → 116,365 ops/sec [114,498..119,596] ~ overlap (+1.1%)
slice empty range 94,100 ops/sec [93,130..94,962] → 94,313 ops/sec [93,796..95,112] ~ overlap (+0.2%) 119,487 ops/sec [119,286..119,907] → 117,640 ops/sec [114,840..118,490] 🔴 -1.5%
byteLength access 273,149 ops/sec [269,771..289,497] → 277,000 ops/sec [273,466..277,891] ~ overlap (+1.4%) 328,255 ops/sec [327,105..329,619] → 326,684 ops/sec [317,417..366,461] ~ overlap (-0.5%)
Symbol.toStringTag access 237,684 ops/sec [215,837..249,930] → 227,524 ops/sec [219,489..232,040] ~ overlap (-4.3%) 242,842 ops/sec [242,016..243,059] → 243,658 ops/sec [242,742..245,528] ~ overlap (+0.3%)
ArrayBuffer.isView 170,608 ops/sec [168,605..171,736] → 168,396 ops/sec [166,515..169,788] ~ overlap (-1.3%) 233,098 ops/sec [227,815..233,896] → 258,748 ops/sec [235,090..288,716] 🟢 +11.0%
clone ArrayBuffer(64) 127,771 ops/sec [126,394..130,071] → 125,470 ops/sec [124,537..127,359] ~ overlap (-1.8%) 174,245 ops/sec [173,231..190,943] → 178,481 ops/sec [173,997..193,340] ~ overlap (+2.4%)
clone ArrayBuffer(1024) 115,929 ops/sec [111,679..117,065] → 112,665 ops/sec [111,474..113,271] ~ overlap (-2.8%) 151,260 ops/sec [149,100..152,489] → 149,252 ops/sec [147,362..160,258] ~ overlap (-1.3%)
clone ArrayBuffer inside object 84,797 ops/sec [83,186..85,061] → 84,090 ops/sec [83,497..84,507] ~ overlap (-0.8%) 104,257 ops/sec [103,610..119,514] → 105,255 ops/sec [103,332..114,365] ~ overlap (+1.0%)
arrays.js — Interp: 19 unch. · avg +1.3% · Bytecode: 🟢 1, 🔴 2, 16 unch. · avg -0.5%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
Array.from length 100 3,551 ops/sec [3,119..4,009] → 3,245 ops/sec [2,992..3,719] ~ overlap (-8.6%) 3,100 ops/sec [2,889..4,604] → 3,072 ops/sec [3,062..3,085] ~ overlap (-0.9%)
Array.from 10 elements 66,073 ops/sec [64,681..73,547] → 69,879 ops/sec [63,583..72,360] ~ overlap (+5.8%) 74,922 ops/sec [72,825..79,372] → 78,518 ops/sec [74,664..86,140] ~ overlap (+4.8%)
Array.of 10 elements 85,610 ops/sec [79,824..86,719] → 84,458 ops/sec [82,764..85,507] ~ overlap (-1.3%) 107,755 ops/sec [105,608..108,500] → 114,222 ops/sec [107,758..115,040] ~ overlap (+6.0%)
spread into new array 92,410 ops/sec [89,149..92,681] → 93,820 ops/sec [91,499..113,075] ~ overlap (+1.5%) 55,341 ops/sec [55,183..59,293] → 54,183 ops/sec [53,919..54,521] 🔴 -2.1%
map over 50 elements 5,031 ops/sec [4,933..5,278] → 5,930 ops/sec [5,175..6,084] ~ overlap (+17.9%) 5,815 ops/sec [5,688..6,042] → 5,707 ops/sec [5,671..5,722] ~ overlap (-1.9%)
filter over 50 elements 4,801 ops/sec [4,669..4,851] → 4,896 ops/sec [4,718..4,954] ~ overlap (+2.0%) 5,716 ops/sec [5,614..5,768] → 5,853 ops/sec [5,603..5,859] ~ overlap (+2.4%)
reduce sum 50 elements 5,369 ops/sec [5,281..5,426] → 5,347 ops/sec [5,290..5,384] ~ overlap (-0.4%) 5,474 ops/sec [5,371..5,850] → 5,652 ops/sec [5,517..5,672] ~ overlap (+3.2%)
forEach over 50 elements 3,643 ops/sec [3,547..4,319] → 3,645 ops/sec [3,632..3,655] ~ overlap (+0.0%) 5,784 ops/sec [5,699..5,908] → 5,909 ops/sec [5,772..6,030] ~ overlap (+2.2%)
find in 50 elements 7,095 ops/sec [7,025..7,225] → 6,960 ops/sec [6,914..7,220] ~ overlap (-1.9%) 7,483 ops/sec [7,277..7,637] → 7,520 ops/sec [7,386..7,583] ~ overlap (+0.5%)
sort 20 elements 4,365 ops/sec [4,323..4,526] → 4,315 ops/sec [4,240..4,356] ~ overlap (-1.1%) 4,908 ops/sec [4,848..5,178] → 4,874 ops/sec [4,804..4,926] ~ overlap (-0.7%)
flat nested array 40,564 ops/sec [39,917..47,534] → 39,647 ops/sec [39,504..40,150] ~ overlap (-2.3%) 47,238 ops/sec [44,731..51,248] → 45,762 ops/sec [45,227..46,413] ~ overlap (-3.1%)
flatMap 21,525 ops/sec [20,772..22,802] → 21,210 ops/sec [21,003..21,387] ~ overlap (-1.5%) 24,090 ops/sec [23,529..24,269] → 24,404 ops/sec [24,290..24,483] 🟢 +1.3%
map inside map (5x5) 5,642 ops/sec [5,609..5,653] → 5,881 ops/sec [5,554..6,142] ~ overlap (+4.2%) 6,737 ops/sec [6,241..7,203] → 6,460 ops/sec [6,356..6,475] ~ overlap (-4.1%)
filter inside map (5x10) 3,771 ops/sec [3,729..3,826] → 3,863 ops/sec [3,776..4,181] ~ overlap (+2.4%) 4,538 ops/sec [4,445..5,511] → 4,529 ops/sec [4,505..4,571] ~ overlap (-0.2%)
reduce inside map (5x10) 4,365 ops/sec [4,350..4,392] → 4,384 ops/sec [4,342..4,506] ~ overlap (+0.4%) 5,104 ops/sec [4,506..5,561] → 4,640 ops/sec [4,260..4,664] ~ overlap (-9.1%)
forEach inside forEach (5x10) 3,066 ops/sec [3,037..3,651] → 3,055 ops/sec [2,994..3,318] ~ overlap (-0.4%) 5,134 ops/sec [4,975..5,965] → 4,981 ops/sec [4,896..5,007] ~ overlap (-3.0%)
find inside some (10x10) 3,126 ops/sec [3,099..3,162] → 3,189 ops/sec [3,123..3,220] ~ overlap (+2.0%) 3,604 ops/sec [3,586..4,033] → 3,485 ops/sec [3,460..3,495] 🔴 -3.3%
map+filter chain nested (5x20) 1,160 ops/sec [1,126..1,286] → 1,192 ops/sec [1,178..1,196] ~ overlap (+2.8%) 1,400 ops/sec [1,383..1,403] → 1,366 ops/sec [1,339..1,514] ~ overlap (-2.4%)
reduce flatten (10x5) 10,006 ops/sec [9,868..11,202] → 10,412 ops/sec [10,371..10,487] ~ overlap (+4.1%) 4,283 ops/sec [4,077..4,457] → 4,350 ops/sec [4,257..4,618] ~ overlap (+1.6%)
async-await.js — Interp: 6 unch. · avg +0.4% · Bytecode: 6 unch. · avg +1.4%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
single await 23,118 ops/sec [21,725..25,961] → 22,191 ops/sec [21,481..22,894] ~ overlap (-4.0%) 23,771 ops/sec [23,066..26,572] → 25,737 ops/sec [23,614..26,135] ~ overlap (+8.3%)
multiple awaits 9,176 ops/sec [9,092..12,224] → 9,150 ops/sec [8,935..10,908] ~ overlap (-0.3%) 8,536 ops/sec [8,437..8,705] → 9,221 ops/sec [8,618..9,882] ~ overlap (+8.0%)
await non-Promise value 30,122 ops/sec [28,947..31,455] → 30,987 ops/sec [30,851..31,366] ~ overlap (+2.9%) 32,455 ops/sec [31,324..36,350] → 34,731 ops/sec [29,190..38,123] ~ overlap (+7.0%)
await with try/catch 18,942 ops/sec [18,604..19,930] → 18,298 ops/sec [17,962..23,077] ~ overlap (-3.4%) 25,760 ops/sec [22,940..25,897] → 23,350 ops/sec [21,607..26,080] ~ overlap (-9.4%)
await Promise.all 5,161 ops/sec [5,071..5,605] → 5,788 ops/sec [5,407..5,836] ~ overlap (+12.1%) 5,508 ops/sec [5,458..5,579] → 5,910 ops/sec [5,015..6,017] ~ overlap (+7.3%)
nested async function call 12,968 ops/sec [10,917..15,259] → 12,302 ops/sec [11,963..14,288] ~ overlap (-5.1%) 13,399 ops/sec [6,694..13,801] → 11,684 ops/sec [11,260..13,109] ~ overlap (-12.8%)
async-generators.js — Interp: 2 unch. · avg +5.3% · Bytecode: 🟢 1, 1 unch. · avg +0.2%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
for-await-of over async generator 1,525 ops/sec [1,369..1,594] → 1,536 ops/sec [1,454..1,694] ~ overlap (+0.7%) 607 ops/sec [597..616] → 689 ops/sec [675..722] 🟢 +13.4%
async generator with await in body 10,131 ops/sec [10,058..12,303] → 11,131 ops/sec [10,365..12,272] ~ overlap (+9.9%) 5,212 ops/sec [4,321..5,401] → 4,532 ops/sec [4,439..4,575] ~ overlap (-13.0%)
atomics.js — Interp: 6 unch. · avg +2.2% · Bytecode: 🟢 1, 🔴 1, 4 unch. · avg -1.6%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
load and store Int32Array 82,381 ops/sec [70,670..91,058] → 89,518 ops/sec [86,394..104,755] ~ overlap (+8.7%) 119,373 ops/sec [118,759..119,842] → 122,249 ops/sec [120,312..125,001] 🟢 +2.4%
read-modify-write Int32Array 55,061 ops/sec [53,040..66,229] → 55,509 ops/sec [54,010..55,957] ~ overlap (+0.8%) 84,083 ops/sec [79,793..91,148] → 80,883 ops/sec [78,662..83,997] ~ overlap (-3.8%)
compareExchange hit and miss 48,696 ops/sec [47,927..56,852] → 50,044 ops/sec [46,634..50,704] ~ overlap (+2.8%) 74,332 ops/sec [74,032..74,872] → 71,515 ops/sec [69,227..76,702] ~ overlap (-3.8%)
wait with zero timeout 131,862 ops/sec [126,048..138,351] → 132,255 ops/sec [131,278..132,810] ~ overlap (+0.3%) 191,149 ops/sec [188,595..203,604] → 187,194 ops/sec [181,984..196,092] ~ overlap (-2.1%)
waitAsync synchronous not-equal 103,082 ops/sec [95,300..114,335] → 102,183 ops/sec [97,304..116,584] ~ overlap (-0.9%) 126,439 ops/sec [126,017..131,767] → 123,377 ops/sec [122,427..124,362] 🔴 -2.4%
notify with no waiters 136,859 ops/sec [132,365..151,878] → 139,053 ops/sec [138,800..140,374] ~ overlap (+1.6%) 199,435 ops/sec [198,913..251,400] → 199,737 ops/sec [198,877..215,855] ~ overlap (+0.2%)
base64.js — Interp: 10 unch. · avg +0.7% · Bytecode: 🟢 1, 🔴 2, 7 unch. · avg -0.9%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
short ASCII (13 chars) 2,374 ops/sec [2,360..2,382] → 2,383 ops/sec [2,351..2,398] ~ overlap (+0.3%) 2,451 ops/sec [2,430..2,454] → 2,463 ops/sec [2,460..2,478] 🟢 +0.5%
medium ASCII (450 chars) 87 ops/sec [85..87] → 87 ops/sec [86..88] ~ overlap (+0.8%) 90 ops/sec [89..90] → 89 ops/sec [88..90] ~ overlap (-0.9%)
Latin-1 characters 3,429 ops/sec [3,362..4,306] → 3,473 ops/sec [3,454..3,502] ~ overlap (+1.3%) 3,559 ops/sec [3,532..3,595] → 3,567 ops/sec [3,536..3,938] ~ overlap (+0.2%)
short base64 (20 chars) 1,697 ops/sec [1,665..1,712] → 1,718 ops/sec [1,706..1,731] ~ overlap (+1.2%) 1,795 ops/sec [1,782..1,800] → 1,758 ops/sec [1,717..1,773] 🔴 -2.1%
medium base64 (600 chars) 68 ops/sec [66..68] → 70 ops/sec [65..72] ~ overlap (+3.4%) 70 ops/sec [70..71] → 68 ops/sec [68..68] 🔴 -3.0%
Latin-1 output 2,471 ops/sec [2,447..2,535] → 2,490 ops/sec [2,421..2,506] ~ overlap (+0.8%) 2,538 ops/sec [2,492..2,558] → 2,505 ops/sec [2,380..2,705] ~ overlap (-1.3%)
forgiving (no padding) 3,684 ops/sec [3,672..3,766] → 3,681 ops/sec [3,581..4,473] ~ overlap (-0.1%) 3,788 ops/sec [3,703..3,987] → 3,748 ops/sec [3,670..3,828] ~ overlap (-1.1%)
with whitespace 1,611 ops/sec [1,592..1,616] → 1,617 ops/sec [1,590..1,778] ~ overlap (+0.3%) 1,617 ops/sec [1,607..1,649] → 1,610 ops/sec [1,603..1,711] ~ overlap (-0.4%)
atob(btoa(short)) 997 ops/sec [969..1,007] → 996 ops/sec [990..1,030] ~ overlap (-0.1%) 1,021 ops/sec [1,004..1,031] → 1,024 ops/sec [1,019..1,033] ~ overlap (+0.4%)
atob(btoa(medium)) 40 ops/sec [38..42] → 39 ops/sec [38..45] ~ overlap (-1.2%) 40 ops/sec [39..40] → 39 ops/sec [39..42] ~ overlap (-1.1%)
classes.js — Interp: 🔴 5, 26 unch. · avg -1.3% · Bytecode: 🟢 5, 🔴 1, 25 unch. · avg +2.2%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
simple class new 41,172 ops/sec [40,045..48,233] → 40,161 ops/sec [39,512..40,362] ~ overlap (-2.5%) 54,581 ops/sec [50,570..54,726] → 53,280 ops/sec [52,970..53,405] ~ overlap (-2.4%)
class with defaults 32,348 ops/sec [30,795..33,012] → 30,734 ops/sec [30,459..31,304] ~ overlap (-5.0%) 37,313 ops/sec [37,218..38,043] → 38,598 ops/sec [35,648..39,342] ~ overlap (+3.4%)
50 instances via Array.from 1,456 ops/sec [1,451..1,461] → 1,421 ops/sec [1,417..1,473] ~ overlap (-2.4%) 1,702 ops/sec [1,693..1,710] → 1,650 ops/sec [1,632..1,654] 🔴 -3.1%
instance method call 18,457 ops/sec [18,329..18,480] → 18,839 ops/sec [18,204..19,691] ~ overlap (+2.1%) 28,562 ops/sec [28,355..28,786] → 27,662 ops/sec [26,889..28,486] ~ overlap (-3.1%)
static method call 32,076 ops/sec [30,030..37,104] → 31,165 ops/sec [30,712..32,569] ~ overlap (-2.8%) 59,922 ops/sec [57,538..71,087] → 57,800 ops/sec [57,662..58,172] ~ overlap (-3.5%)
single-level inheritance 16,394 ops/sec [16,321..16,536] → 16,007 ops/sec [15,909..21,279] ~ overlap (-2.4%) 19,877 ops/sec [18,845..24,153] → 20,278 ops/sec [19,835..23,435] ~ overlap (+2.0%)
two-level inheritance 14,298 ops/sec [14,021..14,540] → 14,206 ops/sec [13,734..19,750] ~ overlap (-0.6%) 14,868 ops/sec [14,529..14,999] → 15,491 ops/sec [15,277..15,627] 🟢 +4.2%
private field access 19,964 ops/sec [19,831..20,136] → 19,965 ops/sec [19,502..20,461] ~ overlap (+0.0%) 14,400 ops/sec [14,153..14,622] → 14,918 ops/sec [14,841..15,006] 🟢 +3.6%
private methods 23,245 ops/sec [21,674..28,750] → 22,054 ops/sec [21,890..22,857] ~ overlap (-5.1%) 16,420 ops/sec [16,073..17,538] → 16,941 ops/sec [16,900..17,074] ~ overlap (+3.2%)
getter/setter access 23,334 ops/sec [21,367..24,881] → 21,816 ops/sec [21,696..23,138] ~ overlap (-6.5%) 29,336 ops/sec [28,424..30,056] → 30,500 ops/sec [30,373..30,911] 🟢 +4.0%
class decorator (identity) 33,213 ops/sec [32,994..41,962] → 32,961 ops/sec [32,913..33,076] ~ overlap (-0.8%) 34,789 ops/sec [34,125..37,328] → 34,839 ops/sec [33,929..39,642] ~ overlap (+0.1%)
class decorator (wrapping) 18,076 ops/sec [18,015..18,729] → 17,925 ops/sec [17,727..19,677] ~ overlap (-0.8%) 18,352 ops/sec [18,181..19,466] → 18,151 ops/sec [17,934..18,292] ~ overlap (-1.1%)
identity method decorator 23,565 ops/sec [22,603..25,235] → 23,150 ops/sec [22,500..28,341] ~ overlap (-1.8%) 28,607 ops/sec [27,860..34,905] → 31,369 ops/sec [28,068..33,399] ~ overlap (+9.7%)
wrapping method decorator 19,818 ops/sec [19,670..20,020] → 18,512 ops/sec [17,889..20,290] ~ overlap (-6.6%) 21,759 ops/sec [20,880..22,593] → 22,304 ops/sec [21,268..23,156] ~ overlap (+2.5%)
stacked method decorators (x3) 15,481 ops/sec [13,077..15,737] → 14,516 ops/sec [13,267..17,659] ~ overlap (-6.2%) 16,469 ops/sec [15,401..18,576] → 15,567 ops/sec [15,463..15,741] ~ overlap (-5.5%)
identity field decorator 26,158 ops/sec [25,865..27,962] → 26,859 ops/sec [26,552..29,621] ~ overlap (+2.7%) 27,814 ops/sec [27,591..27,972] → 27,653 ops/sec [27,516..27,797] ~ overlap (-0.6%)
field initializer decorator 22,215 ops/sec [22,150..22,334] → 21,677 ops/sec [21,214..22,154] ~ overlap (-2.4%) 24,320 ops/sec [23,789..24,748] → 24,161 ops/sec [23,773..27,810] ~ overlap (-0.7%)
getter decorator (identity) 21,335 ops/sec [21,321..21,539] → 20,593 ops/sec [20,300..20,638] 🔴 -3.5% 18,634 ops/sec [18,485..28,685] → 19,235 ops/sec [18,825..19,621] ~ overlap (+3.2%)
setter decorator (identity) 17,439 ops/sec [17,366..18,793] → 16,502 ops/sec [16,346..16,963] 🔴 -5.4% 15,110 ops/sec [14,955..18,908] → 15,666 ops/sec [15,556..15,750] ~ overlap (+3.7%)
static method decorator 23,826 ops/sec [23,490..29,002] → 23,991 ops/sec [23,785..28,516] ~ overlap (+0.7%) 31,921 ops/sec [31,328..32,738] → 33,821 ops/sec [31,531..36,912] ~ overlap (+6.0%)
static field decorator 30,023 ops/sec [28,867..33,814] → 30,983 ops/sec [29,896..31,817] ~ overlap (+3.2%) 34,455 ops/sec [34,180..36,697] → 38,278 ops/sec [36,588..40,310] ~ overlap (+11.1%)
private method decorator 17,534 ops/sec [17,406..17,622] → 22,080 ops/sec [16,963..25,189] ~ overlap (+25.9%) 20,852 ops/sec [20,270..25,633] → 21,753 ops/sec [20,354..23,309] ~ overlap (+4.3%)
private field decorator 19,978 ops/sec [19,262..22,083] → 21,202 ops/sec [19,388..23,322] ~ overlap (+6.1%) 19,852 ops/sec [18,800..22,951] → 18,802 ops/sec [18,617..21,403] ~ overlap (-5.3%)
plain auto-accessor (no decorator) 37,344 ops/sec [35,283..37,783] → 35,145 ops/sec [34,623..38,314] ~ overlap (-5.9%) 34,676 ops/sec [33,641..35,136] → 34,748 ops/sec [33,485..35,442] ~ overlap (+0.2%)
auto-accessor with decorator 21,482 ops/sec [21,128..21,734] → 20,121 ops/sec [19,790..20,903] 🔴 -6.3% 21,095 ops/sec [20,233..23,513] → 21,160 ops/sec [20,576..21,795] ~ overlap (+0.3%)
decorator writing metadata 16,218 ops/sec [15,840..16,378] → 15,736 ops/sec [15,594..15,793] 🔴 -3.0% 19,037 ops/sec [18,693..19,226] → 23,127 ops/sec [19,395..26,660] 🟢 +21.5%
static getter read 38,217 ops/sec [37,848..38,294] → 38,021 ops/sec [37,577..38,454] ~ overlap (-0.5%) 52,943 ops/sec [52,315..58,670] → 55,205 ops/sec [54,510..55,467] ~ overlap (+4.3%)
static getter/setter pair 27,881 ops/sec [27,701..28,130] → 26,676 ops/sec [25,855..27,028] 🔴 -4.3% 39,000 ops/sec [38,869..39,273] → 41,115 ops/sec [40,307..44,150] 🟢 +5.4%
inherited static getter 28,050 ops/sec [24,586..29,710] → 25,311 ops/sec [24,941..38,449] ~ overlap (-9.8%) 34,343 ops/sec [34,156..37,869] → 34,996 ops/sec [34,222..35,256] ~ overlap (+1.9%)
inherited static setter 25,585 ops/sec [25,449..25,717] → 26,515 ops/sec [23,665..27,890] ~ overlap (+3.6%) 34,607 ops/sec [34,303..53,126] → 34,585 ops/sec [34,279..39,001] ~ overlap (-0.1%)
inherited static getter with this binding 19,762 ops/sec [19,678..19,808] → 19,624 ops/sec [19,285..23,468] ~ overlap (-0.7%) 27,580 ops/sec [26,328..31,256] → 27,508 ops/sec [26,897..27,834] ~ overlap (-0.3%)
closures.js — Interp: 🔴 1, 10 unch. · avg +0.5% · Bytecode: 11 unch. · avg +1.5%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
closure over single variable 27,414 ops/sec [27,104..28,942] → 27,833 ops/sec [27,536..30,823] ~ overlap (+1.5%) 92,451 ops/sec [91,887..93,054] → 90,438 ops/sec [89,886..97,070] ~ overlap (-2.2%)
closure over multiple variables 36,253 ops/sec [34,607..39,636] → 34,766 ops/sec [33,828..35,208] ~ overlap (-4.1%) 89,561 ops/sec [88,662..91,701] → 86,662 ops/sec [85,133..95,325] ~ overlap (-3.2%)
nested closures 37,343 ops/sec [37,163..41,720] → 37,320 ops/sec [36,452..37,756] ~ overlap (-0.1%) 88,461 ops/sec [87,695..88,897] → 88,372 ops/sec [87,261..88,739] ~ overlap (-0.1%)
function as argument 28,417 ops/sec [28,097..28,451] → 28,175 ops/sec [27,601..28,564] ~ overlap (-0.9%) 83,806 ops/sec [82,649..100,203] → 84,891 ops/sec [83,254..93,922] ~ overlap (+1.3%)
function returning function 35,618 ops/sec [35,045..37,743] → 35,675 ops/sec [35,202..35,960] ~ overlap (+0.2%) 96,761 ops/sec [94,256..102,634] → 96,812 ops/sec [95,663..96,997] ~ overlap (+0.1%)
compose two functions 22,777 ops/sec [22,598..22,917] → 22,300 ops/sec [22,134..22,403] 🔴 -2.1% 57,930 ops/sec [57,232..60,971] → 58,309 ops/sec [58,259..58,404] ~ overlap (+0.7%)
fn.call 49,402 ops/sec [47,665..50,293] → 48,353 ops/sec [47,991..50,070] ~ overlap (-2.1%) 71,827 ops/sec [71,620..81,103] → 73,724 ops/sec [73,520..74,220] ~ overlap (+2.6%)
fn.apply 38,534 ops/sec [37,854..41,606] → 43,666 ops/sec [38,836..46,906] ~ overlap (+13.3%) 70,815 ops/sec [70,194..74,358] → 70,425 ops/sec [69,241..70,920] ~ overlap (-0.6%)
fn.bind 41,161 ops/sec [41,027..41,488] → 41,725 ops/sec [40,403..43,211] ~ overlap (+1.4%) 99,273 ops/sec [95,679..110,255] → 115,377 ops/sec [93,382..116,059] ~ overlap (+16.2%)
recursive sum to 50 3,327 ops/sec [3,287..3,700] → 3,301 ops/sec [3,285..3,743] ~ overlap (-0.8%) 12,148 ops/sec [11,847..12,286] → 12,044 ops/sec [11,950..13,416] ~ overlap (-0.9%)
recursive tree traversal 5,447 ops/sec [5,017..5,753] → 5,389 ops/sec [5,099..5,461] ~ overlap (-1.1%) 11,522 ops/sec [11,442..19,805] → 11,800 ops/sec [11,714..13,322] ~ overlap (+2.4%)
collections.js — Interp: 🟢 2, 10 unch. · avg +1.5% · Bytecode: 12 unch. · avg -1.4%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
add 50 elements 2,173 ops/sec [2,125..2,191] → 2,408 ops/sec [2,200..2,564] 🟢 +10.8% 2,671 ops/sec [2,625..2,703] → 2,690 ops/sec [2,638..2,809] ~ overlap (+0.7%)
has lookup (50 elements) 35,999 ops/sec [35,807..37,115] → 42,386 ops/sec [38,054..43,583] 🟢 +17.7% 46,984 ops/sec [45,031..47,487] → 47,046 ops/sec [45,901..50,880] ~ overlap (+0.1%)
delete elements 20,065 ops/sec [19,640..20,310] → 20,271 ops/sec [20,237..20,284] ~ overlap (+1.0%) 24,516 ops/sec [24,302..25,631] → 23,715 ops/sec [23,544..29,111] ~ overlap (-3.3%)
forEach iteration 3,813 ops/sec [3,707..3,818] → 3,774 ops/sec [3,745..3,814] ~ overlap (-1.0%) 6,448 ops/sec [6,424..7,404] → 6,317 ops/sec [6,185..6,824] ~ overlap (-2.0%)
spread to array 14,068 ops/sec [13,908..14,185] → 13,725 ops/sec [11,498..15,275] ~ overlap (-2.4%) 74,819 ops/sec [72,301..82,623] → 78,988 ops/sec [70,600..95,447] ~ overlap (+5.6%)
deduplicate array 17,878 ops/sec [16,653..22,382] → 16,938 ops/sec [16,853..17,447] ~ overlap (-5.3%) 31,699 ops/sec [30,722..32,358] → 31,547 ops/sec [30,756..31,917] ~ overlap (-0.5%)
set 50 entries 1,709 ops/sec [1,672..1,736] → 1,715 ops/sec [1,686..1,754] ~ overlap (+0.3%) 2,315 ops/sec [2,174..2,545] → 2,123 ops/sec [2,085..2,222] ~ overlap (-8.3%)
get lookup (50 entries) 36,549 ops/sec [35,612..41,889] → 36,049 ops/sec [35,328..36,261] ~ overlap (-1.4%) 43,072 ops/sec [41,887..52,536] → 42,278 ops/sec [41,879..42,744] ~ overlap (-1.8%)
has check 51,833 ops/sec [51,549..52,139] → 51,987 ops/sec [51,610..58,616] ~ overlap (+0.3%) 62,197 ops/sec [61,451..64,242] → 61,397 ops/sec [60,807..61,515] ~ overlap (-1.3%)
delete entries 20,297 ops/sec [19,825..20,469] → 19,868 ops/sec [19,378..20,031] ~ overlap (-2.1%) 23,162 ops/sec [22,895..23,613] → 22,891 ops/sec [22,792..24,006] ~ overlap (-1.2%)
forEach iteration 3,750 ops/sec [3,346..4,687] → 3,788 ops/sec [3,583..3,817] ~ overlap (+1.0%) 6,687 ops/sec [6,348..9,243] → 6,601 ops/sec [6,240..6,851] ~ overlap (-1.3%)
keys/values/entries 3,389 ops/sec [3,371..4,660] → 3,370 ops/sec [3,289..4,050] ~ overlap (-0.6%) 12,330 ops/sec [11,744..13,975] → 11,941 ops/sec [11,725..15,956] ~ overlap (-3.2%)
csv.js — Interp: 🟢 1, 🔴 1, 11 unch. · avg -2.1% · Bytecode: 🟢 1, 12 unch. · avg +0.8%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
parse simple 3-column CSV 39,855 ops/sec [38,955..46,235] → 46,135 ops/sec [38,658..61,133] ~ overlap (+15.8%) 43,588 ops/sec [43,026..43,887] → 43,612 ops/sec [42,730..50,527] ~ overlap (+0.1%)
parse 10-row CSV 11,377 ops/sec [11,078..12,243] → 11,259 ops/sec [10,822..11,941] ~ overlap (-1.0%) 11,867 ops/sec [11,812..12,274] → 11,969 ops/sec [11,872..12,161] ~ overlap (+0.9%)
parse 100-row CSV 1,797 ops/sec [1,786..1,804] → 1,828 ops/sec [1,754..2,151] ~ overlap (+1.7%) 1,864 ops/sec [1,811..1,899] → 1,906 ops/sec [1,838..1,948] ~ overlap (+2.2%)
parse CSV with quoted fields 57,430 ops/sec [57,206..57,602] → 59,856 ops/sec [57,754..78,361] 🟢 +4.2% 64,504 ops/sec [64,080..66,618] → 65,325 ops/sec [65,087..65,372] ~ overlap (+1.3%)
parse without headers (array of arrays) 6,658 ops/sec [6,524..6,691] → 5,526 ops/sec [5,196..5,820] 🔴 -17.0% 5,780 ops/sec [5,695..6,098] → 6,483 ops/sec [6,407..6,782] 🟢 +12.2%
parse with semicolon delimiter 9,588 ops/sec [9,411..9,823] → 9,082 ops/sec [8,352..10,755] ~ overlap (-5.3%) 9,789 ops/sec [8,506..11,090] → 9,973 ops/sec [8,431..11,655] ~ overlap (+1.9%)
stringify array of objects 58,175 ops/sec [54,513..67,840] → 56,323 ops/sec [54,791..56,686] ~ overlap (-3.2%) 64,015 ops/sec [63,254..65,135] → 64,772 ops/sec [64,647..64,982] ~ overlap (+1.2%)
stringify array of arrays 23,873 ops/sec [22,837..34,815] → 22,986 ops/sec [22,871..23,339] ~ overlap (-3.7%) 23,616 ops/sec [23,540..23,671] → 23,881 ops/sec [23,648..28,674] ~ overlap (+1.1%)
stringify with values needing escaping 45,445 ops/sec [44,257..60,623] → 43,480 ops/sec [41,528..52,105] ~ overlap (-4.3%) 49,535 ops/sec [48,986..49,688] → 48,921 ops/sec [48,264..49,484] ~ overlap (-1.2%)
reviver converts numbers 887 ops/sec [866..971] → 865 ops/sec [856..982] ~ overlap (-2.4%) 1,087 ops/sec [1,043..1,102] → 1,101 ops/sec [1,091..1,108] ~ overlap (+1.4%)
reviver filters empty to null 7,424 ops/sec [7,379..7,996] → 8,069 ops/sec [7,263..8,181] ~ overlap (+8.7%) 10,464 ops/sec [10,257..11,117] → 10,248 ops/sec [9,987..10,482] ~ overlap (-2.1%)
parse then stringify 8,088 ops/sec [6,807..9,156] → 7,269 ops/sec [7,113..7,375] ~ overlap (-10.1%) 7,997 ops/sec [7,947..8,496] → 7,789 ops/sec [7,664..8,320] ~ overlap (-2.6%)
stringify then parse 7,786 ops/sec [7,045..7,857] → 7,011 ops/sec [6,977..7,052] ~ overlap (-10.0%) 8,132 ops/sec [7,652..9,061] → 7,645 ops/sec [7,615..7,655] ~ overlap (-6.0%)
destructuring.js — Interp: 🟢 1, 🔴 5, 16 unch. · avg -1.0% · Bytecode: 🟢 2, 🔴 3, 17 unch. · avg +0.0%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
simple array destructuring 66,124 ops/sec [64,435..66,258] → 65,404 ops/sec [63,151..66,929] ~ overlap (-1.1%) 83,143 ops/sec [82,462..84,760] → 83,137 ops/sec [82,273..92,337] ~ overlap (-0.0%)
with rest element 54,423 ops/sec [53,873..54,606] → 54,098 ops/sec [53,271..54,794] ~ overlap (-0.6%) 66,591 ops/sec [64,885..80,962] → 79,100 ops/sec [69,054..83,802] ~ overlap (+18.8%)
with defaults 65,342 ops/sec [65,003..65,369] → 66,798 ops/sec [64,113..69,519] ~ overlap (+2.2%) 89,740 ops/sec [89,173..95,725] → 91,352 ops/sec [90,231..102,688] ~ overlap (+1.8%)
skip elements 71,649 ops/sec [71,323..72,901] → 71,841 ops/sec [69,507..71,935] ~ overlap (+0.3%) 93,747 ops/sec [90,420..98,812] → 93,335 ops/sec [92,991..106,872] ~ overlap (-0.4%)
nested array destructuring 31,473 ops/sec [31,162..31,575] → 33,798 ops/sec [30,635..40,854] ~ overlap (+7.4%) 33,688 ops/sec [32,179..33,799] → 32,599 ops/sec [32,532..32,622] ~ overlap (-3.2%)
swap variables 88,497 ops/sec [88,089..88,840] → 91,914 ops/sec [88,103..101,358] ~ overlap (+3.9%) 126,376 ops/sec [117,578..145,812] → 124,879 ops/sec [118,062..131,280] ~ overlap (-1.2%)
simple object destructuring 78,540 ops/sec [78,045..79,115] → 79,544 ops/sec [78,218..86,336] ~ overlap (+1.3%) 96,368 ops/sec [92,541..96,621] → 92,816 ops/sec [92,420..98,124] ~ overlap (-3.7%)
with defaults 86,417 ops/sec [85,319..86,704] → 86,476 ops/sec [86,006..87,113] ~ overlap (+0.1%) 135,772 ops/sec [134,194..139,884] → 137,987 ops/sec [135,205..152,258] ~ overlap (+1.6%)
with renaming 86,746 ops/sec [86,359..87,028] → 86,713 ops/sec [85,942..87,044] ~ overlap (-0.0%) 102,033 ops/sec [101,708..102,110] → 100,842 ops/sec [99,826..101,345] 🔴 -1.2%
nested object destructuring 46,825 ops/sec [46,566..46,939] → 46,787 ops/sec [46,282..57,598] ~ overlap (-0.1%) 55,631 ops/sec [50,611..70,712] → 52,219 ops/sec [50,412..73,339] ~ overlap (-6.1%)
rest properties 36,557 ops/sec [36,350..36,888] → 36,576 ops/sec [35,992..37,422] ~ overlap (+0.1%) 49,438 ops/sec [44,013..52,550] → 45,579 ops/sec [44,526..52,011] ~ overlap (-7.8%)
object parameter 26,152 ops/sec [25,885..26,354] → 25,753 ops/sec [25,660..26,170] ~ overlap (-1.5%) 44,917 ops/sec [44,128..63,279] → 44,092 ops/sec [43,442..44,195] ~ overlap (-1.8%)
array parameter 30,705 ops/sec [30,551..30,729] → 31,085 ops/sec [30,737..33,931] 🟢 +1.2% 48,370 ops/sec [48,060..48,517] → 50,638 ops/sec [44,013..53,375] ~ overlap (+4.7%)
mixed destructuring in map 8,380 ops/sec [8,371..8,449] → 8,138 ops/sec [8,034..9,483] ~ overlap (-2.9%) 12,051 ops/sec [11,735..13,698] → 11,775 ops/sec [11,534..11,876] ~ overlap (-2.3%)
forEach with array destructuring 13,421 ops/sec [13,365..13,483] → 13,241 ops/sec [13,002..13,317] 🔴 -1.3% 16,202 ops/sec [15,849..17,499] → 16,357 ops/sec [16,272..16,520] ~ overlap (+1.0%)
map with array destructuring 15,371 ops/sec [15,223..15,548] → 15,544 ops/sec [15,371..15,671] ~ overlap (+1.1%) 14,986 ops/sec [14,342..15,222] → 15,791 ops/sec [15,645..15,929] 🟢 +5.4%
filter with array destructuring 15,971 ops/sec [15,910..16,061] → 15,917 ops/sec [15,853..15,959] ~ overlap (-0.3%) 17,745 ops/sec [15,937..19,715] → 18,899 ops/sec [16,310..20,545] ~ overlap (+6.5%)
reduce with array destructuring 19,434 ops/sec [16,510..20,127] → 16,795 ops/sec [16,674..16,863] ~ overlap (-13.6%) 17,103 ops/sec [16,711..17,209] → 17,429 ops/sec [16,991..18,665] ~ overlap (+1.9%)
map with object destructuring 19,255 ops/sec [19,185..19,283] → 18,823 ops/sec [18,768..18,881] 🔴 -2.2% 23,548 ops/sec [23,333..23,698] → 24,353 ops/sec [23,429..24,595] ~ overlap (+3.4%)
map with nested destructuring 15,623 ops/sec [15,569..15,711] → 15,243 ops/sec [15,170..15,317] 🔴 -2.4% 23,340 ops/sec [23,224..23,446] → 23,677 ops/sec [23,607..23,701] 🟢 +1.4%
map with rest in destructuring 8,883 ops/sec [8,627..9,459] → 8,492 ops/sec [8,359..8,624] 🔴 -4.4% 8,451 ops/sec [8,416..8,490] → 7,579 ops/sec [7,444..7,825] 🔴 -10.3%
map with defaults in destructuring 11,093 ops/sec [10,837..11,181] → 10,216 ops/sec [10,174..10,581] 🔴 -7.9% 18,821 ops/sec [18,697..18,984] → 17,257 ops/sec [16,986..17,496] 🔴 -8.3%
fibonacci.js — Interp: 8 unch. · avg +0.5% · Bytecode: 8 unch. · avg -2.5%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
recursive fib(15) 91 ops/sec [88..96] → 92 ops/sec [88..98] ~ overlap (+1.3%) 332 ops/sec [312..392] → 335 ops/sec [327..348] ~ overlap (+0.7%)
recursive fib(20) 9 ops/sec [8..10] → 9 ops/sec [9..10] ~ overlap (+0.6%) 31 ops/sec [30..34] → 31 ops/sec [29..33] ~ overlap (-1.0%)
recursive fib(15) typed 90 ops/sec [89..101] → 93 ops/sec [87..101] ~ overlap (+3.4%) 334 ops/sec [317..581] → 333 ops/sec [330..415] ~ overlap (-0.5%)
recursive fib(20) typed 9 ops/sec [8..9] → 9 ops/sec [8..10] ~ overlap (+2.1%) 31 ops/sec [30..32] → 31 ops/sec [30..35] ~ overlap (-1.1%)
iterative fib(20) via reduce 4,104 ops/sec [4,100..4,136] → 3,943 ops/sec [3,857..4,108] ~ overlap (-3.9%) 7,190 ops/sec [6,165..7,385] → 6,508 ops/sec [6,341..6,991] ~ overlap (-9.5%)
iterator fib(20) 2,271 ops/sec [2,264..2,331] → 2,299 ops/sec [2,248..2,375] ~ overlap (+1.2%) 5,584 ops/sec [4,888..6,875] → 5,020 ops/sec [4,960..5,026] ~ overlap (-10.1%)
iterator fib(20) via Iterator.from + take 2,124 ops/sec [2,115..2,136] → 2,134 ops/sec [2,110..2,160] ~ overlap (+0.5%) 2,782 ops/sec [2,692..3,369] → 2,778 ops/sec [2,703..2,799] ~ overlap (-0.1%)
iterator fib(20) last value via reduce 1,894 ops/sec [1,876..1,899] → 1,878 ops/sec [1,847..1,937] ~ overlap (-0.9%) 2,286 ops/sec [2,237..2,327] → 2,320 ops/sec [2,277..2,632] ~ overlap (+1.5%)
float16array.js — Interp: 🟢 4, 🔴 1, 27 unch. · avg -1.0% · Bytecode: 🔴 7, 25 unch. · avg -1.7%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
new Float16Array(0) 106,272 ops/sec [95,731..114,232] → 95,953 ops/sec [92,294..96,525] ~ overlap (-9.7%) 115,919 ops/sec [113,251..117,082] → 116,044 ops/sec [115,572..117,082] ~ overlap (+0.1%)
new Float16Array(100) 91,128 ops/sec [90,266..95,948] → 91,615 ops/sec [88,514..97,386] ~ overlap (+0.5%) 111,571 ops/sec [110,002..134,553] → 112,489 ops/sec [111,522..113,743] ~ overlap (+0.8%)
new Float16Array(1000) 80,697 ops/sec [80,608..80,902] → 80,118 ops/sec [79,530..84,195] ~ overlap (-0.7%) 98,487 ops/sec [95,250..102,301] → 97,304 ops/sec [96,672..97,992] ~ overlap (-1.2%)
Float16Array.from([...100]) 1,549 ops/sec [1,517..1,558] → 1,537 ops/sec [1,466..1,681] ~ overlap (-0.8%) 1,586 ops/sec [1,582..1,588] → 1,548 ops/sec [1,536..1,549] 🔴 -2.4%
Float16Array.of(1.5, 2.5, 3.5, 4.5, 5.5) 75,445 ops/sec [75,205..75,967] → 75,370 ops/sec [74,996..76,015] ~ overlap (-0.1%) 74,179 ops/sec [73,699..75,468] → 73,670 ops/sec [72,730..75,035] ~ overlap (-0.7%)
new Float16Array(float64Array) 25,499 ops/sec [25,426..25,642] → 24,733 ops/sec [24,647..24,872] 🔴 -3.0% 26,357 ops/sec [25,898..26,891] → 27,205 ops/sec [26,035..27,929] ~ overlap (+3.2%)
sequential write 100 elements 985 ops/sec [949..1,007] → 1,004 ops/sec [964..1,059] ~ overlap (+1.9%) 3,205 ops/sec [2,973..3,242] → 3,081 ops/sec [2,972..3,649] ~ overlap (-3.9%)
sequential read 100 elements 1,131 ops/sec [1,125..1,136] → 1,123 ops/sec [1,114..1,508] ~ overlap (-0.7%) 3,884 ops/sec [3,834..3,948] → 3,657 ops/sec [3,565..3,703] 🔴 -5.8%
write special values (NaN, Inf, -0) 42,557 ops/sec [42,303..42,712] → 43,530 ops/sec [43,270..44,265] 🟢 +2.3% 80,370 ops/sec [77,397..80,802] → 80,766 ops/sec [79,752..81,633] ~ overlap (+0.5%)
Float16Array write 1,004 ops/sec [980..1,181] → 1,011 ops/sec [1,008..1,016] ~ overlap (+0.7%) 3,176 ops/sec [3,156..3,311] → 3,027 ops/sec [2,982..3,130] 🔴 -4.7%
Float32Array write 1,014 ops/sec [1,006..1,019] → 1,028 ops/sec [1,019..1,030] 🟢 +1.4% 3,207 ops/sec [3,164..3,225] → 3,056 ops/sec [2,948..3,109] 🔴 -4.7%
Float64Array write 1,015 ops/sec [1,008..1,023] → 1,018 ops/sec [1,008..1,026] ~ overlap (+0.3%) 3,210 ops/sec [3,154..3,257] → 2,998 ops/sec [2,987..3,078] 🔴 -6.6%
Float16Array read 1,109 ops/sec [1,089..1,118] → 1,128 ops/sec [1,120..1,130] 🟢 +1.7% 3,653 ops/sec [3,599..3,871] → 3,377 ops/sec [3,320..3,787] ~ overlap (-7.6%)
Float32Array read 1,125 ops/sec [1,120..1,130] → 1,115 ops/sec [1,105..1,132] ~ overlap (-1.0%) 3,767 ops/sec [3,722..3,791] → 3,483 ops/sec [3,469..3,514] 🔴 -7.5%
Float64Array read 1,106 ops/sec [1,097..1,109] → 1,110 ops/sec [1,103..1,129] ~ overlap (+0.4%) 3,643 ops/sec [3,520..3,735] → 3,405 ops/sec [3,376..3,497] 🔴 -6.5%
fill(1.5) 6,647 ops/sec [6,545..8,859] → 6,538 ops/sec [6,444..6,777] ~ overlap (-1.6%) 6,722 ops/sec [6,621..8,284] → 7,699 ops/sec [6,725..8,548] ~ overlap (+14.5%)
slice() 12,049 ops/sec [11,869..12,712] → 11,978 ops/sec [11,821..12,549] ~ overlap (-0.6%) 12,895 ops/sec [12,210..13,325] → 12,444 ops/sec [12,300..13,415] ~ overlap (-3.5%)
map(x => x * 2) 2,099 ops/sec [2,082..2,128] → 2,080 ops/sec [2,026..2,109] ~ overlap (-0.9%) 2,245 ops/sec [2,130..2,886] → 2,167 ops/sec [2,127..2,265] ~ overlap (-3.4%)
filter(x => x > 25) 2,078 ops/sec [2,056..2,424] → 2,061 ops/sec [2,043..2,072] ~ overlap (-0.8%) 2,316 ops/sec [2,264..2,351] → 2,297 ops/sec [2,290..2,615] ~ overlap (-0.9%)
reduce (sum) 2,093 ops/sec [2,036..2,105] → 2,071 ops/sec [1,999..2,151] ~ overlap (-1.0%) 2,058 ops/sec [2,040..2,096] → 2,069 ops/sec [2,049..2,086] ~ overlap (+0.5%)
sort() 18,855 ops/sec [18,642..19,006] → 18,861 ops/sec [18,695..19,215] ~ overlap (+0.0%) 19,826 ops/sec [19,738..19,915] → 19,881 ops/sec [19,479..21,299] ~ overlap (+0.3%)
indexOf() 25,386 ops/sec [25,190..25,474] → 25,665 ops/sec [25,561..25,811] 🟢 +1.1% 29,235 ops/sec [26,749..33,927] → 26,628 ops/sec [26,544..29,302] ~ overlap (-8.9%)
reverse() 27,374 ops/sec [27,324..27,413] → 27,551 ops/sec [26,907..29,474] ~ overlap (+0.6%) 29,190 ops/sec [28,584..29,723] → 29,135 ops/sec [28,989..29,306] ~ overlap (-0.2%)
toReversed() 23,587 ops/sec [21,638..26,174] → 21,706 ops/sec [21,370..21,967] ~ overlap (-8.0%) 22,590 ops/sec [22,512..22,732] → 22,710 ops/sec [22,566..22,746] ~ overlap (+0.5%)
toSorted() 11,593 ops/sec [10,946..12,040] → 11,140 ops/sec [10,996..11,154] ~ overlap (-3.9%) 11,205 ops/sec [11,030..11,228] → 11,297 ops/sec [11,037..12,233] ~ overlap (+0.8%)
create view over existing buffer 114,894 ops/sec [105,877..118,685] → 108,674 ops/sec [104,574..123,221] ~ overlap (-5.4%) 131,231 ops/sec [127,881..140,038] → 127,392 ops/sec [126,563..151,869] ~ overlap (-2.9%)
subarray() 73,555 ops/sec [65,161..91,108] → 67,411 ops/sec [66,767..69,269] ~ overlap (-8.4%) 78,054 ops/sec [77,920..78,186] → 80,403 ops/sec [76,863..90,845] ~ overlap (+3.0%)
set() from array 98,323 ops/sec [97,160..99,546] → 100,104 ops/sec [97,071..100,474] ~ overlap (+1.8%) 130,382 ops/sec [126,831..140,798] → 131,862 ops/sec [129,168..155,056] ~ overlap (+1.1%)
for-of loop 1,521 ops/sec [1,478..1,691] → 1,494 ops/sec [1,464..1,588] ~ overlap (-1.8%) 7,095 ops/sec [6,159..8,386] → 6,609 ops/sec [6,488..6,681] ~ overlap (-6.8%)
spread into array 6,211 ops/sec [6,148..6,290] → 6,252 ops/sec [5,964..6,399] ~ overlap (+0.6%) 23,457 ops/sec [22,441..26,743] → 23,566 ops/sec [22,503..23,700] ~ overlap (+0.5%)
f16round(1.337) 172,068 ops/sec [168,305..174,539] → 175,348 ops/sec [173,234..177,387] ~ overlap (+1.9%) 237,368 ops/sec [226,636..311,240] → 229,181 ops/sec [222,041..238,510] ~ overlap (-3.4%)
f16round over 100 values 1,097 ops/sec [1,060..1,480] → 1,120 ops/sec [1,083..1,180] ~ overlap (+2.1%) 3,176 ops/sec [3,082..3,269] → 3,229 ops/sec [3,104..3,466] ~ overlap (+1.7%)
for-of.js — Interp: 🟢 1, 6 unch. · avg +4.4% · Bytecode: 🔴 1, 6 unch. · avg -0.2%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
for...of with 10-element array 13,064 ops/sec [12,786..14,367] → 13,743 ops/sec [13,501..14,431] ~ overlap (+5.2%) 74,583 ops/sec [71,446..75,454] → 82,903 ops/sec [74,806..105,672] ~ overlap (+11.2%)
for...of with 100-element array 1,535 ops/sec [1,490..1,544] → 1,676 ops/sec [1,631..1,693] 🟢 +9.2% 10,208 ops/sec [10,040..10,790] → 10,294 ops/sec [9,915..10,371] ~ overlap (+0.8%)
for...of with string (10 chars) 11,260 ops/sec [10,282..12,156] → 11,615 ops/sec [10,543..11,858] ~ overlap (+3.2%) 27,894 ops/sec [27,634..28,067] → 27,992 ops/sec [27,143..30,765] ~ overlap (+0.3%)
for...of with Set (10 elements) 14,847 ops/sec [13,625..15,215] → 14,877 ops/sec [14,744..15,245] ~ overlap (+0.2%) 85,153 ops/sec [83,778..98,062] → 86,125 ops/sec [85,620..95,680] ~ overlap (+1.1%)
for...of with Map entries (10 entries) 7,095 ops/sec [6,868..7,957] → 7,578 ops/sec [6,962..7,777] ~ overlap (+6.8%) 12,983 ops/sec [12,475..17,382] → 12,891 ops/sec [12,192..13,015] ~ overlap (-0.7%)
for...of with destructuring 8,038 ops/sec [8,002..8,070] → 8,007 ops/sec [7,820..8,036] ~ overlap (-0.4%) 17,092 ops/sec [16,761..17,416] → 15,026 ops/sec [14,821..15,686] 🔴 -12.1%
for-await-of with sync array 8,379 ops/sec [8,229..8,415] → 8,937 ops/sec [8,144..9,085] ~ overlap (+6.7%) 1,971 ops/sec [1,794..2,165] → 1,928 ops/sec [1,820..1,958] ~ overlap (-2.2%)
generators.js — Interp: 🔴 1, 3 unch. · avg -1.4% · Bytecode: 4 unch. · avg +2.3%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
manual next over object generator 699 ops/sec [677..712] → 695 ops/sec [689..722] ~ overlap (-0.6%) 1,021 ops/sec [1,016..1,037] → 1,027 ops/sec [1,007..1,030] ~ overlap (+0.6%)
for...of over object generator 1,004 ops/sec [934..1,147] → 993 ops/sec [976..1,245] ~ overlap (-1.1%) 1,496 ops/sec [1,486..1,507] → 1,490 ops/sec [1,466..2,267] ~ overlap (-0.4%)
yield delegation 954 ops/sec [951..957] → 973 ops/sec [869..977] ~ overlap (+2.0%) 1,382 ops/sec [1,366..2,106] → 1,505 ops/sec [1,498..1,513] ~ overlap (+8.9%)
class generator method 957 ops/sec [955..957] → 901 ops/sec [868..915] 🔴 -5.8% 1,375 ops/sec [1,353..1,395] → 1,376 ops/sec [1,259..1,529] ~ overlap (+0.1%)
intl.js — Interp: 6 unch. · avg -1.5% · Bytecode: 🔴 1, 5 unch. · avg -0.7%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
format decimal 22,251 ops/sec [22,083..23,494] → 22,821 ops/sec [22,759..23,078] ~ overlap (+2.6%) 25,263 ops/sec [25,182..25,268] → 25,513 ops/sec [25,097..28,574] ~ overlap (+1.0%)
format currency 18,854 ops/sec [18,569..20,118] → 18,072 ops/sec [17,454..18,645] ~ overlap (-4.2%) 20,123 ops/sec [20,094..20,373] → 20,728 ops/sec [19,837..20,812] ~ overlap (+3.0%)
format UTC date 2,324 ops/sec [2,295..2,521] → 2,293 ops/sec [2,285..2,296] ~ overlap (-1.4%) 2,352 ops/sec [2,340..2,519] → 2,369 ops/sec [2,349..2,781] ~ overlap (+0.7%)
formatRange UTC dates 2,804 ops/sec [2,744..2,830] → 2,745 ops/sec [2,701..2,757] ~ overlap (-2.1%) 2,829 ops/sec [2,794..2,878] → 2,821 ops/sec [2,807..3,246] ~ overlap (-0.3%)
compare numeric strings 94,239 ops/sec [93,353..97,060] → 92,924 ops/sec [92,256..94,172] ~ overlap (-1.4%) 108,866 ops/sec [105,740..110,213] → 102,386 ops/sec [101,605..105,305] 🔴 -6.0%
sort short string list 18,933 ops/sec [18,708..19,446] → 18,400 ops/sec [17,892..18,823] ~ overlap (-2.8%) 20,616 ops/sec [20,521..21,094] → 20,060 ops/sec [19,767..20,967] ~ overlap (-2.7%)
iterators.js — Interp: 🟢 8, 34 unch. · avg +3.5% · Bytecode: 🟢 3, 🔴 6, 33 unch. · avg +0.3%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
Iterator.from({next}).toArray() — 20 elements 2,694 ops/sec [2,381..2,817] → 2,602 ops/sec [2,506..2,958] ~ overlap (-3.4%) 3,597 ops/sec [3,539..3,628] → 3,996 ops/sec [3,911..4,177] 🟢 +11.1%
Iterator.from({next}).toArray() — 50 elements 1,159 ops/sec [1,046..1,182] → 1,087 ops/sec [1,063..1,103] ~ overlap (-6.2%) 1,588 ops/sec [1,584..1,723] → 1,686 ops/sec [1,677..1,800] ~ overlap (+6.2%)
spread pre-wrapped iterator — 20 elements 2,674 ops/sec [2,609..2,684] → 2,796 ops/sec [2,711..3,257] 🟢 +4.6% 5,201 ops/sec [5,142..5,468] → 5,668 ops/sec [5,472..5,817] 🟢 +9.0%
Iterator.from({next}).forEach — 50 elements 799 ops/sec [793..801] → 818 ops/sec [812..820] 🟢 +2.4% 1,275 ops/sec [1,266..1,431] → 1,307 ops/sec [1,293..1,315] ~ overlap (+2.5%)
Iterator.from({next}).reduce — 50 elements 872 ops/sec [849..1,057] → 925 ops/sec [885..1,001] ~ overlap (+6.1%) 1,267 ops/sec [1,261..1,302] → 1,320 ops/sec [1,265..1,410] ~ overlap (+4.2%)
wrap array iterator 16,045 ops/sec [15,589..16,531] → 16,573 ops/sec [16,428..16,651] ~ overlap (+3.3%) 18,336 ops/sec [17,803..20,878] → 18,349 ops/sec [18,264..18,496] ~ overlap (+0.1%)
wrap plain {next()} object 1,838 ops/sec [1,764..1,967] → 1,860 ops/sec [1,825..1,867] ~ overlap (+1.2%) 2,799 ops/sec [2,687..3,913] → 2,880 ops/sec [2,801..3,308] ~ overlap (+2.9%)
map + toArray (50 elements) 690 ops/sec [670..700] → 767 ops/sec [679..1,074] ~ overlap (+11.0%) 914 ops/sec [871..997] → 934 ops/sec [886..938] ~ overlap (+2.2%)
filter + toArray (50 elements) 726 ops/sec [710..733] → 788 ops/sec [715..1,068] ~ overlap (+8.6%) 983 ops/sec [968..998] → 968 ops/sec [960..989] ~ overlap (-1.5%)
take(10) + toArray (50 element source) 3,765 ops/sec [3,600..4,081] → 4,370 ops/sec [3,835..5,034] ~ overlap (+16.1%) 5,300 ops/sec [5,033..5,505] → 5,088 ops/sec [5,050..5,642] ~ overlap (-4.0%)
drop(40) + toArray (50 element source) 1,052 ops/sec [957..1,140] → 989 ops/sec [959..999] ~ overlap (-6.0%) 1,313 ops/sec [1,300..1,418] → 1,309 ops/sec [1,304..1,328] ~ overlap (-0.3%)
chained map + filter + take (100 element source) 1,158 ops/sec [1,136..1,161] → 1,161 ops/sec [1,158..1,226] ~ overlap (+0.3%) 1,543 ops/sec [1,395..1,671] → 1,418 ops/sec [1,393..1,921] ~ overlap (-8.1%)
some + every (50 elements) 496 ops/sec [488..522] → 512 ops/sec [506..615] ~ overlap (+3.3%) 735 ops/sec [727..913] → 712 ops/sec [704..726] 🔴 -3.0%
find (50 elements) 1,126 ops/sec [1,118..1,179] → 1,131 ops/sec [1,125..1,302] ~ overlap (+0.4%) 1,603 ops/sec [1,595..1,617] → 1,575 ops/sec [1,527..1,590] 🔴 -1.7%
concat 2 arrays (10 + 10 elements) 6,985 ops/sec [6,012..8,548] → 6,412 ops/sec [6,091..7,447] ~ overlap (-8.2%) 6,664 ops/sec [6,490..6,865] → 7,255 ops/sec [6,412..7,562] ~ overlap (+8.9%)
concat 5 arrays (10 elements each) 2,886 ops/sec [2,548..3,200] → 2,841 ops/sec [2,759..3,522] ~ overlap (-1.6%) 2,781 ops/sec [2,764..3,800] → 2,849 ops/sec [2,825..3,410] ~ overlap (+2.5%)
concat 2 arrays (20 + 20 elements) 3,792 ops/sec [3,550..4,404] → 3,582 ops/sec [3,481..4,113] ~ overlap (-5.5%) 3,543 ops/sec [3,486..4,687] → 3,653 ops/sec [3,598..3,839] ~ overlap (+3.1%)
concat + filter + toArray (20 + 20 elements) 1,450 ops/sec [1,434..1,813] → 1,507 ops/sec [1,447..1,769] ~ overlap (+4.0%) 1,637 ops/sec [1,541..1,752] → 1,634 ops/sec [1,631..1,643] ~ overlap (-0.2%)
concat + map + take (20 + 20 elements, take 10) 3,679 ops/sec [3,468..4,038] → 3,664 ops/sec [3,606..3,798] ~ overlap (-0.4%) 3,929 ops/sec [3,700..4,211] → 3,838 ops/sec [3,611..3,944] ~ overlap (-2.3%)
concat Sets (15 + 15 elements) 4,797 ops/sec [4,469..5,450] → 5,257 ops/sec [4,608..5,937] ~ overlap (+9.6%) 4,909 ops/sec [4,818..6,003] → 4,794 ops/sec [4,655..4,837] ~ overlap (-2.3%)
concat strings (13 + 13 characters) 4,980 ops/sec [4,905..5,714] → 5,040 ops/sec [4,898..6,666] ~ overlap (+1.2%) 5,240 ops/sec [4,973..5,527] → 5,164 ops/sec [5,013..5,492] ~ overlap (-1.5%)
zip 2 arrays (10 + 10 elements) 11,420 ops/sec [11,209..11,788] → 11,420 ops/sec [9,699..12,555] ~ overlap (+0.0%) 12,848 ops/sec [11,794..14,644] → 11,443 ops/sec [11,376..11,576] 🔴 -10.9%
zip 3 arrays (10 elements each) 10,862 ops/sec [10,757..11,938] → 11,253 ops/sec [10,875..12,698] ~ overlap (+3.6%) 11,469 ops/sec [10,823..11,698] → 11,624 ops/sec [11,369..13,075] ~ overlap (+1.4%)
zip 2 arrays (20 + 20 elements) 6,819 ops/sec [6,643..7,794] → 6,962 ops/sec [6,818..8,956] ~ overlap (+2.1%) 6,852 ops/sec [6,796..6,951] → 7,170 ops/sec [7,053..7,333] 🟢 +4.6%
zip 2 arrays (50 + 50 elements) 3,117 ops/sec [3,033..3,144] → 3,194 ops/sec [2,812..3,829] ~ overlap (+2.5%) 3,238 ops/sec [3,114..3,327] → 3,213 ops/sec [3,162..4,289] ~ overlap (-0.8%)
zip shortest mode (20 + 10 elements) 11,195 ops/sec [11,056..11,266] → 12,593 ops/sec [11,262..13,296] ~ overlap (+12.5%) 12,253 ops/sec [11,739..12,529] → 12,771 ops/sec [11,688..15,192] ~ overlap (+4.2%)
zip longest mode (10 + 20 elements) 6,447 ops/sec [6,346..6,751] → 7,441 ops/sec [7,285..7,583] 🟢 +15.4% 7,021 ops/sec [6,934..7,083] → 6,754 ops/sec [6,604..6,791] 🔴 -3.8%
zip strict mode (20 + 20 elements) 6,618 ops/sec [6,535..7,446] → 7,733 ops/sec [7,512..8,062] 🟢 +16.8% 6,749 ops/sec [6,707..7,169] → 7,943 ops/sec [6,900..8,678] ~ overlap (+17.7%)
zip + map + toArray (20 + 20 elements) 2,139 ops/sec [2,117..2,604] → 2,357 ops/sec [2,156..2,507] ~ overlap (+10.2%) 2,194 ops/sec [2,065..2,250] → 2,605 ops/sec [2,135..2,620] ~ overlap (+18.7%)
zip + filter + toArray (20 + 20 elements) 2,364 ops/sec [2,215..2,703] → 2,406 ops/sec [2,399..2,415] ~ overlap (+1.8%) 2,415 ops/sec [2,374..2,553] → 2,393 ops/sec [2,315..2,714] ~ overlap (-0.9%)
zip Sets (15 + 15 elements) 9,550 ops/sec [8,813..10,684] → 9,701 ops/sec [9,585..9,834] ~ overlap (+1.6%) 10,462 ops/sec [10,371..10,565] → 9,554 ops/sec [9,468..9,617] 🔴 -8.7%
zipKeyed 2 keys (10 elements each) 11,727 ops/sec [10,980..12,498] → 11,989 ops/sec [11,168..13,299] ~ overlap (+2.2%) 11,808 ops/sec [11,640..12,417] → 11,626 ops/sec [11,502..12,266] ~ overlap (-1.5%)
zipKeyed 3 keys (20 elements each) 5,905 ops/sec [5,705..6,479] → 5,738 ops/sec [5,650..6,288] ~ overlap (-2.8%) 6,551 ops/sec [5,750..7,713] → 5,892 ops/sec [5,786..5,967] ~ overlap (-10.1%)
zipKeyed longest mode (10 + 20 elements) 6,204 ops/sec [6,169..6,243] → 6,444 ops/sec [6,284..9,158] 🟢 +3.9% 7,081 ops/sec [6,214..7,479] → 6,497 ops/sec [6,451..7,046] ~ overlap (-8.2%)
zipKeyed strict mode (20 + 20 elements) 6,368 ops/sec [6,273..6,659] → 7,611 ops/sec [6,478..8,974] ~ overlap (+19.5%) 6,606 ops/sec [6,434..8,046] → 6,599 ops/sec [6,570..6,643] ~ overlap (-0.1%)
zipKeyed + filter + map (20 elements) 2,049 ops/sec [1,966..2,198] → 2,113 ops/sec [1,982..2,346] ~ overlap (+3.1%) 2,470 ops/sec [2,327..2,753] → 2,345 ops/sec [2,330..2,356] ~ overlap (-5.1%)
array.values().map().filter().toArray() 800 ops/sec [789..824] → 853 ops/sec [803..885] ~ overlap (+6.6%) 894 ops/sec [874..1,003] → 900 ops/sec [894..902] ~ overlap (+0.6%)
array.values().take(5).toArray() 13,914 ops/sec [13,740..13,980] → 14,663 ops/sec [14,581..16,348] 🟢 +5.4% 15,277 ops/sec [15,213..15,617] → 14,801 ops/sec [14,682..18,886] ~ overlap (-3.1%)
array.values().drop(45).toArray() 2,915 ops/sec [2,872..2,920] → 3,138 ops/sec [2,968..3,173] 🟢 +7.6% 3,069 ops/sec [3,048..3,079] → 3,023 ops/sec [2,995..4,059] ~ overlap (-1.5%)
map.entries() chained helpers 1,137 ops/sec [1,103..1,157] → 1,214 ops/sec [1,203..1,229] 🟢 +6.7% 1,175 ops/sec [1,167..1,354] → 1,124 ops/sec [1,111..1,159] 🔴 -4.4%
set.values() chained helpers 2,423 ops/sec [1,985..2,507] → 1,993 ops/sec [1,928..2,107] ~ overlap (-17.7%) 2,226 ops/sec [2,143..2,294] → 2,146 ops/sec [2,096..2,441] ~ overlap (-3.6%)
string iterator map + toArray 1,982 ops/sec [1,417..3,105] → 2,059 ops/sec [2,025..2,075] ~ overlap (+3.9%) 2,134 ops/sec [2,063..2,233] → 2,106 ops/sec [2,078..2,138] ~ overlap (-1.3%)
json.js — Interp: 🟢 2, 🔴 2, 16 unch. · avg +1.8% · Bytecode: 🔴 6, 14 unch. · avg -1.8%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
parse simple object 54,395 ops/sec [53,296..62,328] → 68,334 ops/sec [62,733..69,792] 🟢 +25.6% 69,848 ops/sec [68,851..70,788] → 65,520 ops/sec [64,608..66,119] 🔴 -6.2%
parse nested object 38,329 ops/sec [36,388..42,709] → 43,007 ops/sec [42,705..47,130] ~ overlap (+12.2%) 44,888 ops/sec [44,422..45,147] → 43,076 ops/sec [42,295..44,092] 🔴 -4.0%
parse array of objects 26,195 ops/sec [26,025..26,402] → 26,500 ops/sec [26,427..26,546] 🟢 +1.2% 27,383 ops/sec [27,089..29,060] → 26,154 ops/sec [25,955..26,550] 🔴 -4.5%
parse large flat object 28,147 ops/sec [28,011..28,611] → 28,702 ops/sec [28,507..28,802] ~ overlap (+2.0%) 28,883 ops/sec [28,449..33,516] → 29,514 ops/sec [29,271..30,842] ~ overlap (+2.2%)
parse mixed types 32,245 ops/sec [31,276..36,244] → 30,793 ops/sec [30,667..30,952] 🔴 -4.5% 35,461 ops/sec [33,490..38,135] → 34,516 ops/sec [33,232..40,371] ~ overlap (-2.7%)
stringify simple object 60,453 ops/sec [59,867..63,734] → 56,416 ops/sec [55,867..57,417] 🔴 -6.7% 59,759 ops/sec [56,550..61,184] → 58,002 ops/sec [57,428..58,503] ~ overlap (-2.9%)
stringify nested object 34,366 ops/sec [34,170..34,486] → 35,477 ops/sec [33,487..36,081] ~ overlap (+3.2%) 31,623 ops/sec [31,383..31,678] → 31,677 ops/sec [31,445..32,504] ~ overlap (+0.2%)
stringify array of objects 14,970 ops/sec [14,906..15,087] → 15,041 ops/sec [14,514..15,252] ~ overlap (+0.5%) 15,939 ops/sec [15,662..16,119] → 17,257 ops/sec [16,012..19,844] ~ overlap (+8.3%)
stringify mixed types 23,478 ops/sec [22,844..23,759] → 25,894 ops/sec [22,783..29,005] ~ overlap (+10.3%) 21,266 ops/sec [21,075..21,796] → 22,079 ops/sec [21,280..23,453] ~ overlap (+3.8%)
reviver doubles numbers 9,824 ops/sec [9,781..9,876] → 10,005 ops/sec [9,108..11,036] ~ overlap (+1.8%) 14,521 ops/sec [14,224..15,420] → 14,321 ops/sec [14,042..16,412] ~ overlap (-1.4%)
reviver filters properties 10,572 ops/sec [9,752..10,840] → 9,809 ops/sec [9,736..10,737] ~ overlap (-7.2%) 12,991 ops/sec [12,717..13,233] → 13,021 ops/sec [12,722..13,697] ~ overlap (+0.2%)
reviver on nested object 13,485 ops/sec [11,327..13,894] → 11,756 ops/sec [11,698..14,175] ~ overlap (-12.8%) 15,992 ops/sec [15,098..17,711] → 15,505 ops/sec [15,434..16,959] ~ overlap (-3.0%)
reviver on array 6,157 ops/sec [6,095..6,718] → 6,143 ops/sec [6,091..8,985] ~ overlap (-0.2%) 9,494 ops/sec [9,026..9,881] → 9,450 ops/sec [8,984..10,120] ~ overlap (-0.5%)
replacer function doubles numbers 11,296 ops/sec [10,848..13,847] → 10,781 ops/sec [10,054..10,857] ~ overlap (-4.6%) 15,461 ops/sec [15,326..15,595] → 15,365 ops/sec [15,056..18,207] ~ overlap (-0.6%)
replacer function excludes properties 14,340 ops/sec [14,177..14,417] → 15,385 ops/sec [11,816..16,575] ~ overlap (+7.3%) 19,042 ops/sec [18,857..22,384] → 18,870 ops/sec [18,286..21,383] ~ overlap (-0.9%)
array replacer (allowlist) 37,977 ops/sec [37,717..38,321] → 39,885 ops/sec [37,870..44,215] ~ overlap (+5.0%) 35,898 ops/sec [34,753..37,985] → 32,535 ops/sec [32,379..32,742] 🔴 -9.4%
stringify with 2-space indent 30,966 ops/sec [29,566..34,146] → 33,889 ops/sec [30,540..37,649] ~ overlap (+9.4%) 30,443 ops/sec [29,538..30,995] → 28,730 ops/sec [28,610..28,973] 🔴 -5.6%
stringify with tab indent 32,949 ops/sec [32,297..33,300] → 30,600 ops/sec [29,653..35,021] ~ overlap (-7.1%) 28,143 ops/sec [27,970..30,349] → 28,337 ops/sec [28,298..38,316] ~ overlap (+0.7%)
parse then stringify 19,040 ops/sec [18,661..21,122] → 18,893 ops/sec [18,655..19,764] ~ overlap (-0.8%) 21,388 ops/sec [20,983..21,822] → 20,881 ops/sec [19,936..21,863] ~ overlap (-2.4%)
stringify then parse 11,668 ops/sec [11,437..12,116] → 11,716 ops/sec [11,424..12,334] ~ overlap (+0.4%) 12,572 ops/sec [12,353..12,713] → 11,719 ops/sec [11,670..11,899] 🔴 -6.8%
jsx.jsx — Interp: 🔴 2, 19 unch. · avg -2.0% · Bytecode: 🟢 2, 🔴 3, 16 unch. · avg -1.2%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
simple element 83,265 ops/sec [75,479..89,019] → 72,408 ops/sec [71,725..75,633] ~ overlap (-13.0%) 90,236 ops/sec [84,879..97,330] → 86,726 ops/sec [84,480..88,003] ~ overlap (-3.9%)
self-closing element 76,076 ops/sec [75,461..86,195] → 75,253 ops/sec [74,374..95,131] ~ overlap (-1.1%) 95,155 ops/sec [91,734..103,454] → 90,903 ops/sec [89,586..92,084] ~ overlap (-4.5%)
element with string attribute 64,591 ops/sec [58,831..72,721] → 66,762 ops/sec [64,862..73,508] ~ overlap (+3.4%) 74,157 ops/sec [73,878..74,199] → 71,171 ops/sec [70,913..72,118] 🔴 -4.0%
element with multiple attributes 56,281 ops/sec [55,560..66,872] → 58,668 ops/sec [54,910..64,772] ~ overlap (+4.2%) 53,964 ops/sec [53,534..54,695] → 52,544 ops/sec [52,380..52,773] 🔴 -2.6%
element with expression attribute 57,951 ops/sec [57,203..58,304] → 57,919 ops/sec [57,598..62,433] ~ overlap (-0.1%) 74,606 ops/sec [71,802..74,678] → 71,287 ops/sec [69,866..75,932] ~ overlap (-4.4%)
text child 75,124 ops/sec [72,293..78,969] → 75,000 ops/sec [73,677..88,031] ~ overlap (-0.2%) 87,726 ops/sec [87,239..94,495] → 88,036 ops/sec [86,065..123,441] ~ overlap (+0.4%)
expression child 72,959 ops/sec [71,244..83,854] → 69,747 ops/sec [68,036..78,044] ~ overlap (-4.4%) 84,988 ops/sec [84,235..88,290] → 84,404 ops/sec [84,038..84,633] ~ overlap (-0.7%)
mixed text and expression 67,777 ops/sec [67,236..90,952] → 67,209 ops/sec [64,985..80,089] ~ overlap (-0.8%) 77,535 ops/sec [75,426..91,297] → 76,187 ops/sec [74,924..77,778] ~ overlap (-1.7%)
nested elements (3 levels) 31,626 ops/sec [29,343..49,079] → 30,133 ops/sec [29,761..33,825] ~ overlap (-4.7%) 34,402 ops/sec [33,309..40,476] → 34,012 ops/sec [33,419..41,240] ~ overlap (-1.1%)
sibling children 22,896 ops/sec [21,933..22,980] → 22,603 ops/sec [22,406..27,993] ~ overlap (-1.3%) 25,381 ops/sec [24,644..26,420] → 25,372 ops/sec [25,350..25,430] ~ overlap (-0.0%)
component element 55,435 ops/sec [54,319..70,080] → 55,321 ops/sec [52,882..65,345] ~ overlap (-0.2%) 70,009 ops/sec [65,477..80,587] → 65,873 ops/sec [62,412..69,347] ~ overlap (-5.9%)
component with children 43,123 ops/sec [34,457..55,137] → 34,080 ops/sec [33,091..39,789] ~ overlap (-21.0%) 40,938 ops/sec [40,095..42,552] → 40,845 ops/sec [39,824..44,193] ~ overlap (-0.2%)
dotted component 47,568 ops/sec [46,095..47,909] → 46,306 ops/sec [45,801..48,675] ~ overlap (-2.7%) 53,423 ops/sec [51,770..58,871] → 52,958 ops/sec [52,604..53,245] ~ overlap (-0.9%)
empty fragment 78,054 ops/sec [77,585..100,199] → 78,013 ops/sec [75,980..87,644] ~ overlap (-0.1%) 99,789 ops/sec [98,161..103,164] → 99,275 ops/sec [98,113..103,323] ~ overlap (-0.5%)
fragment with children 23,414 ops/sec [22,975..24,645] → 22,374 ops/sec [20,147..25,730] ~ overlap (-4.4%) 27,032 ops/sec [25,098..30,830] → 25,713 ops/sec [25,288..25,815] ~ overlap (-4.9%)
spread attributes 38,484 ops/sec [38,280..38,600] → 37,033 ops/sec [35,417..53,175] ~ overlap (-3.8%) 39,117 ops/sec [38,687..49,131] → 37,579 ops/sec [37,249..37,718] 🔴 -3.9%
spread with overrides 34,713 ops/sec [34,554..34,762] → 38,606 ops/sec [32,832..43,710] ~ overlap (+11.2%) 33,371 ops/sec [31,875..33,467] → 34,209 ops/sec [33,705..35,085] 🟢 +2.5%
shorthand props 56,270 ops/sec [55,979..61,719] → 71,237 ops/sec [52,093..86,386] ~ overlap (+26.6%) 58,141 ops/sec [57,581..60,794] → 57,125 ops/sec [56,610..61,693] ~ overlap (-1.7%)
nav bar structure 13,078 ops/sec [10,892..14,728] → 10,373 ops/sec [9,796..10,691] 🔴 -20.7% 11,992 ops/sec [11,914..12,053] → 12,326 ops/sec [12,164..12,361] 🟢 +2.8%
card component tree 13,053 ops/sec [12,911..15,715] → 12,161 ops/sec [11,798..12,558] 🔴 -6.8% 13,659 ops/sec [13,621..14,042] → 14,011 ops/sec [13,761..15,964] ~ overlap (+2.6%)
10 list items via Array.from 5,724 ops/sec [5,634..5,796] → 5,552 ops/sec [5,486..7,255] ~ overlap (-3.0%) 5,610 ops/sec [5,045..5,625] → 6,097 ops/sec [5,511..7,219] ~ overlap (+8.7%)
modules.js — Interp: 9 unch. · avg +1.5% · Bytecode: 9 unch. · avg -0.5%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
call imported function 131,480 ops/sec [126,280..138,448] → 130,096 ops/sec [126,964..143,319] ~ overlap (-1.1%) 43,973 ops/sec [43,525..49,621] → 42,994 ops/sec [42,696..44,493] ~ overlap (-2.2%)
call two imported functions 79,509 ops/sec [71,836..97,473] → 74,112 ops/sec [71,091..79,903] ~ overlap (-6.8%) 23,566 ops/sec [22,866..24,810] → 24,052 ops/sec [22,111..25,425] ~ overlap (+2.1%)
read imported constant 338,713 ops/sec [325,432..427,081] → 341,212 ops/sec [336,778..344,547] ~ overlap (+0.7%) 48,887 ops/sec [46,685..60,765] → 51,109 ops/sec [47,303..54,404] ~ overlap (+4.5%)
read imported string 338,492 ops/sec [333,711..347,189] → 342,803 ops/sec [330,920..363,768] ~ overlap (+1.3%) 49,065 ops/sec [46,398..53,120] → 47,457 ops/sec [47,113..49,921] ~ overlap (-3.3%)
read JSON string property 341,345 ops/sec [335,172..351,116] → 379,478 ops/sec [346,394..440,304] ~ overlap (+11.2%) 49,701 ops/sec [48,401..55,208] → 52,040 ops/sec [46,804..54,667] ~ overlap (+4.7%)
read JSON number property 346,929 ops/sec [324,794..375,820] → 375,099 ops/sec [336,720..433,841] ~ overlap (+8.1%) 47,539 ops/sec [46,119..48,745] → 47,343 ops/sec [45,857..51,262] ~ overlap (-0.4%)
read JSON boolean property 359,550 ops/sec [331,474..541,589] → 349,024 ops/sec [338,725..439,801] ~ overlap (-2.9%) 48,779 ops/sec [46,456..63,331] → 49,249 ops/sec [47,978..60,309] ~ overlap (+1.0%)
read JSON array property 344,061 ops/sec [339,359..349,026] → 347,354 ops/sec [339,012..398,984] ~ overlap (+1.0%) 48,593 ops/sec [47,236..53,306] → 48,339 ops/sec [47,038..48,972] ~ overlap (-0.5%)
read multiple JSON properties 196,116 ops/sec [193,418..200,191] → 200,454 ops/sec [188,974..238,742] ~ overlap (+2.2%) 19,007 ops/sec [16,768..19,569] → 17,091 ops/sec [16,674..17,220] ~ overlap (-10.1%)
numbers.js — Interp: 11 unch. · avg -1.6% · Bytecode: 🟢 3, 8 unch. · avg +5.4%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
integer arithmetic 95,658 ops/sec [93,686..98,699] → 93,498 ops/sec [90,462..96,204] ~ overlap (-2.3%) 366,549 ops/sec [358,608..385,299] → 389,104 ops/sec [369,048..423,873] ~ overlap (+6.2%)
floating point arithmetic 112,692 ops/sec [111,468..120,854] → 114,260 ops/sec [108,991..135,083] ~ overlap (+1.4%) 218,044 ops/sec [217,350..219,569] → 221,897 ops/sec [213,287..248,325] ~ overlap (+1.8%)
number coercion 43,910 ops/sec [41,898..51,446] → 44,484 ops/sec [42,370..45,281] ~ overlap (+1.3%) 61,894 ops/sec [53,983..63,755] → 63,962 ops/sec [60,253..67,204] ~ overlap (+3.3%)
toFixed 34,573 ops/sec [33,228..34,743] → 33,229 ops/sec [30,146..37,934] ~ overlap (-3.9%) 35,442 ops/sec [35,350..35,559] → 40,710 ops/sec [37,151..43,159] 🟢 +14.9%
toString 56,897 ops/sec [47,703..60,343] → 50,701 ops/sec [43,879..57,534] ~ overlap (-10.9%) 64,442 ops/sec [62,562..79,741] → 63,445 ops/sec [62,720..68,934] ~ overlap (-1.5%)
valueOf 75,089 ops/sec [69,238..85,209] → 71,917 ops/sec [59,747..78,910] ~ overlap (-4.2%) 93,684 ops/sec [91,767..110,288] → 94,113 ops/sec [91,486..103,134] ~ overlap (+0.5%)
toPrecision 27,811 ops/sec [23,445..33,855] → 24,904 ops/sec [22,577..32,940] ~ overlap (-10.5%) 25,138 ops/sec [24,871..28,209] → 27,506 ops/sec [26,753..29,135] ~ overlap (+9.4%)
Number.isNaN 77,769 ops/sec [75,510..90,060] → 89,184 ops/sec [72,680..93,555] ~ overlap (+14.7%) 102,523 ops/sec [99,716..129,796] → 107,154 ops/sec [101,090..130,658] ~ overlap (+4.5%)
Number.isFinite 83,177 ops/sec [75,947..91,377] → 74,159 ops/sec [71,340..93,282] ~ overlap (-10.8%) 93,812 ops/sec [81,537..94,635] → 102,931 ops/sec [101,503..103,322] 🟢 +9.7%
Number.isInteger 78,254 ops/sec [77,272..78,300] → 82,270 ops/sec [77,788..85,304] ~ overlap (+5.1%) 96,940 ops/sec [93,877..99,829] → 98,938 ops/sec [98,183..99,325] ~ overlap (+2.1%)
Number.parseInt and parseFloat 65,495 ops/sec [63,586..89,564] → 66,918 ops/sec [61,263..69,348] ~ overlap (+2.2%) 73,968 ops/sec [72,133..74,303] → 80,373 ops/sec [74,665..90,624] 🟢 +8.7%
objects.js — Interp: 7 unch. · avg +2.3% · Bytecode: 🔴 1, 6 unch. · avg -2.5%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
create simple object 148,053 ops/sec [145,993..151,719] → 148,527 ops/sec [138,969..161,812] ~ overlap (+0.3%) 131,316 ops/sec [130,137..131,478] → 127,392 ops/sec [126,862..129,817] 🔴 -3.0%
create nested object 81,775 ops/sec [81,161..83,971] → 83,292 ops/sec [79,795..99,925] ~ overlap (+1.9%) 61,081 ops/sec [60,845..77,405] → 62,364 ops/sec [59,601..71,951] ~ overlap (+2.1%)
create 50 objects via Array.from 3,370 ops/sec [3,335..3,581] → 3,560 ops/sec [3,310..4,117] ~ overlap (+5.6%) 2,483 ops/sec [2,421..2,593] → 2,506 ops/sec [2,451..3,055] ~ overlap (+0.9%)
property read 134,551 ops/sec [128,783..144,390] → 130,747 ops/sec [125,293..138,638] ~ overlap (-2.8%) 305,828 ops/sec [264,971..322,490] → 292,212 ops/sec [260,323..369,708] ~ overlap (-4.5%)
Object.keys 85,798 ops/sec [84,154..97,280] → 85,004 ops/sec [80,099..103,833] ~ overlap (-0.9%) 116,624 ops/sec [97,650..123,730] → 102,024 ops/sec [97,371..147,891] ~ overlap (-12.5%)
Object.entries 43,147 ops/sec [41,006..45,825] → 43,039 ops/sec [39,627..59,793] ~ overlap (-0.2%) 44,644 ops/sec [43,738..56,236] → 44,445 ops/sec [43,946..44,563] ~ overlap (-0.4%)
spread operator 52,641 ops/sec [50,713..77,050] → 59,083 ops/sec [52,176..66,341] ~ overlap (+12.2%) 53,097 ops/sec [52,777..53,467] → 53,151 ops/sec [52,237..59,215] ~ overlap (+0.1%)
promises.js — Interp: 12 unch. · avg +0.3% · Bytecode: 🟢 3, 9 unch. · avg +4.0%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
Promise.resolve(value) 69,351 ops/sec [68,764..69,619] → 67,644 ops/sec [64,699..70,711] ~ overlap (-2.5%) 76,589 ops/sec [75,219..83,451] → 99,786 ops/sec [78,347..108,422] ~ overlap (+30.3%)
new Promise(resolve => resolve(value)) 50,920 ops/sec [48,687..52,401] → 48,070 ops/sec [47,193..63,794] ~ overlap (-5.6%) 59,654 ops/sec [57,146..70,210] → 62,474 ops/sec [58,370..67,669] ~ overlap (+4.7%)
Promise.reject(reason) 70,871 ops/sec [67,927..74,872] → 67,601 ops/sec [65,530..68,116] ~ overlap (-4.6%) 76,950 ops/sec [74,260..77,918] → 77,945 ops/sec [76,231..96,811] ~ overlap (+1.3%)
resolve + then (1 handler) 22,562 ops/sec [22,020..24,989] → 22,267 ops/sec [22,228..22,322] ~ overlap (-1.3%) 25,647 ops/sec [25,560..25,876] → 28,214 ops/sec [27,158..30,149] 🟢 +10.0%
resolve + then chain (3 deep) 9,483 ops/sec [9,353..9,576] → 9,493 ops/sec [9,332..11,227] ~ overlap (+0.1%) 11,419 ops/sec [10,477..12,891] → 10,761 ops/sec [10,139..10,976] ~ overlap (-5.8%)
resolve + then chain (10 deep) 3,208 ops/sec [3,075..3,391] → 3,332 ops/sec [3,160..4,393] ~ overlap (+3.9%) 3,647 ops/sec [3,473..3,732] → 3,556 ops/sec [3,549..3,587] ~ overlap (-2.5%)
reject + catch + then 13,780 ops/sec [13,249..16,272] → 14,766 ops/sec [13,318..17,314] ~ overlap (+7.2%) 15,395 ops/sec [14,506..15,804] → 14,864 ops/sec [14,744..16,809] ~ overlap (-3.5%)
resolve + finally + then 6,670 ops/sec [6,276..7,576] → 6,485 ops/sec [6,257..7,392] ~ overlap (-2.8%) 6,876 ops/sec [6,731..7,737] → 6,796 ops/sec [6,700..6,906] ~ overlap (-1.2%)
Promise.all (5 resolved) 4,382 ops/sec [4,293..4,428] → 4,681 ops/sec [4,270..5,349] ~ overlap (+6.8%) 4,709 ops/sec [4,662..4,750] → 4,903 ops/sec [4,852..4,930] 🟢 +4.1%
Promise.race (5 resolved) 5,051 ops/sec [4,954..6,992] → 5,102 ops/sec [4,810..6,355] ~ overlap (+1.0%) 5,287 ops/sec [5,257..5,304] → 5,610 ops/sec [5,231..5,632] ~ overlap (+6.1%)
Promise.allSettled (5 mixed) 4,130 ops/sec [3,819..4,986] → 4,316 ops/sec [3,686..5,010] ~ overlap (+4.5%) 4,054 ops/sec [3,842..4,100] → 3,908 ops/sec [3,809..4,039] ~ overlap (-3.6%)
Promise.any (5 mixed) 4,923 ops/sec [4,410..5,186] → 4,746 ops/sec [4,422..5,435] ~ overlap (-3.6%) 4,679 ops/sec [4,540..4,733] → 5,062 ops/sec [4,791..5,455] 🟢 +8.2%
property-access.js — Interp: 🔴 1, 4 unch. · avg -3.8% · Bytecode: 5 unch. · avg +1.3%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
class instance fields across 1000 instances 140 ops/sec [138..143] → 135 ops/sec [132..144] ~ overlap (-4.0%) 643 ops/sec [627..656] → 666 ops/sec [647..903] ~ overlap (+3.6%)
object literal fields across 1000 literals 145 ops/sec [144..145] → 137 ops/sec [127..142] 🔴 -5.2% 654 ops/sec [644..669] → 677 ops/sec [661..683] ~ overlap (+3.6%)
mixed-shape literals across 1000 literals 159 ops/sec [139..177] → 143 ops/sec [136..226] ~ overlap (-10.0%) 517 ops/sec [512..520] → 525 ops/sec [511..547] ~ overlap (+1.6%)
own-class method across 1000 instances 86 ops/sec [85..86] → 85 ops/sec [84..91] ~ overlap (-0.7%) 355 ops/sec [355..400] → 345 ops/sec [329..355] ~ overlap (-2.9%)
inherited method across 1000 instances 93 ops/sec [92..98] → 94 ops/sec [91..103] ~ overlap (+1.0%) 386 ops/sec [385..387] → 388 ops/sec [378..397] ~ overlap (+0.6%)
regexp.js — Interp: 11 unch. · avg -2.0% · Bytecode: 🟢 1, 🔴 1, 9 unch. · avg +1.5%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
regex literal creation 7,678 ops/sec [7,447..8,057] → 6,743 ops/sec [6,538..7,640] ~ overlap (-12.2%) 183,099 ops/sec [181,584..183,786] → 189,741 ops/sec [173,782..241,065] ~ overlap (+3.6%)
new RegExp(pattern, flags) 6,803 ops/sec [6,503..6,821] → 6,952 ops/sec [6,437..7,345] ~ overlap (+2.2%) 6,980 ops/sec [6,686..7,243] → 7,045 ops/sec [6,841..7,658] ~ overlap (+0.9%)
RegExp(existingRegex) returns the same regex 174,914 ops/sec [173,907..181,546] → 171,935 ops/sec [169,308..176,629] ~ overlap (-1.7%) 274,925 ops/sec [274,725..275,648] → 282,672 ops/sec [275,070..296,214] ~ overlap (+2.8%)
test() on a global regex 54,661 ops/sec [53,693..56,043] → 56,982 ops/sec [52,815..67,053] ~ overlap (+4.2%) 72,688 ops/sec [71,555..73,193] → 82,859 ops/sec [74,612..88,468] 🟢 +14.0%
exec() with capture groups 15,696 ops/sec [15,084..16,846] → 14,995 ops/sec [14,765..16,603] ~ overlap (-4.5%) 16,886 ops/sec [16,769..18,128] → 16,809 ops/sec [16,766..17,951] ~ overlap (-0.5%)
toString() 150,749 ops/sec [149,645..152,557] → 150,746 ops/sec [148,919..153,749] ~ overlap (-0.0%) 229,002 ops/sec [227,700..229,645] → 229,720 ops/sec [228,039..230,259] ~ overlap (+0.3%)
match() with global regex 20,360 ops/sec [20,201..20,368] → 20,358 ops/sec [19,731..20,996] ~ overlap (-0.0%) 23,089 ops/sec [22,394..25,174] → 23,951 ops/sec [22,433..25,915] ~ overlap (+3.7%)
matchAll() with capture groups 9,687 ops/sec [9,383..10,455] → 10,190 ops/sec [9,145..12,372] ~ overlap (+5.2%) 14,584 ops/sec [14,180..14,651] → 14,435 ops/sec [14,216..14,501] ~ overlap (-1.0%)
replace() with global regex 20,104 ops/sec [17,682..23,584] → 18,045 ops/sec [17,842..22,872] ~ overlap (-10.2%) 20,331 ops/sec [20,260..23,211] → 20,043 ops/sec [19,869..20,191] 🔴 -1.4%
search() with regex 45,568 ops/sec [40,354..50,680] → 43,733 ops/sec [39,845..45,228] ~ overlap (-4.0%) 49,320 ops/sec [46,581..68,243] → 47,206 ops/sec [46,935..47,607] ~ overlap (-4.3%)
split() with regex separator 7,522 ops/sec [7,217..8,469] → 7,462 ops/sec [7,240..8,210] ~ overlap (-0.8%) 7,819 ops/sec [7,655..8,118] → 7,651 ops/sec [7,330..7,841] ~ overlap (-2.1%)
strings.js — Interp: 🔴 1, 18 unch. · avg -0.8% · Bytecode: 🔴 3, 16 unch. · avg -1.4%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
string concatenation 112,648 ops/sec [111,297..113,254] → 114,741 ops/sec [111,301..123,218] ~ overlap (+1.9%) 500,912 ops/sec [478,185..625,728] → 497,108 ops/sec [495,764..497,342] ~ overlap (-0.8%)
template literal 216,814 ops/sec [197,041..343,554] → 196,633 ops/sec [190,680..275,994] ~ overlap (-9.3%) 416,117 ops/sec [405,652..455,463] → 380,208 ops/sec [374,750..381,265] 🔴 -8.6%
string repeat 137,014 ops/sec [127,100..160,373] → 129,523 ops/sec [126,891..140,584] ~ overlap (-5.5%) 183,130 ops/sec [161,726..204,446] → 165,680 ops/sec [159,663..167,671] ~ overlap (-9.5%)
split and join 48,646 ops/sec [47,437..50,574] → 48,062 ops/sec [46,710..70,758] ~ overlap (-1.2%) 59,584 ops/sec [54,647..68,052] → 57,597 ops/sec [54,588..62,311] ~ overlap (-3.3%)
indexOf and includes 52,710 ops/sec [51,032..57,548] → 52,514 ops/sec [51,703..82,053] ~ overlap (-0.4%) 58,595 ops/sec [58,116..58,997] → 57,875 ops/sec [57,008..77,350] ~ overlap (-1.2%)
toUpperCase and toLowerCase 66,451 ops/sec [65,826..66,625] → 65,629 ops/sec [64,284..67,210] ~ overlap (-1.2%) 83,264 ops/sec [79,605..90,151] → 86,351 ops/sec [76,688..99,641] ~ overlap (+3.7%)
slice and substring 51,643 ops/sec [47,614..61,737] → 48,762 ops/sec [47,161..49,286] ~ overlap (-5.6%) 61,708 ops/sec [58,717..76,363] → 62,629 ops/sec [59,877..79,378] ~ overlap (+1.5%)
trim operations 56,719 ops/sec [56,599..57,427] → 57,828 ops/sec [55,928..58,040] ~ overlap (+2.0%) 71,974 ops/sec [70,922..75,169] → 74,689 ops/sec [69,253..85,244] ~ overlap (+3.8%)
replace and replaceAll 56,532 ops/sec [55,499..61,170] → 55,584 ops/sec [55,121..57,552] ~ overlap (-1.7%) 63,872 ops/sec [63,607..64,212] → 63,708 ops/sec [61,977..68,498] ~ overlap (-0.3%)
startsWith and endsWith 41,342 ops/sec [40,145..41,553] → 40,466 ops/sec [39,622..42,622] ~ overlap (-2.1%) 46,515 ops/sec [41,090..49,792] → 45,601 ops/sec [45,138..47,678] ~ overlap (-2.0%)
padStart and padEnd 65,193 ops/sec [63,491..77,002] → 66,441 ops/sec [64,237..75,612] ~ overlap (+1.9%) 76,870 ops/sec [75,208..77,350] → 78,740 ops/sec [75,477..89,869] ~ overlap (+2.4%)
identity tag, no substitutions 104,120 ops/sec [103,257..105,636] → 105,226 ops/sec [96,714..118,291] ~ overlap (+1.1%) 159,436 ops/sec [157,151..160,893] → 160,403 ops/sec [153,708..185,954] ~ overlap (+0.6%)
tag with 1 substitution 24,700 ops/sec [24,435..25,297] → 24,892 ops/sec [24,472..26,527] ~ overlap (+0.8%) 32,606 ops/sec [32,238..37,268] → 31,695 ops/sec [31,471..31,898] 🔴 -2.8%
tag with 3 substitutions 13,757 ops/sec [13,485..14,403] → 13,878 ops/sec [13,813..13,987] ~ overlap (+0.9%) 19,552 ops/sec [18,932..22,438] → 18,899 ops/sec [18,686..19,183] ~ overlap (-3.3%)
tag with 6 substitutions 8,361 ops/sec [8,268..8,397] → 8,358 ops/sec [8,231..8,977] ~ overlap (-0.0%) 11,965 ops/sec [11,678..12,153] → 11,698 ops/sec [11,471..11,801] ~ overlap (-2.2%)
String.raw, no substitutions 86,507 ops/sec [78,975..90,028] → 86,575 ops/sec [85,698..86,832] ~ overlap (+0.1%) 89,418 ops/sec [88,700..89,963] → 88,007 ops/sec [87,874..88,170] 🔴 -1.6%
String.raw, 2 substitutions 71,032 ops/sec [70,802..71,892] → 68,684 ops/sec [68,237..69,092] 🔴 -3.3% 71,933 ops/sec [71,189..82,235] → 71,010 ops/sec [70,728..71,481] ~ overlap (-1.3%)
tag accessing .raw array 40,020 ops/sec [38,996..40,510] → 40,428 ops/sec [39,664..47,191] ~ overlap (+1.0%) 45,254 ops/sec [43,363..47,193] → 44,220 ops/sec [43,893..46,116] ~ overlap (-2.3%)
method as tag (this binding) 16,874 ops/sec [16,767..18,104] → 17,798 ops/sec [16,197..19,301] ~ overlap (+5.5%) 22,151 ops/sec [21,919..22,559] → 22,402 ops/sec [22,026..22,726] ~ overlap (+1.1%)
temporal.js — Interp: 🟢 1, 5 unch. · avg -0.4% · Bytecode: 6 unch. · avg -1.9%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
PlainDate.add({ months: 1 }) 42,412 ops/sec [41,301..52,057] → 40,438 ops/sec [38,886..42,647] ~ overlap (-4.7%) 45,594 ops/sec [44,689..46,694] → 46,235 ops/sec [45,219..49,881] ~ overlap (+1.4%)
PlainDate.until(..., { largestUnit: 'months' }) 50,485 ops/sec [49,811..52,968] → 51,873 ops/sec [49,793..57,910] ~ overlap (+2.7%) 55,384 ops/sec [54,492..55,605] → 56,412 ops/sec [55,398..64,324] ~ overlap (+1.9%)
Duration.total days relative to PlainDate 45,203 ops/sec [42,995..45,272] → 46,155 ops/sec [45,816..46,548] 🟢 +2.1% 47,764 ops/sec [45,594..48,006] → 47,737 ops/sec [45,602..48,656] ~ overlap (-0.1%)
Duration.round to hours 33,110 ops/sec [32,388..38,273] → 32,723 ops/sec [32,574..32,830] ~ overlap (-1.2%) 33,656 ops/sec [32,746..37,381] → 32,411 ops/sec [32,046..52,442] ~ overlap (-3.7%)
ZonedDateTime.from named time zone 9,336 ops/sec [9,154..9,356] → 9,258 ops/sec [9,207..9,305] ~ overlap (-0.8%) 9,773 ops/sec [9,497..10,459] → 9,969 ops/sec [9,534..10,245] ~ overlap (+2.0%)
ZonedDateTime.since across DST 9,889 ops/sec [9,766..10,386] → 9,811 ops/sec [9,691..9,964] ~ overlap (-0.8%) 11,745 ops/sec [10,049..13,756] → 10,221 ops/sec [10,121..11,723] ~ overlap (-13.0%)
tsv.js — Interp: 9 unch. · avg +1.0% · Bytecode: 🟢 2, 7 unch. · avg +1.3%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
parse simple 3-column TSV 39,559 ops/sec [38,800..40,417] → 39,907 ops/sec [39,372..40,906] ~ overlap (+0.9%) 42,305 ops/sec [41,925..45,689] → 42,664 ops/sec [42,464..43,413] ~ overlap (+0.8%)
parse 10-row TSV 11,112 ops/sec [11,019..12,895] → 11,268 ops/sec [11,166..11,700] ~ overlap (+1.4%) 11,446 ops/sec [11,296..17,902] → 11,393 ops/sec [11,145..12,177] ~ overlap (-0.5%)
parse 100-row TSV 1,877 ops/sec [1,793..2,306] → 1,793 ops/sec [1,755..2,647] ~ overlap (-4.5%) 1,838 ops/sec [1,806..2,104] → 1,808 ops/sec [1,746..2,003] ~ overlap (-1.7%)
parse TSV with backslash-escaped fields 8,483 ops/sec [8,427..10,015] → 8,554 ops/sec [8,177..10,139] ~ overlap (+0.8%) 8,726 ops/sec [8,535..8,764] → 8,595 ops/sec [8,494..8,619] ~ overlap (-1.5%)
parse without headers (array of arrays) 5,748 ops/sec [5,606..6,650] → 5,654 ops/sec [5,431..6,639] ~ overlap (-1.6%) 5,666 ops/sec [5,572..5,730] → 5,700 ops/sec [5,608..5,742] ~ overlap (+0.6%)
stringify array of objects 34,859 ops/sec [34,459..35,148] → 34,727 ops/sec [33,892..40,071] ~ overlap (-0.4%) 38,060 ops/sec [38,034..38,119] → 39,605 ops/sec [39,491..39,770] 🟢 +4.1%
stringify array of arrays 11,147 ops/sec [10,970..12,174] → 11,781 ops/sec [10,662..12,495] ~ overlap (+5.7%) 11,065 ops/sec [10,914..11,278] → 11,218 ops/sec [11,104..12,343] ~ overlap (+1.4%)
stringify with values needing escaping 28,081 ops/sec [27,854..29,209] → 30,580 ops/sec [28,307..32,953] ~ overlap (+8.9%) 31,039 ops/sec [30,218..31,510] → 33,406 ops/sec [31,806..37,225] 🟢 +7.6%
parse then stringify 6,895 ops/sec [6,636..7,453] → 6,752 ops/sec [6,420..7,250] ~ overlap (-2.1%) 6,554 ops/sec [6,434..6,942] → 6,599 ops/sec [6,499..7,723] ~ overlap (+0.7%)
typed-arrays.js — Interp: 🟢 7, 15 unch. · avg +18.9% · Bytecode: 🟢 6, 🔴 3, 13 unch. · avg +20.1%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
new Int32Array(0) 97,372 ops/sec [94,920..128,583] → 107,666 ops/sec [94,789..117,657] ~ overlap (+10.6%) 116,850 ops/sec [116,027..117,079] → 123,868 ops/sec [114,615..154,983] ~ overlap (+6.0%)
new Int32Array(100) 90,788 ops/sec [87,072..102,542] → 91,738 ops/sec [89,587..92,806] ~ overlap (+1.0%) 109,427 ops/sec [107,606..120,559] → 111,866 ops/sec [110,088..138,772] ~ overlap (+2.2%)
new Int32Array(1000) 80,496 ops/sec [71,182..83,933] → 72,464 ops/sec [72,273..72,788] ~ overlap (-10.0%) 83,824 ops/sec [77,895..100,335] → 86,537 ops/sec [85,462..87,282] ~ overlap (+3.2%)
new Float64Array(100) 90,110 ops/sec [88,957..90,448] → 89,559 ops/sec [88,616..89,784] ~ overlap (-0.6%) 109,608 ops/sec [102,876..111,532] → 108,209 ops/sec [107,367..108,457] ~ overlap (-1.3%)
Int32Array.from([...]) 1,497 ops/sec [1,430..1,800] → 1,480 ops/sec [1,479..1,513] ~ overlap (-1.1%) 1,480 ops/sec [1,464..1,493] → 1,510 ops/sec [1,483..1,525] ~ overlap (+2.0%)
Int32Array.of(1, 2, 3, 4, 5) 67,629 ops/sec [66,218..72,759] → 68,101 ops/sec [67,919..68,991] ~ overlap (+0.7%) 79,103 ops/sec [78,154..79,645] → 79,849 ops/sec [78,693..80,009] ~ overlap (+0.9%)
sequential write 100 elements 1,068 ops/sec [1,047..1,105] → 1,068 ops/sec [1,066..1,070] ~ overlap (-0.0%) 3,644 ops/sec [3,630..5,015] → 3,414 ops/sec [3,380..3,558] 🔴 -6.3%
sequential read 100 elements 1,137 ops/sec [1,072..1,144] → 1,148 ops/sec [1,140..1,264] ~ overlap (+1.0%) 4,115 ops/sec [4,092..4,141] → 3,992 ops/sec [3,899..4,010] 🔴 -3.0%
Float64Array write 100 elements 1,020 ops/sec [1,002..1,048] → 1,024 ops/sec [995..1,204] ~ overlap (+0.4%) 3,235 ops/sec [3,182..3,261] → 3,164 ops/sec [3,006..3,211] ~ overlap (-2.2%)
fill(42) 2,007 ops/sec [1,937..2,174] → 3,688 ops/sec [3,634..3,713] 🟢 +83.8% 2,051 ops/sec [2,032..2,065] → 2,044 ops/sec [2,017..2,414] ~ overlap (-0.3%)
slice() 8,440 ops/sec [8,257..8,651] → 14,405 ops/sec [8,833..14,538] 🟢 +70.7% 8,609 ops/sec [8,564..8,974] → 14,653 ops/sec [14,516..14,809] 🟢 +70.2%
map(x => x * 2) 1,968 ops/sec [1,944..2,015] → 3,224 ops/sec [3,211..3,230] 🟢 +63.9% 2,100 ops/sec [2,022..2,459] → 3,557 ops/sec [3,512..3,604] 🟢 +69.4%
filter(x => x > 50) 2,072 ops/sec [2,060..2,073] → 2,140 ops/sec [2,115..3,427] 🟢 +3.3% 2,302 ops/sec [2,295..2,306] → 4,021 ops/sec [4,005..4,048] 🟢 +74.7%
reduce (sum) 2,155 ops/sec [2,148..2,162] → 2,158 ops/sec [2,155..2,164] ~ overlap (+0.2%) 2,230 ops/sec [2,198..2,302] → 2,242 ops/sec [2,235..2,289] ~ overlap (+0.5%)
sort() 12,957 ops/sec [12,895..13,032] → 13,403 ops/sec [13,241..13,451] 🟢 +3.4% 13,328 ops/sec [13,084..13,429] → 24,039 ops/sec [13,310..24,126] ~ overlap (+80.4%)
indexOf() 29,172 ops/sec [27,815..30,894] → 29,899 ops/sec [29,345..30,026] ~ overlap (+2.5%) 30,324 ops/sec [30,044..30,688] → 52,216 ops/sec [52,043..52,278] 🟢 +72.2%
reverse() 15,594 ops/sec [14,438..17,919] → 14,675 ops/sec [14,575..14,788] ~ overlap (-5.9%) 15,540 ops/sec [14,942..17,507] → 27,571 ops/sec [27,398..27,786] 🟢 +77.4%
create view over existing buffer 122,535 ops/sec [120,798..123,917] → 170,312 ops/sec [169,447..170,441] 🟢 +39.0% 215,698 ops/sec [147,198..217,883] → 210,741 ops/sec [129,100..213,100] ~ overlap (-2.3%)
subarray() 68,499 ops/sec [67,382..78,461] → 110,957 ops/sec [109,451..111,880] 🟢 +62.0% 127,402 ops/sec [126,788..127,925] → 123,229 ops/sec [122,938..123,795] 🔴 -3.3%
set() from array 75,949 ops/sec [75,844..76,974] → 76,206 ops/sec [75,248..121,666] ~ overlap (+0.3%) 155,351 ops/sec [154,594..155,452] → 154,993 ops/sec [154,180..155,389] ~ overlap (-0.2%)
for-of loop 1,593 ops/sec [1,577..1,756] → 2,440 ops/sec [1,520..2,466] ~ overlap (+53.2%) 13,265 ops/sec [12,932..13,277] → 13,236 ops/sec [13,179..13,299] ~ overlap (-0.2%)
spread into array 7,129 ops/sec [6,263..10,062] → 9,872 ops/sec [9,800..9,921] ~ overlap (+38.5%) 39,022 ops/sec [38,742..39,358] → 39,947 ops/sec [39,718..40,230] 🟢 +2.4%
uint8array-encoding.js — Interp: 🟢 1, 🔴 6, 11 unch. · avg -14.7% · Bytecode: 🔴 4, 14 unch. · avg -8.9%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
short (5 bytes) 141,956 ops/sec [139,488..144,075] → 138,193 ops/sec [136,378..143,179] ~ overlap (-2.7%) 188,158 ops/sec [182,695..204,232] → 184,348 ops/sec [182,081..185,331] ~ overlap (-2.0%)
medium (450 bytes) 99,200 ops/sec [97,166..101,877] → 99,893 ops/sec [98,817..100,993] ~ overlap (+0.7%) 117,400 ops/sec [116,805..118,705] → 117,003 ops/sec [116,072..123,037] ~ overlap (-0.3%)
large (4096 bytes) 29,062 ops/sec [28,690..29,514] → 29,450 ops/sec [29,247..29,688] ~ overlap (+1.3%) 31,274 ops/sec [31,138..31,806] → 31,662 ops/sec [31,467..32,075] ~ overlap (+1.2%)
base64url alphabet 72,641 ops/sec [72,236..73,025] → 75,174 ops/sec [74,962..77,824] 🟢 +3.5% 79,197 ops/sec [78,844..82,195] → 81,176 ops/sec [80,005..83,269] ~ overlap (+2.5%)
omitPadding 95,757 ops/sec [94,631..97,243] → 97,161 ops/sec [96,184..98,360] ~ overlap (+1.5%) 109,580 ops/sec [108,099..113,834] → 111,634 ops/sec [110,813..111,714] ~ overlap (+1.9%)
short (8 chars) 112,079 ops/sec [106,610..136,344] → 112,154 ops/sec [111,881..114,614] ~ overlap (+0.1%) 134,495 ops/sec [132,715..135,557] → 135,061 ops/sec [132,810..145,403] ~ overlap (+0.4%)
medium (600 chars) 64,669 ops/sec [61,808..79,663] → 61,896 ops/sec [61,482..71,504] ~ overlap (-4.3%) 69,632 ops/sec [68,386..72,670] → 69,648 ops/sec [69,223..69,876] ~ overlap (+0.0%)
large (5464 chars) 13,464 ops/sec [12,953..13,680] → 13,577 ops/sec [13,098..14,118] ~ overlap (+0.8%) 13,746 ops/sec [13,528..14,158] → 14,191 ops/sec [13,939..14,212] ~ overlap (+3.2%)
short (5 bytes) 234,072 ops/sec [231,324..236,309] → 144,123 ops/sec [141,758..154,286] 🔴 -38.4% 195,771 ops/sec [194,046..197,796] → 202,354 ops/sec [197,182..208,191] ~ overlap (+3.4%)
medium (450 bytes) 144,613 ops/sec [143,543..144,722] → 93,639 ops/sec [93,247..95,094] 🔴 -35.2% 111,100 ops/sec [77,287..136,301] → 109,576 ops/sec [109,256..109,899] ~ overlap (-1.4%)
large (4096 bytes) 37,057 ops/sec [36,858..37,387] → 23,513 ops/sec [22,825..23,561] 🔴 -36.5% 26,636 ops/sec [23,738..31,321] → 24,212 ops/sec [23,486..24,254] ~ overlap (-9.1%)
short (10 chars) 187,072 ops/sec [185,750..188,589] → 122,532 ops/sec [121,519..125,750] 🔴 -34.5% 147,821 ops/sec [146,726..162,100] → 148,900 ops/sec [147,056..149,517] ~ overlap (+0.7%)
medium (900 chars) 87,311 ops/sec [84,081..144,818] → 83,159 ops/sec [82,902..84,458] ~ overlap (-4.8%) 165,971 ops/sec [165,794..166,911] → 172,643 ops/sec [96,394..174,178] ~ overlap (+4.0%)
large (8192 chars) 46,233 ops/sec [45,958..46,247] → 27,977 ops/sec [23,315..30,342] 🔴 -39.5% 48,574 ops/sec [47,419..49,148] → 24,715 ops/sec [24,060..25,276] 🔴 -49.1%
setFromBase64 (450 bytes) 84,976 ops/sec [84,126..85,122] → 53,259 ops/sec [52,740..54,106] 🔴 -37.3% 95,860 ops/sec [95,243..97,298] → 60,663 ops/sec [60,245..61,195] 🔴 -36.7%
setFromHex (450 bytes) 20,250 ops/sec [20,089..34,723] → 20,006 ops/sec [19,811..21,196] ~ overlap (-1.2%) 35,776 ops/sec [35,284..36,113] → 21,586 ops/sec [21,102..24,158] 🔴 -39.7%
toBase64 → fromBase64 (450 bytes) 67,453 ops/sec [43,104..68,680] → 43,068 ops/sec [42,718..47,321] ~ overlap (-36.2%) 74,445 ops/sec [73,458..75,146] → 74,431 ops/sec [46,156..74,830] ~ overlap (-0.0%)
toHex → fromHex (450 bytes) 84,749 ops/sec [84,052..86,636] → 83,553 ops/sec [82,943..84,434] ~ overlap (-1.4%) 93,537 ops/sec [91,667..93,977] → 57,561 ops/sec [56,309..63,176] 🔴 -38.5%
weak-collections.js — Interp: 🟢 5, 🔴 2, 8 unch. · avg +16.0% · Bytecode: 🟢 7, 8 unch. · avg +28.9%
Benchmark Interpreted (main → PR) Δ Bytecode (main → PR) Δ
constructor from 50 entries 10,165 ops/sec [9,964..10,405] → 9,731 ops/sec [9,397..10,191] ~ overlap (-4.3%) 9,807 ops/sec [9,490..10,015] → 9,941 ops/sec [9,753..10,379] ~ overlap (+1.4%)
set 50 object keys 2,898 ops/sec [2,857..2,947] → 3,288 ops/sec [2,924..4,676] ~ overlap (+13.5%) 3,905 ops/sec [3,811..4,219] → 4,562 ops/sec [3,863..6,587] ~ overlap (+16.8%)
get lookups (50 entries) 43,510 ops/sec [43,354..44,295] → 43,957 ops/sec [43,896..44,078] ~ overlap (+1.0%) 79,365 ops/sec [77,417..79,756] → 82,471 ops/sec [81,619..83,297] 🟢 +3.9%
has checks (50 entries) 57,642 ops/sec [56,959..59,161] → 93,004 ops/sec [92,167..93,078] 🟢 +61.3% 98,564 ops/sec [95,601..100,970] → 102,347 ops/sec [102,004..104,446] 🟢 +3.8%
delete entries 2,727 ops/sec [2,724..2,736] → 4,381 ops/sec [4,364..4,393] 🟢 +60.6% 3,725 ops/sec [3,679..3,931] → 3,807 ops/sec [3,801..3,831] ~ overlap (+2.2%)
non-registered symbol keys 6,682 ops/sec [6,654..6,723] → 10,566 ops/sec [10,467..10,750] 🟢 +58.1% 8,971 ops/sec [8,912..9,074] → 14,782 ops/sec [14,726..14,876] 🟢 +64.8%
getOrInsert 2,818 ops/sec [2,806..2,852] → 4,427 ops/sec [4,372..4,445] 🟢 +57.1% 3,613 ops/sec [3,578..3,629] → 3,641 ops/sec [3,606..3,715] ~ overlap (+0.8%)
getOrInsertComputed 2,564 ops/sec [1,639..2,578] → 1,658 ops/sec [1,648..1,670] ~ overlap (-35.3%) 1,862 ops/sec [1,800..1,983] → 1,877 ops/sec [1,860..1,895] ~ overlap (+0.8%)
forced gc live-key retention 60 ops/sec [49..62] → 92 ops/sec [72..130] 🟢 +53.0% 97 ops/sec [92..107] → 127 ops/sec [76..146] ~ overlap (+30.8%)
constructor from 50 values 19,818 ops/sec [11,723..20,569] → 11,783 ops/sec [11,534..19,184] ~ overlap (-40.5%) 11,548 ops/sec [10,991..12,355] → 12,135 ops/sec [11,795..12,380] ~ overlap (+5.1%)
add 50 object values 5,072 ops/sec [5,047..5,127] → 4,873 ops/sec [4,825..4,880] 🔴 -3.9% 4,102 ops/sec [4,025..6,596] → 4,604 ops/sec [4,114..6,925] ~ overlap (+12.2%)
has checks (50 values) 56,678 ops/sec [56,096..56,927] → 58,179 ops/sec [56,769..89,624] ~ overlap (+2.6%) 103,498 ops/sec [100,495..104,497] → 175,397 ops/sec [174,832..175,634] 🟢 +69.5%
delete values 12,701 ops/sec [9,090..15,927] → 14,921 ops/sec [14,824..15,015] ~ overlap (+17.5%) 11,121 ops/sec [10,833..11,527] → 17,610 ops/sec [17,584..17,774] 🟢 +58.3%
non-registered symbol values 11,503 ops/sec [11,302..11,659] → 10,983 ops/sec [10,861..11,118] 🔴 -4.5% 9,530 ops/sec [9,497..9,561] → 15,661 ops/sec [15,598..15,735] 🟢 +64.3%
forced gc pruning smoke 181 ops/sec [179..182] → 186 ops/sec [179..201] ~ overlap (+3.1%) 121 ops/sec [86..233] → 240 ops/sec [239..242] 🟢 +98.1%

Deterministic profile diff

Deterministic profile diff: no significant changes.

Measured on ubuntu-latest x64. Each PR run also builds the main base and benchmarks it back-to-back on the same runner after a warm-up discard, so the ranges compare two runs measured under the same conditions; overlapping min/max ranges are treated as unchanged noise. Percentage deltas are secondary context. See docs/adr/0076.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 10,948 passed; bytecode: 10,948 passed)
Metric Interpreted Bytecode
Total 10948 10948
Passed 10948 ✅ 10948 ✅
Workers 4 4
Test Duration 19.24s 18.64s
Lex (cumulative) 486.8ms 562.1ms
Parse (cumulative) 353.6ms 396.0ms
Compile (cumulative) 829.6ms
Execute (cumulative) 72.5ms 42.34s
Engine Total (cumulative) 913.0ms 44.13s
Lex (avg/worker) 121.7ms 140.5ms
Parse (avg/worker) 88.4ms 99.0ms
Compile (avg/worker) 207.4ms
Execute (avg/worker) 18.1ms 10.59s
Engine Total (avg/worker) 228.2ms 11.03s

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Test runner worker shutdown frees thread-local heaps in bulk; that shutdown reclamation is not counted as GC collections or collected objects.

Metric Interpreted Bytecode
GC Live 282.87 MiB 280.29 MiB
GC Peak Live 330.29 MiB 316.32 MiB
GC Allocated During Run 528.33 MiB 472.64 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 195 195
GC Collected Objects 2,591,362 2,162,585
Heap Start Allocated 181.0 KiB 181.0 KiB
Heap End Allocated 3.65 MiB 3.65 MiB
Heap Delta Allocated 3.48 MiB 3.48 MiB
Heap Delta Free 1.68 MiB 1.68 MiB
Benchmarks (interpreted: 430; bytecode: 430)
Metric Interpreted Bytecode
Total 430 430
Workers 4 4
Duration 2.80min 2.69min

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Benchmark runner performs explicit between-file collections, so collection and collected-object counts can be much higher than the test runner.

Metric Interpreted Bytecode
GC Live 6.09 MiB 6.09 MiB
GC Peak Live 91.39 MiB 96.18 MiB
GC Allocated During Run 14.75 GiB 10.05 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 3,647 3,488
GC Collected Objects 229,775,143 223,860,965
Heap Start Allocated 3.36 MiB 3.36 MiB
Heap End Allocated 3.36 MiB 3.36 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,643 22,609 +1 1,034 95.6% ±0pp
harness 116 116 ±0 0 100.0% ±0pp
intl402 3,341 3,334 ±0 7 99.8% ±0pp
language 23,711 23,711 ±0 0 100.0% ±0pp
staging 1,482 1,109 ±0 373 74.8% ±0pp
total 52,293 50,879 +1 1,414 97.3% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/TypedArray 99.9% ±0pp 1,445 / 1,446
intl402/Temporal 99.9% ±0pp 2,026 / 2,029
built-ins/Object 99.7% ±0pp 3,401 / 3,411
Per-test deltas (+1 / -0)

Newly passing (1):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js

Steady-state failures are non-blocking; regressions vs the cached main baseline (lower total pass count, or any PASS → non-PASS transition) fail the conformance gate. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached main baseline.

@frostney frostney marked this pull request as ready for review June 27, 2026 10:46
@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation internal Refactoring, CI, tooling, cleanup new feature New feature or request labels Jun 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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.

Inline comments:
In @.github/workflows/pr.yml:
- Line 196: The benchmark workflow is overly gated by the build-main job,
causing benchmark and benchmark-comment to be skipped when the base build fails.
Update the pr.yml workflow so benchmark can still run and post PR-only feedback
even if build-main fails, while preserving the build-main ordering dependency
for available artifacts. Use the benchmark, benchmark-comment, and build-main
job definitions to keep the downstream graceful-fallback path in
buildBenchmarkComparison reachable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 33c9903d-14e0-4950-850a-a6a8bf9245a4

📥 Commits

Reviewing files that changed from the base of the PR and between 10ba727 and f6647ab.

📒 Files selected for processing (9)
  • .github/workflows/ci.yml
  • .github/workflows/pr.yml
  • docs/adr/0076-same-runner-benchmark-comparison.md
  • docs/adr/README.md
  • docs/benchmarks.md
  • docs/build-system.md
  • scripts/benchmark-compare.js
  • scripts/profile-diff.js
  • scripts/test-benchmark-compare.ts

Comment thread .github/workflows/pr.yml
frostney and others added 2 commits June 27, 2026 13:23
The benchmark job hard-depended on build-main (needs: [build, build-main]),
so a build-main failure (base predating the benchmarkrunner target, or a
transient FPC install hiccup) skipped benchmark and, transitively,
benchmark-comment — the PR got no benchmark feedback at all, even though
build-pr succeeded. That made the downstream graceful-degradation path
(optional main downloads + null-main handling in buildBenchmarkComparison)
unreachable.

Keep the build-main ordering dependency but run benchmark whenever `build`
itself succeeds (if: !cancelled() && needs.build.result == 'success'), and
make the main-build inputs optional: continue-on-error on the build-main
download, a tolerant chmod, and if-no-files-found: ignore on the main result
and profile uploads. When build-main fails the comparison now posts PR-only
numbers instead of going silent.

Addresses CodeRabbit review feedback on #886.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai coderabbitai Bot removed the internal Refactoring, CI, tooling, cleanup label Jun 27, 2026
frostney and others added 2 commits June 27, 2026 15:12
The benchmark (interpreted) leg timed out after 51 minutes on #886: the PR
measured pass hung while the main pass (same workloads, same runner) had
just completed in ~3 min. Locally the full interpreted suite runs in ~2 min,
so this is a non-deterministic per-benchmark calibration runaway on a loaded
GitHub runner, not a benchmark bug.

The trigger was self-inflicted: the two-binary warm-up ran with the default
200 ms calibration (no override), making it ~a full extra pass per binary —
roughly 2.5x the interpreted work and heavy runner load right before the
final measured pass, which is when calibration is most likely to misfire.
There was also no timeout, so a runaway burned 51 min and red-marked the PR.

- Replace the two-binary warm-up with a single cheap one (PR binary,
  ROUNDS=1 + CALIBRATION_MS=10): still ramps the CPU and warms the shared
  benchmark-file cache, but light and low-load. The runner's per-benchmark
  warm-up (5 iters) covers binary-specific warmth, so one binary suffices.
- Wrap each pass in `timeout -k 30 480` (8 min cap; normal ~3 min). A killed
  main pass writes no JSON and degrades to PR-only; a killed PR pass fails
  fast instead of spinning.
- Add `timeout-minutes: 30` to the benchmark job as a hard backstop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@frostney frostney merged commit 2398f2f into main Jun 27, 2026
15 checks passed
@frostney frostney deleted the claude/beautiful-feistel-ce5255 branch June 27, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation new feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Benchmark PR comparison is unreliable — baseline is a cached run from a different runner, so deltas reflect runner variance, not the diff

1 participant