Skip to content

fix(intl): discover the installed ICU version at runtime instead of a hardcoded max#908

Merged
frostney merged 5 commits into
mainfrom
icu-dynamic-version-discovery
Jun 29, 2026
Merged

fix(intl): discover the installed ICU version at runtime instead of a hardcoded max#908
frostney merged 5 commits into
mainfrom
icu-dynamic-version-discovery

Conversation

@frostney

@frostney frostney commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • The Linux ICU loader (source/shared/ICU.pas) looped a hardcoded ICU_VERSION_MAX = 76 downto 70, so a newer ICU runtime — 77+, as shipped by e.g. Ubuntu 25.10 — was never found: libicui18n.so failed to load, all Intl returned empty, and Intl.DateTimeFormat silently fell back to printing the raw epoch number. Supporting each new ICU required bumping the constant by hand.
  • Replaces the fixed ceiling with runtime discovery: scan the standard library directories and the LD_LIBRARY_PATH directories for the installed libicui18n.so.<major> files, take the newest major present, and try it down to a ICU_VERSION_MIN compatibility floor, keeping the unversioned-SONAME fallback. There is no upper bound, so any future ICU release loads with no code change. LoadLibrary still resolves the final path through the dynamic linker; the scan only learns which majors exist.
  • The two pieces of pure logic behind discovery — ParseICUSoMajorVersion (SONAME → major) and HighestICUMajorVersionInDir (newest <base>.<major> in a dir) — are platform-independent, so they live outside the Linux {$IFDEF} and are unit-tested on every platform. Only the system-path scan + LoadLibrary stay Linux-only. The directory scan enumerates entries and lets the parser decide what matches, rather than relying on FindFirst wildcard semantics that differ across platforms.
  • Adds source/shared/ICU.Test.pas covering the version parsing (libicui18n.so.77 → 77, …so.76.1 → 76, unversioned/garbage → 0) and the newest-present directory scan, including majors above the old 76 ceiling (74/76/77/100 → 100).

Constraints / non-goals: the actual ICU loading is Linux-only — the macOS (libicucore) and Windows (icu.dll) paths are untouched. No behavior change on systems where an ICU in 70–76 is installed. Discovered while investigating the intl402/.../formatToParts/compare-to-temporal.js CI flake (that test's flakiness is a separate, contention-driven timeout, not this bug).

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests

  • Updated documentation

  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed)

  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

  • ICU.Test passes on both platforms (2/2 on macOS and on x86_64 Linux): version parsing and the newest-present scan, with fake majors 77 and 100 → 100 (proving the ceiling is gone). The string/directory logic is now tested everywhere, not just Linux.

  • x86_64 Linux (Ubuntu, ICU 76): engine builds, Intl loads via runtime discovery, Intl.DateTimeFormat(...).format/formatToParts produce correct output, and intl402/DateTimeFormat/prototype/formatToParts/compare-to-temporal.js passes.

  • LD_LIBRARY_PATH discovery verified end-to-end: with ICU 76 moved out of every standard dir, Intl.DateTimeFormat is unavailable with no LD_LIBRARY_PATH (returns the raw number) and works again with LD_LIBRARY_PATH pointing at the relocated libs.

  • macOS: ./build.pas testrunner + full JS suite 11046/11046; all Pascal unit tests build and pass.

  • ./format.pas --check clean.

No documentation/version-range update needed — the supported ICU range was not documented (only "the libicu system package").

… hardcoded max

The Linux ICU loader looped a fixed `ICU_VERSION_MAX = 76 downto 70` range, so a
newer ICU runtime (77+, e.g. on Ubuntu 25.10) was never found: `libicui18n.so`
failed to load, all Intl returned empty, and DateTimeFormat fell back to printing
raw numbers. Supporting a new ICU required bumping the constant by hand.

Replace the hardcoded ceiling with runtime discovery: scan the standard library
directories for the installed `libicui18n.so.<major>` files, take the newest
major present, and try it (down to a `ICU_VERSION_MIN` compatibility floor),
keeping the unversioned-SONAME fallback. There is no upper bound, so any future
ICU release is picked up with no code change. LoadLibrary still resolves the
final path through the dynamic linker; the scan only learns which majors exist.

Adds source/shared/ICU.Test.pas covering the version parsing and the
newest-present directory scan, including majors above the old 76 ceiling.

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

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview Jun 29, 2026 4:23pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6c10c386-d186-4fbd-9483-7c910d17bf3a

📥 Commits

Reviewing files that changed from the base of the PR and between 5a7f32b and acec0e3.

📒 Files selected for processing (1)
  • source/shared/ICU.Test.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/shared/ICU.Test.pas

📝 Walkthrough

Walkthrough

Adds ICU SONAME parsing and runtime major discovery, rewrites Linux loading to scan installed libraries, and expands tests for single-directory and directory-list lookup.

Changes

ICU Runtime Version Discovery

Layer / File(s) Summary
New public helpers and config change
source/shared/ICU.pas
Declares ParseICUSoMajorVersion, HighestICUMajorVersionInDir, and HighestICUMajorVersionInDirList in the public interface and removes the hardcoded Linux ICU max major constant.
Version parsing, directory scanning, and loader rewrite
source/shared/ICU.pas
Implements the helper functions that parse SONAME majors and scan directories or directory lists, then rewrites TryLoadLinuxICU to discover installed ICU majors at runtime and fall back to unversioned SONAMEs.
ICU tests for parsing and directory lists
source/shared/ICU.Test.pas
Updates the ICU test suite registration, fixture helpers, existing parsing and single-directory checks, and adds a directory-list test covering multiple paths and empty segments.

🎯 3 (Moderate) | ⏱️ ~20 minutes

bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It clearly describes the main change: discovering the installed ICU version at runtime instead of using a hardcoded maximum.
Description check ✅ Passed It follows the template with Summary and Testing sections, and includes implementation constraints, non-goals, and test results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 11,046 passed; bytecode: 11,046 passed)
Metric Interpreted Bytecode
Total 11046 11046
Passed 11046 ✅ 11046 ✅
Workers 4 4
Test Duration 18.93s 18.43s
Lex (cumulative) 466.1ms 496.6ms
Parse (cumulative) 352.1ms 376.1ms
Compile (cumulative) 794.2ms
Execute (cumulative) 54.5ms 44.85s
Engine Total (cumulative) 872.7ms 46.52s
Lex (avg/worker) 116.5ms 124.1ms
Parse (avg/worker) 88.0ms 94.0ms
Compile (avg/worker) 198.5ms
Execute (avg/worker) 13.6ms 11.21s
Engine Total (avg/worker) 218.2ms 11.63s

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 283.78 MiB 281.18 MiB
GC Peak Live 336.98 MiB 309.95 MiB
GC Allocated During Run 531.00 MiB 474.99 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 195 195
GC Collected Objects 2,605,583 2,172,706
Heap Start Allocated 182.7 KiB 182.7 KiB
Heap End Allocated 3.66 MiB 3.66 MiB
Heap Delta Allocated 3.48 MiB 3.48 MiB
Heap Delta Free 1.68 MiB 1.68 MiB
Benchmarks (interpreted: 437; bytecode: 437)
Metric Interpreted Bytecode
Total 437 437
Workers 4 4
Duration 2.86min 2.87min

Memory

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

Metric Interpreted Bytecode
GC Live 6.28 MiB 6.28 MiB
GC Peak Live 87.25 MiB 97.63 MiB
GC Allocated During Run 15.38 GiB 11.25 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 3,721 3,533
GC Collected Objects 242,765,182 251,951,194
Heap Start Allocated 3.36 MiB 3.36 MiB
Heap End Allocated 3.36 MiB 3.36 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

437 benchmarks · PR vs same-runner main build

Interpreted: 🟢 19 improved · 🔴 36 regressed · 382 unchanged · avg -0.6%
Bytecode: 🟢 30 improved · 🔴 40 regressed · 367 unchanged · avg +0.6%

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

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

test262 Conformance

🚫 Regression vs cached main baseline. 1 previously-passing test(s) now fail; pass count Δ -1. This run blocks merge — see "Newly failing" below.

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,642 22,618 ±0 1,024 95.7% ±0pp
harness 116 116 ±0 0 100.0% ±0pp
intl402 3,341 3,334 -1 7 99.8% ±0pp
language 23,711 23,711 ±0 0 100.0% ±0pp
staging 1,482 1,111 ±0 371 75.0% ±0pp
total 52,292 50,890 -1 1,402 97.3% ±0pp

Areas closest to 100%

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

Newly failing (1):

  • intl402/DateTimeFormat/prototype/formatToParts/compare-to-temporal.js

Newly passing (1):

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

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

The version parsing and "newest present" directory scan are pure string and
directory logic, but they were declared inside the Linux {$IFDEF} alongside the
loader, so ICU.Test could only exercise them on Linux — even though the logic
they test works anywhere.

Move ParseICUSoMajorVersion and HighestICUMajorVersionInDir out of the Linux
block and parameterise the scan by SONAME base, leaving only the actual library
loading (system-path scan + LoadLibrary) Linux-only. The directory scan now
enumerates entries and lets the parser decide what matches, rather than relying
on FindFirst wildcard semantics that differ across platforms. ICU.Test drops its
{$IFDEF LINUX} gating and runs on every platform.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@frostney frostney marked this pull request as ready for review June 29, 2026 14:57
@coderabbitai coderabbitai Bot added the bug Something isn't working label Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@source/shared/ICU.pas`:
- Around line 116-124: DiscoverHighestICUMajorVersion currently only checks
ICU_SCAN_DIRS, so add linker-search-path discovery to make versioned ICU
installs visible to TryLoadLinuxICU. Update the ICU discovery flow around
DiscoverHighestICUMajorVersion, HighestICUMajorVersionInDir, and TryLoadLinuxICU
to also inspect linker paths such as those from LD_LIBRARY_PATH and include
those directories when searching for libicu*.so.<major> SONAMEs. Keep the
unversioned fallback, but ensure versioned libraries reachable only through
linker paths are found first.

In `@source/shared/ICU.Test.pas`:
- Around line 32-39: The temp fixture setup is swallowing I/O failures, so the
test can continue and fail later with a misleading assertion instead of the real
problem. Update TouchFile to raise when FileCreate fails, and change the setup
around ForceDirectories so directory creation is checked and any failure aborts
immediately. Use the existing TouchFile helper and the fixture setup block that
prepares the temp path/files to locate the changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a6b4050-e522-425a-a1bf-10e532909e67

📥 Commits

Reviewing files that changed from the base of the PR and between b42672c and ec2c15c.

📒 Files selected for processing (2)
  • source/shared/ICU.Test.pas
  • source/shared/ICU.pas

Comment thread source/shared/ICU.pas
Comment thread source/shared/ICU.Test.pas
Address PR review: DiscoverHighestICUMajorVersion only scanned the fixed
ICU_SCAN_DIRS, so an ICU reachable only through a dynamic-linker env path
(LD_LIBRARY_PATH) was never found — its versioned SONAME was never tried, and the
unversioned fallback does not cover a runtime-only `libicu*.so.<major>`. The
previous range-loop happened to cover this because LoadLibrary searches linker
paths by SONAME; the discovery rewrite lost it.

Add a generic, cross-platform HighestICUMajorVersionInDirList that scans a
separator-delimited directory list, and feed it LD_LIBRARY_PATH from the Linux
discovery. The newest major found there is then loaded by SONAME through the
linker as before. Verified end-to-end on x86_64 Linux: with ICU moved out of all
standard dirs, Intl is unavailable without LD_LIBRARY_PATH and works with it.

Also address the test-fixture review: ICU.Test now fails fast — TouchFile raises
when FileCreate fails and directory creation goes through a MakeTempDir helper
that raises on ForceDirectories failure — so a fixture I/O error reports the real
problem instead of a misleading assertion. Adds a cross-platform test for the new
directory-list scan.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@source/shared/ICU.Test.pas`:
- Around line 109-119: The multi-directory ICU test is using a path separator
that can collide with absolute temp paths on Windows, so the split logic breaks
before the intended case is exercised. Update the
`HighestICUMajorVersionInDirList` test fixture in `ICU.Test.pas` to use a
separator that cannot appear in `MakeTempDir` outputs (for example a test-only
delimiter like `|`) and pass that same delimiter consistently into the helper
call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c29f204-4072-4b16-bf11-c973cad34a79

📥 Commits

Reviewing files that changed from the base of the PR and between ec2c15c and 5a7f32b.

📒 Files selected for processing (2)
  • source/shared/ICU.Test.pas
  • source/shared/ICU.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/shared/ICU.pas

Comment thread source/shared/ICU.Test.pas Outdated
frostney and others added 2 commits June 29, 2026 17:22
Address PR review: TestHighestInDirListAcrossPaths built the list with ':' over
absolute temp paths, which on Windows contain a drive-letter colon (C:\...) and
would split there, breaking the test before it exercises the multi-directory
logic. Use '|' — which cannot occur in a generated path — as the fixture
separator. HighestICUMajorVersionInDirList takes the separator as a parameter,
so the split logic under test is identical; the production caller still passes
':' for LD_LIBRARY_PATH.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@frostney frostney merged commit 3021e38 into main Jun 29, 2026
61 of 62 checks passed
@frostney frostney deleted the icu-dynamic-version-discovery branch June 29, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant