Skip to content

Fix IteratorClose for abrupt for-of completion#488

Merged
frostney merged 3 commits intomainfrom
t3code/verify-fix-482
May 1, 2026
Merged

Fix IteratorClose for abrupt for-of completion#488
frostney merged 3 commits intomainfrom
t3code/verify-fix-482

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented May 1, 2026

Summary

  • call iterator return() for abrupt for...of completion in the interpreter
  • add bytecode iterator-close cleanup handling for throw, break, and return paths
  • add regression coverage for throw, break, return, and continue behavior

Fixes #482

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

📝 Walkthrough

Walkthrough

Adds iterator finalization to for-of loops: both interpreter and bytecode now invoke iterator return() on abrupt completion (throw, break, return). A new bytecode opcode OP_ITER_CLOSE and compiler pending-cleanup support were added; the VM executes iterator-close while preserving the original abrupt completion.

Changes

Cohort / File(s) Summary
Bytecode definitions
source/units/Goccia.Bytecode.pas, source/units/Goccia.Bytecode.OpCodeNames.pas
Bumped format version (20 → 21), added TGocciaOpCode.OP_ITER_CLOSE = 65, and mapped it to 'OP_ITER_CLOSE'.
Compiler: for-of & cleanup
source/units/Goccia.Compiler.Statements.pas
Added EmitPendingEntryCleanup, extended TPendingFinallyEntry with iterator-close metadata, refactored pending-cleanup usage, and register/emit iterator-close pending entry and handler that emits OP_ITER_CLOSE and rethrows.
Interpreter: for-of evaluation
source/units/Goccia.Evaluator.pas
EvaluateForOf tracks whether to close the iterator on head-phase exceptions, closes iterator preserving original error on head/body-phase exceptions, and closes on early break/return exits.
VM: iterator-close opcode
source/units/Goccia.VM.pas
Implemented OP_ITER_CLOSE: when operand is an object, call CloseRawIteratorPreservingError on its iterator; preserves original abrupt completion semantics.
Tests
tests/language/for-of/for-of-iterators.js
Added tests asserting iterator return() is invoked for loop-body exception, break, and return exits, and not invoked for continue; verifies invocation counts and error/result behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Compiler
    participant BytecodeVM
    participant IteratorObj
    participant HostCode

    HostCode->>Compiler: compile for-of (emit handler + OP_ITER_CLOSE)
    Compiler-->>HostCode: bytecode with OP_ITER_CLOSE and pending-finally entry
    HostCode->>BytecodeVM: execute bytecode (enter loop)
    BytecodeVM->>IteratorObj: getIterator / next()
    alt body completes abruptly (throw / break / return)
        BytecodeVM->>BytecodeVM: invoke pending-finally handler
        BytecodeVM->>IteratorObj: OP_ITER_CLOSE -> call iterator.return() if present (preserve original error)
        BytecodeVM-->>HostCode: rethrow original abrupt completion
    else iteration continues
        BytecodeVM->>IteratorObj: continue loop / next()
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing iterator cleanup for abrupt for-of loop completion, which matches the core objective across all modified files.
Linked Issues check ✅ Passed The PR directly implements all coding requirements from issue #482: adds iterator return() invocation for abrupt completion in both interpreter (Goccia.Evaluator.pas) and bytecode (compiler and VM), and includes regression tests.
Out of Scope Changes check ✅ Passed All changes directly support fixing iterator-close on abrupt for-of completion: bytecode version bump, new OP_ITER_CLOSE opcode, compiler exception handling, evaluator cleanup logic, VM instruction support, and test coverage are all in-scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description provides a concise summary of the changes and clearly references the linked issue (#482), meeting the basic requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@vercel
Copy link
Copy Markdown

vercel Bot commented May 1, 2026

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 May 1, 2026 5:52pm

Request Review

@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification internal Refactoring, CI, tooling, cleanup labels May 1, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/units/Goccia.Compiler.Statements.pas (1)

1653-1669: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove active pending entries before compiling break cleanup.

CompileBreakStatement emits each pending cleanup while the same entry is still present in GPendingFinally. If that cleanup block contains return/break/continue (for example, break inside try { ... } finally { return ... }), EmitPendingCleanup sees the same entry again and recursively recompiles it. That can blow the compiler stack and also duplicate iterator/disposal cleanup. Mirror the snapshot/delete/restore flow you already use in CompileContinueStatement.

Suggested fix
 procedure CompileBreakStatement(const ACtx: TGocciaCompilationContext);
 var
-  I: Integer;
+  I, Count, Base: Integer;
+  Entries: array of TPendingFinallyEntry;
   Entry: TPendingFinallyEntry;
 begin
   if not Assigned(GBreakJumps) then
     Exit;
 
-  if Assigned(GPendingFinally) and (GPendingFinally.Count > GBreakFinallyBase) then
+  if Assigned(GPendingFinally) and (GPendingFinally.Count > GBreakFinallyBase) then
+  begin
+    Count := GPendingFinally.Count;
+    Base := GBreakFinallyBase;
+    SetLength(Entries, Count - Base);
+    for I := Base to Count - 1 do
+      Entries[I - Base] := GPendingFinally[I];
+
+    for I := Count - 1 downto Base do
+    begin
+      if GPendingFinally.Count > I then
+        GPendingFinally.Delete(I);
+      Entry := Entries[I - Base];
+      EmitPendingEntryCleanup(ACtx, Entry, True);
+    end;
+
+    for I := 0 to Length(Entries) - 1 do
+      GPendingFinally.Insert(Base + I, Entries[I]);
+  end;
-    for I := GPendingFinally.Count - 1 downto GBreakFinallyBase do
-    begin
-      Entry := GPendingFinally[I];
-      EmitPendingEntryCleanup(ACtx, Entry, True);
-    end;
 
   GBreakJumps.Add(EmitJumpInstruction(ACtx, OP_JUMP, 0));
 end;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/units/Goccia.Compiler.Statements.pas` around lines 1653 - 1669,
CompileBreakStatement currently calls EmitPendingEntryCleanup while the same
entries remain in GPendingFinally, which allows recursive recompilation; fix it
by mirroring CompileContinueStatement's snapshot/delete/restore flow: when there
are pending finally entries above GBreakFinallyBase, copy the range
(GPendingFinally[GBreakFinallyBase..Count-1]) into a local list/array, remove
those entries from GPendingFinally (truncate Count to GBreakFinallyBase), then
iterate the local copy calling EmitPendingEntryCleanup(ACtx, Entry, True), and
finally restore the removed entries back into GPendingFinally so state is
preserved; keep the final GBreakJumps.Add(EmitJumpInstruction(ACtx, OP_JUMP, 0))
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@source/units/Goccia.Compiler.Statements.pas`:
- Around line 1653-1669: CompileBreakStatement currently calls
EmitPendingEntryCleanup while the same entries remain in GPendingFinally, which
allows recursive recompilation; fix it by mirroring CompileContinueStatement's
snapshot/delete/restore flow: when there are pending finally entries above
GBreakFinallyBase, copy the range (GPendingFinally[GBreakFinallyBase..Count-1])
into a local list/array, remove those entries from GPendingFinally (truncate
Count to GBreakFinallyBase), then iterate the local copy calling
EmitPendingEntryCleanup(ACtx, Entry, True), and finally restore the removed
entries back into GPendingFinally so state is preserved; keep the final
GBreakJumps.Add(EmitJumpInstruction(ACtx, OP_JUMP, 0)) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 67a4c13d-d562-4851-b929-a356cdf2cfef

📥 Commits

Reviewing files that changed from the base of the PR and between 5430dc5 and ccf2373.

📒 Files selected for processing (6)
  • source/units/Goccia.Bytecode.OpCodeNames.pas
  • source/units/Goccia.Bytecode.pas
  • source/units/Goccia.Compiler.Statements.pas
  • source/units/Goccia.Evaluator.pas
  • source/units/Goccia.VM.pas
  • tests/language/for-of/for-of-iterators.js

# Conflicts:
#	source/units/Goccia.Bytecode.pas
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
source/units/Goccia.VM.pas (1)

7835-7862: ⚡ Quick win

Reuse the shared abrupt-close helper instead of open-coding iterator close

Line 7837 onward duplicates close behavior and can drift from the canonical IteratorClose paths. Using CloseRawIteratorPreservingError here keeps VM close semantics centralized while still preserving the original abrupt completion.

♻️ Proposed refactor
       OP_ITER_CLOSE:
       begin
-        try
-          if (FRegisters[A].Kind = grkObject) and
-             (FRegisters[A].ObjectValue is TGocciaIteratorValue) then
-            TGocciaIteratorValue(FRegisters[A].ObjectValue).Close
-          else if (FRegisters[A].Kind = grkObject) and
-                  (FRegisters[A].ObjectValue is TGocciaObjectValue) then
-          begin
-            IterResult := FRegisters[A].ObjectValue;
-            NextMethod := IterResult.GetProperty(PROP_RETURN);
-            if Assigned(NextMethod) and
-               not (NextMethod is TGocciaUndefinedLiteralValue) and
-               not (NextMethod is TGocciaNullLiteralValue) and
-               NextMethod.IsCallable then
-            begin
-              CallArgs := AcquireArguments;
-              try
-                TGocciaFunctionBase(NextMethod).Call(CallArgs, IterResult);
-              finally
-                ReleaseArguments(CallArgs);
-              end;
-            end;
-          end;
-        except
-          // Iterator close errors must not replace the original abrupt completion.
-        end;
+        if FRegisters[A].Kind = grkObject then
+          CloseRawIteratorPreservingError(RegisterToValue(FRegisters[A]));
       end;

Based on learnings: CloseRawIterator/CloseRawIteratorPreservingError are the canonical normal/abrupt IteratorClose paths in source/units/Goccia.VM.pas.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/units/Goccia.VM.pas` around lines 7835 - 7862, The OP_ITER_CLOSE case
is reimplementing iterator-close logic instead of using the canonical helper;
replace the try/except block and open-coded close logic in the OP_ITER_CLOSE
branch with a call to the shared helper CloseRawIteratorPreservingError (or
CloseRawIterator for non-abrupt semantics) passing the iterator register
(FRegisters[A] or its ObjectValue) so the VM uses the centralized IteratorClose
path and preserves the original abrupt completion; remove the duplicated manual
property lookup/CallArgs handling and ensure the call uses the same value/kind
you currently check (e.g. when FRegisters[A].Kind = grkObject) so behavior is
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@source/units/Goccia.VM.pas`:
- Around line 7835-7862: The OP_ITER_CLOSE case is reimplementing iterator-close
logic instead of using the canonical helper; replace the try/except block and
open-coded close logic in the OP_ITER_CLOSE branch with a call to the shared
helper CloseRawIteratorPreservingError (or CloseRawIterator for non-abrupt
semantics) passing the iterator register (FRegisters[A] or its ObjectValue) so
the VM uses the centralized IteratorClose path and preserves the original abrupt
completion; remove the duplicated manual property lookup/CallArgs handling and
ensure the call uses the same value/kind you currently check (e.g. when
FRegisters[A].Kind = grkObject) so behavior is unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6b9a5f63-f3fa-4118-9e14-b3d87594bd85

📥 Commits

Reviewing files that changed from the base of the PR and between ccf2373 and bb5a875.

📒 Files selected for processing (3)
  • source/units/Goccia.Bytecode.pas
  • source/units/Goccia.Evaluator.pas
  • source/units/Goccia.VM.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/units/Goccia.Evaluator.pas

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 9 improved · 🔴 364 regressed · 34 unchanged · avg -7.6%
Bytecode: 🟢 84 improved · 🔴 59 regressed · 264 unchanged · avg +0.2%

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

Measured on ubuntu-latest x64. Benchmark ranges compare cached main-branch min/max ops/sec with the PR run; overlapping ranges are treated as unchanged noise. Percentage deltas are secondary context.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

Suite Timing

Test Runner (interpreted: 8,418 passed; bytecode: 8,418 passed)
Metric Interpreted Bytecode
Total 8418 8418
Passed 8418 ✅ 8418 ✅
Workers 4 4
Test Duration 1.80s 1.81s
Lex (cumulative) 221.6ms 127.5ms
Parse (cumulative) 219.6ms 197.8ms
Compile (cumulative) 193.2ms
Execute (cumulative) 1.61s 1.74s
Engine Total (cumulative) 2.05s 2.25s
Lex (avg/worker) 55.4ms 31.9ms
Parse (avg/worker) 54.9ms 49.5ms
Compile (avg/worker) 48.3ms
Execute (avg/worker) 403.1ms 434.0ms
Engine Total (avg/worker) 513.4ms 563.7ms

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 175.07 MiB 169.93 MiB
GC Peak Live 175.08 MiB 169.94 MiB
GC Allocated During Run 178.72 MiB 173.55 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 87 87
Heap Start Allocated 142.5 KiB 142.5 KiB
Heap End Allocated 1.34 MiB 1.34 MiB
Heap Delta Allocated 1.20 MiB 1.20 MiB
Heap Delta Free 469.5 KiB 469.5 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.51min 2.39min

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 2.73 MiB 2.72 MiB
GC Peak Live 113.30 MiB 63.16 MiB
GC Allocated During Run 14.34 GiB 9.59 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,829 2,637
GC Collected Objects 276,523,514 233,925,093
Heap Start Allocated 1.10 MiB 1.10 MiB
Heap End Allocated 1.10 MiB 1.10 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

test262 Conformance

Metric Value Δ vs main
Total tests 47,420 ±0
Eligible tests 39,029 (82.3%) ±0
Eligible tests passing 20,125 (51.6%) +5 (±0pp)
Total tests passing 20,125 (42.4%) +5 (±0pp)

Areas closest to 100%

Area Pass rate Δ vs main Passing
language/types 90.1% ±0pp 73 / 81
language/statementList 90.0% ±0pp 36 / 40
built-ins/Symbol 87.7% ±0pp 64 / 73

Non-blocking. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached main baseline.

@frostney frostney merged commit 2841b33 into main May 1, 2026
14 checks passed
@frostney frostney deleted the t3code/verify-fix-482 branch May 1, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working internal Refactoring, CI, tooling, cleanup spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

for-of skips IteratorClose on abrupt completion (both interpreter and bytecode)

1 participant