Skip to content

feat(ffi): expand native call capabilities - #1034

Merged
frostney merged 3 commits into
mainfrom
codex/ffi-capabilities-1029-1033
Jul 24, 2026
Merged

feat(ffi): expand native call capabilities#1034
frostney merged 3 commits into
mainfrom
codex/ffi-capabilities-1029-1033

Conversation

@frostney

@frostney frostney commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Extend the shared compiled-signature ABI planner to support mixed top-level f32 arguments and a defensible 64-argument bound for calls and reverse callbacks, including a nine-argument DrawBillboardPro-shaped fixture.
  • Add explicit variadic native calls through { variadic: true } plus one FFI.varargs(types, values) tail, with pre-entry validation, C default promotions, Windows x64 register mirroring, and Darwin ARM64 variadic stack placement. Variadic callbacks remain unsupported.
  • Add FFI.nullable("utf8string") for strict borrowed UTF-8-or-NULL inputs using call-scoped temporary storage, while preserving plain utf8string coercion behavior.
  • Preserve exact aggregate field names, including buffer and byteOffset, and expose collision-free backing information through FFI.metadata(value).
  • Add direct native fixture regressions, public documentation, ADR 0102, and host-neutral planner regressions for all five ABI models. This does not change performance work, imports, typed arrays, wasm, or the Raylib project.

Closes #1029

Closes #1030

Closes #1031

Closes #1032

Closes #1033

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
  • Updated documentation
  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed)
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

Validation run locally on Darwin ARM64 with FPC 3.2.2:

  • ./build/GocciaTestRunner tests/built-ins/FFI — 106/106 tests, 382 assertions
  • ./build/GocciaTestRunner tests/built-ins/FFI --mode=bytecode — 106/106 tests, 382 assertions
  • ./build/GocciaTestRunner tests --silent --no-progress — 11,565/11,565 tests, 25,879 assertions
  • ./build/GocciaTestRunner tests --mode=bytecode --silent --no-progress — 11,565/11,565 tests, 25,879 assertions
  • ./build/Goccia.FFI.ABI.Test — 4/4 tests covering all five planner models
  • ./build.pas tests plus all 61 build/Goccia.*.Test binaries — passed
  • ./format.pas --check — 430 files formatted
  • bun run scripts/check-test-structure.ts — 1,440 JavaScript test files checked
  • Documentation symbol, duplication, length, and link gates — passed (only the repository's existing fuzzy-duplication warnings)
  • cc -std=c11 -Wall -Wextra -Werror -fsyntax-only fixtures/ffi/fixture.c — passed
  • Pre-commit hooks, including Markdown lint and documentation gates — passed

The local native FFI executions cover Darwin ARM64. The host-neutral Pascal regression constructs and verifies SysV x64, Win64, AAPCS64, Darwin ARM64, and i386 Windows plans; compiler-generated Darwin ARM64 and Win64 probe call sites were also compared during self-review. The PR workflow executes Ubuntu x64, while the repository's main CI matrix remains the build authority for x86_64 Darwin, AArch64 Linux, Win64, and i386 Windows.

Support mixed f32 signatures, high-arity and variadic calls,
collision-safe aggregate metadata, and nullable UTF-8 arguments.
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview Jul 24, 2026 12:49pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds explicit nullable UTF-8 and variadic FFI descriptors, raises supported arity to 64, expands ABI planning for mixed and variadic arguments, exposes aggregate metadata access, and adds native fixtures, tests, ADR documentation, and validation messages.

Changes

FFI descriptor contracts

Layer / File(s) Summary
Descriptor contracts and built-ins
source/units/Goccia.FFI.Types.pas, source/units/Goccia.Values.FFIType.pas, source/units/Goccia.Builtins.GlobalFFI.pas, source/units/Goccia.Error.Messages.pas
Adds FFI.nullable, FFI.varargs, and FFI.metadata, position-aware type validation, nullable UTF-8 descriptors, variadic values, callback restrictions, metadata construction, and a 64-argument limit.

ABI and invocation

Layer / File(s) Summary
Variadic ABI planning
source/units/Goccia.FFI.ABI.pas, source/units/Goccia.FFI.ABI.Test.pas
Adds variadic signature boundaries and target-specific Win64 and Darwin ARM64 placement rules, with mixed-scalar and high-arity ABI tests.
Bound-call parsing and invocation
source/units/Goccia.Values.FFILibrary.pas
Parses variadic, marshals nullable strings, applies C default promotions, builds call-specific signatures, and invokes explicit typed variadic tails.

Fixtures and documentation

Layer / File(s) Summary
Native fixtures and behavioral validation
fixtures/ffi/fixture.c, tests/built-ins/FFI/*
Adds native variadic, callback, mixed-f32, aggregate, metadata, and high-arity fixtures with corresponding Jest coverage.
FFI contract documentation
docs/adr/*, docs/built-ins-ffi.md
Documents the descriptor contract, ABI rules, nullable strings, metadata access, variadic calls, limits, and ADR index entry.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant JavaScript
  participant FFILibrary
  participant BoundFunction
  participant ABIPlanner
  participant NativeFunction
  JavaScript->>FFILibrary: bind variadic signature
  FFILibrary->>BoundFunction: create bound function
  JavaScript->>BoundFunction: invoke with FFI.varargs
  BoundFunction->>ABIPlanner: promote and compile call layout
  BoundFunction->>NativeFunction: marshal and invoke arguments
Loading

Possibly related PRs

Suggested labels: new feature, documentation

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements all five linked requirements: mixed f32, >8 args, variadic calls, metadata-collision handling, and nullable UTF-8 support.
Out of Scope Changes check ✅ Passed The added docs, ADR, fixtures, and tests all support the FFI feature expansion and do not appear unrelated.
Title check ✅ Passed The title is concise and accurately summarizes the main change: expanded native FFI call capabilities.
Description check ✅ Passed The description matches the template with Summary, non-goals, issue links, and Testing sections filled out.

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

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Web Tooling Benchmark

Workload Status Goccia
acorn pass 0.03 runs/s
babel pass 0.01 runs/s
babel-minify pass 0.09 runs/s
babylon pass 0.06 runs/s
buble pass 0.10 runs/s
chai pass 0.09 runs/s
coffeescript pass 0.01 runs/s
espree pass 0.02 runs/s
esprima pass 0.04 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 338 runs/s
typescript pass 0.11 runs/s
uglify-js pass 123 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

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 11,565 passed; bytecode: 11,565 passed)
Metric Interpreted Bytecode
Total 11565 11565
Passed 11565 ✅ 11565 ✅
Workers 4 4
Test Duration 17.64s 12.33s
Lex (cumulative) 1.76s 1.26s
Parse (cumulative) 931.1ms 684.4ms
Compile (cumulative) 799.4ms
Execute (cumulative) 387.7ms 11.39s
Engine Total (cumulative) 3.07s 14.14s
Lex (avg/worker) 438.9ms 315.5ms
Parse (avg/worker) 232.8ms 171.1ms
Compile (avg/worker) 199.8ms
Execute (avg/worker) 96.9ms 2.85s
Engine Total (avg/worker) 768.6ms 3.53s

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 65.78 MiB 64.99 MiB
GC Peak Live 216.27 MiB 185.96 MiB
GC Allocated During Run 529.83 MiB 459.10 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 226 226
GC Collected Objects 4,417,428 3,852,895
Heap Start Allocated 329.6 KiB 329.6 KiB
Heap End Allocated 2.90 MiB 2.90 MiB
Heap Delta Allocated 2.58 MiB 2.58 MiB
Heap Delta Free 2.29 MiB 2.29 MiB
Benchmarks (interpreted: 439; bytecode: 439)
Metric Interpreted Bytecode
Total 439 439
Workers 4 4
Duration 3.11min 3.00min

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 808 B 808 B
GC Peak Live 155.17 MiB 71.12 MiB
GC Allocated During Run 16.65 GiB 10.27 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 5,364 6,962
GC Collected Objects 239,311,868 224,781,765
Heap Start Allocated 1.36 MiB 1.36 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) 7.2ms 7.3ms
Boot (min) 7.1ms 7.2ms

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

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

439 benchmarks · PR vs same-runner main build

Interpreted: 🟢 59 improved · 🔴 43 regressed · 337 unchanged · avg +0.4%
Bytecode: 🟢 47 improved · 🔴 40 regressed · 352 unchanged · avg +2.1%

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

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

@github-actions

github-actions Bot commented Jul 24, 2026

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.67 0.66 18.64 391.30 28.17× 591.18×
ai-astar pass 1.76 1.76 48.56 348.41 27.54× 197.58×
gaussian-blur pass 0.34 0.35 7.43 281.74 21.03× 797.83×
raytrace-public-class-fields pass 0.44 0.43 11.51 201.00 26.54× 463.54×
sync-fs pass 0.88 0.87 26.81 225.56 30.91× 260.05×
lazy-collections pass 2.01 2.00 67.00 145.38 33.44× 72.57×

Geomean reference ratio: QuickJS 27.66×; Node.js 305.64×.

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

test262 Conformance

11 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,668 23,668 +2 0 0 -2 0 100.0% ±0pp
harness 116 116 ±0 0 0 ±0 0 100.0% ±0pp
intl402 3,349 3,340 ±0 8 1 ±0 0 99.7% ±0pp
language 23,713 23,712 +2 1 0 -2 0 100.0% ±0pp
staging 1,482 1,386 +2 86 10 -2 0 93.5% +0.1pp
total 52,328 52,222 +6 95 11 -6 0 99.8% ±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
intl402/NumberFormat 99.6% ±0pp 248 / 249
Per-test deltas (+0 / -0 / timeout +0 / -6)

Resolved timeouts (6):

  • built-ins/decodeURI/S15.1.3.1_A2.5_T1.js
  • built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
  • language/identifiers/start-unicode-10.0.0-class-escaped.js
  • language/identifiers/start-unicode-10.0.0-class.js
  • staging/sm/extensions/recursion.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

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

AWFY Results

Target Status Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v26.5.0 Δ PR vs main
Bounce pass 24.48ms 24.69ms 1.05ms 1.06ms 🔴 -0.86%
CD pass 222.78ms 222.26ms 10.68ms 9.80ms ~ overlap (+0.24%)
DeltaBlue pass 5.15ms 5.14ms 302.70µs 1.79ms ~ overlap (+0.24%)
Havlak pass 86.39s 86.41s 4262.75ms 179.40ms ~ overlap (-0.02%)
Json pass 373.68ms 374.26ms 14.51ms 4.43ms ~ overlap (-0.16%)
List pass 17.25ms 17.13ms 1.04ms 0.73ms ~ overlap (+0.73%)
Mandelbrot pass 31.88µs 31.68µs 5.02µs 89.11µs ~ overlap (+0.63%)
NBody pass 434.79µs 410.26µs 28.16µs 384.31µs ~ overlap (+5.64%)
Permute pass 45.78ms 46.13ms 1.92ms 0.71ms ~ overlap (-0.77%)
Queens pass 24.31ms 24.49ms 1.26ms 1.08ms ~ overlap (-0.74%)
Richards pass 1013.20ms 1019.88ms 51.74ms 7.13ms ~ overlap (-0.66%)
Sieve pass 13.65ms 13.39ms 0.56ms 0.76ms ~ overlap (+1.90%)
Storage pass 36.57ms 37.00ms 2.94ms 1.00ms ~ overlap (-1.18%)
Towers pass 66.30ms 66.78ms 3.15ms 1.12ms ~ overlap (-0.73%)

Geomean Ratios

Ratio (row / column) Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v26.5.0
Goccia main 1.000 1.003 18.116 21.572
Goccia PR 0.997 1.000 18.058 21.503
QuickJS 2026-06-04 0.055 0.055 1.000 1.191
NodeJS v26.5.0 0.046 0.047 0.840 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 July 24, 2026 12:05
@cursor

cursor Bot commented Jul 24, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation new feature New feature or request labels Jul 24, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/built-ins-ffi.md`:
- Around line 81-95: The nullable UTF-8 documentation must state that non-null
arguments use temporary NUL-terminated buffers valid only for the duration of
the native call, and that native code must not retain the pointer afterward.
Update the nullable UTF-8 section in docs/built-ins-ffi.md (lines 81-95) and the
corresponding ownership/lifetime contract in
docs/adr/0102-explicit-bounded-ffi-call-descriptors.md (lines 24-29).

In `@tests/built-ins/FFI/prototype/variadic.js`:
- Around line 95-110: Extend the test named “bounds the combined fixed and
variadic argument count” to verify the accepted 64-argument boundary: invoke sum
with one fixed argument and 63 variadic i32 values, and assert it succeeds with
the expected result. Keep the existing 65-total-argument RangeError assertion to
preserve rejection coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 74194f9e-cf9b-411c-b89c-f72d7915ff20

📥 Commits

Reviewing files that changed from the base of the PR and between 34cc32f and 0e9f380.

📒 Files selected for processing (17)
  • docs/adr/0102-explicit-bounded-ffi-call-descriptors.md
  • docs/adr/README.md
  • docs/built-ins-ffi.md
  • fixtures/ffi/fixture.c
  • source/units/Goccia.Builtins.GlobalFFI.pas
  • source/units/Goccia.Error.Messages.pas
  • source/units/Goccia.FFI.ABI.Test.pas
  • source/units/Goccia.FFI.ABI.pas
  • source/units/Goccia.FFI.Types.pas
  • source/units/Goccia.Values.FFILibrary.pas
  • source/units/Goccia.Values.FFIType.pas
  • tests/built-ins/FFI/ffi-v2-callback.js
  • tests/built-ins/FFI/ffi-v2-types.js
  • tests/built-ins/FFI/prototype/arity.js
  • tests/built-ins/FFI/prototype/bind.js
  • tests/built-ins/FFI/prototype/mixed.js
  • tests/built-ins/FFI/prototype/variadic.js

Comment thread docs/built-ins-ffi.md Outdated
Comment thread tests/built-ins/FFI/prototype/variadic.js
@frostney
frostney merged commit 29c952c into main Jul 24, 2026
126 checks passed
@frostney
frostney deleted the codex/ffi-capabilities-1029-1033 branch July 24, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

1 participant