Skip to content

Fix spyOn restore descriptor for re-spying#397

Merged
frostney merged 1 commit into
mainfrom
codex/394-spyon-mockrestore-respy
Apr 24, 2026
Merged

Fix spyOn restore descriptor for re-spying#397
frostney merged 1 commit into
mainfrom
codex/394-spyon-mockrestore-respy

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Closes Testing API: spyOn cannot re-spy a property after mockRestore (non-configurable) #394.
  • Clone the original spy target descriptor before replacing the target property, so mockRestore() does not restore from a descriptor that DefineProperty has freed.
  • Restore from a fresh cloned descriptor and mark/free the stored descriptor snapshot with the mock function.
  • Add native Pascal coverage for mockRestore() preserving configurable/writable flags and allowing a second spyOn on the same method.

Testing

  • Verified no regressions in end-to-end JavaScript/TypeScript tests: ./fixtures/ffi/build.sh && ./build/GocciaTestRunner tests --asi --unsafe-ffi --no-progress
  • Updated documentation
  • Optional: Verified no regressions and confirmed the bugfix in native Pascal tests: ./build.pas tests && ./build/Goccia.Builtins.TestingLibrary.Test
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

Additional checks:

  • ./format.pas --check

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

Modified the spy/restore mechanism to preserve and restore the full original property descriptor instead of reconstructing it, ensuring that configurable and writable flags persist after mockRestore(), enabling subsequent spyOn() calls on the same property. Added a test case validating re-spy capability post-restore.

Changes

Cohort / File(s) Summary
Mock and Spy Core Fix
source/units/Goccia.Values.MockFunction.pas
Modified spy creation to clone and store the original complete property descriptor; updated DoMockRestore to re-define the property using the stored descriptor clone instead of reconstructing it, preserving all flags and accessor/data behavior.
Testing Coverage
source/units/Goccia.Builtins.TestingLibrary.Test.pas
Added TestSpyOnMockRestoreAllowsReSpy test that verifies a property can be re-spied after mockRestore() and that the descriptor remains configurable and writable through multiple spy/restore cycles.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing the spyOn restore descriptor to allow re-spying after mockRestore.
Description check ✅ Passed The description provides a clear summary of the fix, references the linked issue (#394), details testing performed, and follows the template structure with completed testing checkboxes.
Linked Issues check ✅ Passed The PR directly addresses issue #394 by cloning the original descriptor before replacement and preserving configurable/writable flags on restore, enabling re-spying.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the descriptor handling in MockFunction.pas and adding related test coverage, with no unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

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.Builtins.TestingLibrary.Test.pas (1)

3500-3503: Prefer asserting the restored flags through the public Object API.

This part of the test now depends on TGocciaObjectValue.GetOwnPropertyDescriptor / TGocciaPropertyDescriptor rather than the user-visible surface. If you want to keep the flag check, exercising Object.getOwnPropertyDescriptor here would preserve the coverage without coupling the test to descriptor internals.

Based on learnings, native Pascal tests should stay focused on visible public behavior where possible and keep implementation details private.

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

In `@source/units/Goccia.Builtins.TestingLibrary.Test.pas` around lines 3500 -
3503, The test inspects property flags via internal types
(TGocciaObjectValue.GetOwnPropertyDescriptor / TGocciaPropertyDescriptor) —
change it to assert flags using the public JS API by calling
Object.getOwnPropertyDescriptor(Obj, 'method') and then checking the returned
descriptor's configurable/writable/enumerable via the public surface (the result
of Object.getOwnPropertyDescriptor) instead of referencing Descriptor or
TGocciaPropertyDescriptor; update the Expect<Boolean>(...) assertions to read
from the JS API result and remove direct uses of GetOwnPropertyDescriptor and
TGocciaPropertyDescriptor so the test relies only on visible Object API
behavior.
🤖 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.Builtins.TestingLibrary.Test.pas`:
- Around line 3500-3503: The test inspects property flags via internal types
(TGocciaObjectValue.GetOwnPropertyDescriptor / TGocciaPropertyDescriptor) —
change it to assert flags using the public JS API by calling
Object.getOwnPropertyDescriptor(Obj, 'method') and then checking the returned
descriptor's configurable/writable/enumerable via the public surface (the result
of Object.getOwnPropertyDescriptor) instead of referencing Descriptor or
TGocciaPropertyDescriptor; update the Expect<Boolean>(...) assertions to read
from the JS API result and remove direct uses of GetOwnPropertyDescriptor and
TGocciaPropertyDescriptor so the test relies only on visible Object API
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4955afc3-233f-48a0-b462-b878dd1b54b6

📥 Commits

Reviewing files that changed from the base of the PR and between a11b6ee and 4f8d622.

📒 Files selected for processing (2)
  • source/units/Goccia.Builtins.TestingLibrary.Test.pas
  • source/units/Goccia.Values.MockFunction.pas

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark Results

386 benchmarks

Interpreted: 🟢 292 improved · 🔴 16 regressed · 78 unchanged · avg +7.1%
Bytecode: 🟢 3 improved · 🔴 380 regressed · 3 unchanged · avg -19.6%

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

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

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 7759 7759
Tests Passed 7718 ✅ 7759 ✅
Tests Skipped 41 0
Tests Workers 4 4
Tests Test Duration 1.60s 1.40s
Tests Lex (cumulative) 187.7ms 125.6ms
Tests Parse (cumulative) 316.4ms 267.4ms
Tests Compile (cumulative) 170.9ms
Tests Execute (cumulative) 1.96s 1.35s
Tests Engine Total (cumulative) 2.47s 1.92s
Tests Lex (avg/worker) 46.9ms 31.4ms
Tests Parse (avg/worker) 79.1ms 66.9ms
Tests Compile (avg/worker) 42.7ms
Tests Execute (avg/worker) 490.8ms 338.7ms
Tests Engine Total (avg/worker) 616.8ms 479.7ms
Benchmarks Total 386 386
Benchmarks Workers 4 4
Benchmarks Duration 3.10min 2.86min

Measured on ubuntu-latest x64.

@frostney frostney merged commit f29a34a into main Apr 24, 2026
10 checks passed
@frostney frostney deleted the codex/394-spyon-mockrestore-respy branch April 24, 2026 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Testing API: spyOn cannot re-spy a property after mockRestore (non-configurable)

1 participant