Skip to content

fix(gc): make BytesAllocated reads tear-free on 32-bit targets - #1214

Merged
frostney merged 1 commit into
mainfrom
claude/beautiful-lalande-1e8e70
Aug 25, 2026
Merged

fix(gc): make BytesAllocated reads tear-free on 32-bit targets#1214
frostney merged 1 commit into
mainfrom
claude/beautiful-lalande-1e8e70

Conversation

@frostney

Copy link
Copy Markdown
Owner

Summary

  • On i386-win32, memory-limit and memory-pressure decisions could act on a garbage BytesAllocated total: owner-thread readers take no lock, so a bare Int64 load can tear across a cross-thread ReleaseExternalBytes (an error object charged on this collector but destroyed on another thread) writing the counter under the per-collector accounting lock introduced in perf(gc): keep worker allocations running during another worker's collection #1213.
  • BytesAllocated now reads through an accessor: a bare inlined field load on 64-bit (aligned Int64 loads cannot tear there — the per-allocation path keeps zero added cost) and a lock-guarded load on 32-bit. No 64-bit interlocked read is usable: FPC 3.2.2 declares those only under CPU64, and CI builds i386-win32.
  • The decisive unlocked read in NeedsMemoryPressureCollection routes through the accessor behind the cheap early-exit guards (the periodic VM/interpreter pressure polls stay lock-free when no limit is set), the external-byte charge path decides from the total it just committed instead of re-reading under the lock, and CanAllocateNativeBytes decides from one snapshot instead of two independent reads.
  • Non-goals: PeakBytesAllocated, TotalBytesAllocated, MaxBytes, and the since-GC external counter stay direct field reads — they are written only by the owning thread, so no reader can observe a half-applied write. Compound predicates that consult the counter and then act remain approximate, as before.
  • The exposure predates perf(gc): keep worker allocations running during another worker's collection #1213 (these readers never took the old global collect lock either): correctness hardening, not a regression fix.

The reader rule is documented at FAccountingLock and in docs/garbage-collector.md.

Reviewed by a separate high-effort code-review pass: no correctness findings; its two 32-bit lock-traffic findings are fixed here (pressure-poll guards, single-snapshot CanAllocateNativeBytes).

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests — 12,780/12,780 in both --mode=ast and --mode=bytecode
  • Updated documentation — reader rule added to docs/garbage-collector.md threading model
  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed) — Goccia.GarbageCollector.Test 12/12 (incl. the cross-thread release churn test), Goccia.MemoryLimit.Test 33/33; the 32-bit locked branch was additionally compiled and run on the 64-bit host by temporarily inverting the width gate
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

Full CI (incl. the i386-win32 job, which pr.yml does not run) dispatched on this branch: https://github.com/frostney/GocciaScript/actions/runs/32823875897

Owner-thread readers of the live-byte total took no lock while a
cross-thread ReleaseExternalBytes (an error object charged on this
collector but destroyed on another thread) writes it under the
per-collector accounting lock. On i386-win32 a bare Int64 load can tear
across that locked 64-bit write, feeding a garbage total into
memory-limit and memory-pressure decisions.

BytesAllocated now reads through an accessor that is a bare inlined
field load on 64-bit (aligned Int64 loads cannot tear there; the
per-allocation path keeps zero added cost) and a lock-guarded load on
32-bit. The decisive unlocked read in NeedsMemoryPressureCollection
routes through it behind the cheap early-exit guards, the charge path
passes the total it just committed instead of re-reading under the
lock, and CanAllocateNativeBytes decides from one snapshot instead of
two independent reads. Peak and lifetime totals stay direct reads: they
are written only by the owning thread.

The exposure predates the per-collector accounting lock (these readers
never took the old global collect lock either), so this is correctness
hardening, not a regression fix.
@vercel

vercel Bot commented Aug 25, 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 Aug 25, 2026 7:54am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 25, 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: 7085aa3f-18a5-4a58-93f9-38638a8288ca

📥 Commits

Reviewing files that changed from the base of the PR and between f426b1b and b44b8bb.

📒 Files selected for processing (3)
  • docs/garbage-collector.md
  • source/units/Goccia.GarbageCollector.pas
  • source/units/Goccia.MemoryLimit.pas

Included review availability: 3 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour.


📝 Walkthrough

Walkthrough

The garbage collector now uses platform-aware reads for BytesAllocated. Pressure checks reuse committed byte snapshots. Native allocation checks use one counter snapshot for overflow and budget validation.

Changes

Allocation accounting synchronization

Layer / File(s) Summary
Platform-aware counter accessor
source/units/Goccia.GarbageCollector.pas, docs/garbage-collector.md
BytesAllocated uses direct reads on 64-bit targets and locked reads on 32-bit targets. The synchronization rules are documented.
Pressure-check snapshot reuse
source/units/Goccia.GarbageCollector.pas
Pressure checks accept a pre-read byte total and use it for threshold evaluation, including external-byte charging.
Native allocation snapshot
source/units/Goccia.MemoryLimit.pas
CanAllocateNativeBytes reads BytesAllocated once and reuses the value for overflow and budget checks.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to b44b8

This localized change makes cross-thread memory accounting reads safe on 32-bit targets while preserving the existing 64-bit fast path, with targeted tests and documentation updates. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: preventing torn BytesAllocated reads on 32-bit targets.
Description check ✅ Passed The description follows the required Summary and Testing sections. It explains the implementation, constraints, non-goals, issue context, documentation update, and test results. The optional benchmark…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
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.
Full details: Description check

Explanation

The description follows the required Summary and Testing sections. It explains the implementation, constraints, non-goals, issue context, documentation update, and test results. The optional benchmark item is unchecked, which does not prevent approval.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (3 skipped: 3 unsupported.)


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

@github-actions

Copy link
Copy Markdown
Contributor

Web Tooling Benchmark

Workload Status Goccia
acorn pass 0.02 runs/s
babel pass 0.01 runs/s
babel-minify pass 0.09 runs/s
babylon pass 0.04 runs/s
buble pass 0.08 runs/s
chai pass 0.08 runs/s
coffeescript pass 0.01 runs/s
espree pass 0.02 runs/s
esprima pass 0.05 runs/s
jshint pass 0.01 runs/s
lebab pass 0.07 runs/s
postcss pass 0.02 runs/s
prepack pass 0.10 runs/s
prettier pass 0.06 runs/s
source-map pass 0.04 runs/s
terser pass 0.23 runs/s
typescript pass 0.11 runs/s
uglify-js pass 0.05 runs/s

18 pinned Web Tooling workloads; 18 workloads produced at least one Goccia sample. Raw results from 1 sample per workload; full stdout/stderr for failures and min/max/CV stay in the web-tooling-report artifact. This lane is Goccia-only by design.

@github-actions

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 12,780 passed; bytecode: 12,780 passed)
Metric Interpreted Bytecode
Total 12780 12780
Passed 12780 ✅ 12780 ✅
Workers 4 4
Test Duration 19.25s 20.94s
Lex (cumulative) 1.88s 2.20s
Parse (cumulative) 991.8ms 1.14s
Compile (cumulative) 1.51s
Execute (cumulative) 741.8ms 20.11s
Engine Total (cumulative) 3.62s 24.95s
Lex (avg/worker) 470.9ms 549.0ms
Parse (avg/worker) 248.0ms 285.0ms
Compile (avg/worker) 377.7ms
Execute (avg/worker) 185.4ms 5.03s
Engine Total (avg/worker) 904.3ms 6.24s

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 59.76 MiB 54.10 MiB
GC Peak Live 202.52 MiB 166.22 MiB
GC Allocated During Run 700.48 MiB 611.57 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1,004 1,010
GC Collected Objects 5,463,113 4,770,223
Heap Start Allocated 371.1 KiB 371.1 KiB
Heap End Allocated 2.99 MiB 2.99 MiB
Heap Delta Allocated 2.63 MiB 2.63 MiB
Heap Delta Free 2.21 MiB 2.21 MiB
Benchmarks (interpreted: 440; bytecode: 440)
Metric Interpreted Bytecode
Total 440 440
Workers 4 4
Duration 3.18min 2.92min

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 85.0 KiB 85.0 KiB
GC Peak Live 429.14 MiB 327.48 MiB
GC Allocated During Run 19.32 GiB 13.32 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 5,728 5,482
GC Collected Objects 216,295,435 171,578,331
Heap Start Allocated 1.37 MiB 1.37 MiB
Heap End Allocated 1.37 MiB 1.37 MiB
Heap Delta Allocated 3.2 KiB 3.2 KiB
Boot
Metric Interpreted Bytecode
Boot (median) 6.1ms 6.1ms
Boot (min) 5.9ms 5.9ms

Empty-script (0;) end-to-end process wall-clock for GocciaScriptLoader, min and median over 60 runs after 10 warmups. Includes a fixed process / dynamic-loader floor that does not shrink, so it understates the engine-boot speedup; treat as practical boot time, not pure engine work.

Measured on ubuntu-latest x64.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

440 benchmarks · PR vs same-runner main build

Interpreted: 🟢 27 improved · 🔴 35 regressed · 378 unchanged · avg +0.3%
Bytecode: 🟢 51 improved · 🔴 36 regressed · 353 unchanged · avg +1.1%

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

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

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

Copy link
Copy Markdown
Contributor

test262 Conformance

10 timeout(s) — counted separately from ordinary conformance failures; inspect the full artifact for affected tests.

Category Run Passed Δ Pass Failed Timeouts Δ Timeout Wrap-Infra Pass-rate Δ Rate
built-ins 23,812 23,719 +2 93 0 -2 0 99.6% ±0pp
harness 116 116 ±0 0 0 ±0 0 100.0% ±0pp
intl402 3,357 3,344 ±0 12 1 ±0 0 99.6% ±0pp
language 23,724 23,717 ±0 7 0 ±0 0 100.0% ±0pp
staging 1,483 1,389 +3 85 9 -3 0 93.7% +0.2pp
total 52,492 52,285 +5 197 10 -5 0 99.6% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
language/expressions 100.0% ±0pp 11,101 / 11,102
intl402/Temporal 100.0% ±0pp 2,028 / 2,029
language/statements 99.9% ±0pp 9,341 / 9,347
Per-test deltas (+0 / -0 / timeout +0 / -5)

Resolved timeouts (5):

  • built-ins/decodeURI/S15.1.3.1_A2.5_T1.js
  • built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
  • staging/sm/extensions/recursion.js
  • staging/sm/regress/regress-610026.js
  • staging/sm/TypedArray/element-setting-converts-using-ToNumber.js

Steady-state failures and timeouts are non-blocking; PASS → non-timeout failure transitions 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.

@github-actions

Copy link
Copy Markdown
Contributor

JetStream 3 Performance Barometer

Workload Status Goccia main Goccia PR QuickJS Node.js vs QuickJS vs Node.js
hash-map pass 0.55 0.56 13.71 333.73 24.57× 598.26×
ai-astar pass 1.68 1.68 41.24 339.71 24.57× 202.37×
gaussian-blur pass 0.35 0.36 7.93 288.62 22.21× 808.08×
raytrace-public-class-fields pass 0.38 0.39 10.98 194.00 28.20× 498.22×
sync-fs pass 1.20 1.18 33.44 279.69 28.41× 237.64×
lazy-collections pass 2.15 2.20 71.83 152.49 32.59× 69.19×

Geomean reference ratio: QuickJS 26.55×; Node.js 304.77×.

1.00× means aligned; values above 1.00× mean Goccia was proportionally slower after normalizing JetStream’s higher-is-better score. This is a directional barometer across runtimes with different goals, not a product ranking. Raw samples and failure details remain in the jetstream-report artifact.

@github-actions

Copy link
Copy Markdown
Contributor

AWFY Results

Target Status Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v26.7.0 Δ PR vs main
Bounce pass 23.68ms 22.92ms 1.04ms 1.04ms 🟢 +3.20%
CD pass 225.71ms 218.77ms 10.60ms 9.04ms 🟢 +3.07%
DeltaBlue pass 5.04ms 4.99ms 306.48µs 1.77ms 🟢 +0.98%
Havlak pass 86.90s 85.44s 4248.68ms 183.59ms 🟢 +1.68%
Json pass 391.72ms 384.65ms 14.43ms 4.16ms 🟢 +1.80%
List pass 15.59ms 15.58ms 1.03ms 0.72ms ~ overlap (+0.09%)
Mandelbrot pass 34.08µs 29.87µs 4.99µs 93.15µs 🟢 +12.38%
NBody pass 475.51µs 429.59µs 27.97µs 387.98µs 🟢 +9.66%
Permute pass 44.56ms 43.98ms 1.89ms 0.72ms 🟢 +1.30%
Queens pass 23.66ms 23.13ms 1.27ms 1.06ms 🟢 +2.23%
Richards pass 959.08ms 933.74ms 52.03ms 6.55ms 🟢 +2.64%
Sieve pass 13.71ms 13.72ms 0.56ms 0.53ms ~ overlap (-0.11%)
Storage pass 42.00ms 41.98ms 2.94ms 0.97ms ~ overlap (+0.06%)
Towers pass 64.89ms 63.50ms 3.14ms 1.14ms ~ overlap (+2.14%)

Geomean Ratios

Ratio (row / column) Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v26.7.0
Goccia main 1.000 1.031 18.256 22.585
Goccia PR 0.970 1.000 17.708 21.907
QuickJS 2026-06-04 0.055 0.056 1.000 1.237
NodeJS v26.7.0 0.044 0.046 0.808 1.000

14 pinned AWFY benchmarks. Medians from 5 interleaved samples per engine; raw JSON includes min/max/CV and is attached as the awfy-report artifact. Δ compares PR Goccia median against the same-runner main Goccia median; overlapping min/max ranges are treated as unchanged noise. Rows below 0.5ms are timer-floor sensitive.

@frostney
frostney marked this pull request as ready for review August 25, 2026 08:34
@frostney
frostney merged commit f4d403f into main Aug 25, 2026
126 checks passed
@frostney
frostney deleted the claude/beautiful-lalande-1e8e70 branch August 25, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant