Skip to content

fix(windows): console output shows characters outside the console's code page - #2106

Merged
frostney merged 3 commits into
mainfrom
fix/1890-windows-console-unicode
Nov 5, 2026
Merged

frostney merged 3 commits into
mainfrom
fix/1890-windows-console-unicode

Conversation

@frostney

@frostney frostney commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • On a Windows console, console.log and every other line the CLIs write now show characters outside the console's code page, such as 😀 or 日本語, instead of ?. When GetConsoleMode succeeds on standard output or error, the text goes out as UTF-16 through WriteConsoleW. The code page is never changed.
  • Redirected output stays UTF-8 bytes. OutputCallback is unchanged, and Linux and macOS don't link the new unit.

Closes #1890

Details
  • Where: the new ConsoleOutput unit replaces the write function of a standard text file whose handle is a console. The RTL still fills the buffer with UTF-8, and each flush hands its complete characters to a writer that converts them on the stack, so nothing is allocated, and calls WriteConsoleW. ProcessEncoding applies it to Output, StdOut, ErrOutput and StdErr.
  • Why not in EmitLine: every Write and WriteLn goes through the text file, so timing lines, test reports, errors and the REPL are covered without touching a call site.
  • Out of scope: the RTL reopens the standard files for each new thread, so other threads keep the console's code page. No thread in the repository writes to them directly. GUI applications are left alone.
  • Not checked on a real Windows console. Under wine 9.0 in a pseudo-terminal, ü, 日本語 and ✓ print where main prints ?. Wine shows any surrogate pair from WriteConsoleW as two U+FFFD, so the emoji is unconfirmed.

Visual walkthrough

script.js:

console.log("ü 😀 日本語");
GocciaRunner script.js in cmd (code page 850) GocciaRunner script.js > out.txt
main ü, and ? for each character missing from code page 850 UTF-8 bytes of ü 😀 日本語
This PR ü 😀 日本語 (subject to the console font) the same UTF-8 bytes

How to test

  • On Windows, in cmd or PowerShell with the default OEM code page, run build\GocciaRunner.exe script.js with the script above. Expected: ü 😀 日本語, and chcp afterwards prints the same code page as before.
  • Run build\GocciaRunner.exe script.js > out.txt. Expected: out.txt holds the UTF-8 bytes C3 BC 20 F0 9F 98 80 20 E6 97 A5 E6 9C AC E8 AA 9E 0D 0A.
  • On any platform: ./build.pas tests --test=ConsoleOutput.Test --run-tests. Expected: all tests pass.

Edit: ac1e358 reviewed

  • Code review (fresh engineering-quality lane plus coordinator): nine findings fixed, none open. Fixed: a held-back byte dropped at close, a heap allocation per console write, GUI standard files switched to UTF-8, and test gaps.
  • Full CI (ci.yml, Windows x64 and i386-win32 included): pending for this head.

… page on a Windows console

When a standard handle is a console, ConsoleOutput replaces the text
file's write function: the RTL fills the buffer with UTF-8 and each
flush writes the complete characters as UTF-16 with WriteConsoleW. Every
Write and WriteLn to the console goes through it, including the CLIs'
timing lines and reports. Redirected output stays UTF-8 bytes, and the
console's code page is never changed.

Closes #1890
…thing per write, leave GUI standard files alone

The console write function holds back a split character only when the RTL
flushes a full buffer, so Close and the flush at exit write everything. The
Windows writer converts UTF-8 to UTF-16 on the stack. ProcessEncoding only
changes the standard files of a console application. The test starts its
file in code page 850, decodes each writer call on its own, and names the
IOResult of a failed write.
@frostney frostney added this to the 0.17.0 milestone Nov 5, 2026
@frostney frostney added bug Something isn't working os specific This issue is only for a specific platform/OS runtime TGocciaRuntime: optional host extensions (console, fetch, JSON5, FFI, test assertions, etc.) labels Nov 5, 2026
@vercel

vercel Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
gocciascript-homepage Ready Ready Preview Nov 5, 2026 1:07pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Windows console output now converts UTF-8 text to UTF-16 and writes it with WriteConsoleW. Redirected output remains UTF-8. Initialization configures standard output streams, and documentation describes the encoding behavior.

Changes: Windows console output

Layer / File(s) Summary
UTF-8 output buffering and validation
source/shared/ConsoleOutput.pas, source/shared/ConsoleOutput.Test.pas
A new helper configures UTF-8 output and handles incomplete trailing UTF-8 sequences when buffers split characters. Tests cover console and redirected output, flushing, close-time tails, and writer failures.
Windows stream configuration
source/shared/ProcessEncoding.pas, docs/contributing/tooling.md, docs/embedding.md
Windows console output is converted to UTF-16 and written through WriteConsoleW. Initialization configures four output streams for console processes. The documentation describes console, redirected, and GUI standard-file behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant ProcessEncoding
  participant UseUnicodeOutput
  participant RTLOutput
  participant WriteConsoleW
  ProcessEncoding->>UseUnicodeOutput: Register console probe and writer
  UseUnicodeOutput->>RTLOutput: Set UTF-8 and install console buffer handler
  RTLOutput->>ProcessEncoding: Send buffered UTF-8 bytes
  ProcessEncoding->>WriteConsoleW: Write converted UTF-16 chunks
Loading
Merge Risk: Minimal · up to ac1e3

No actionable merge-blocking issue remains for the repository’s current output paths. A caller that installs an unusually small console text buffer could still stall a write.

Architecture risk: Low · up to ac1e3

The change affects 2 systems.

Changed systems: source, docs

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — source (service) was modified; 3 changed files map to changed impact.
  • observed — docs (service) was modified; 2 changed files map to changed impact.

Before / after behavior

  • observed — Modified behavior in docs/contributing/tooling.md: The Windows encoding description now applies UTF-8 to RTL-returned names and, in console applications, to all four standard text files; redirected output is UTF-8, while GUI standard files retain RTL settings. Console handles use ConsoleOutput to convert buffered UTF-8 to UTF-16 via WriteConsoleW without changing the console code page. The text also adds the per-thread reopening detail and identifies Output and StdOut among the configured files.
  • observed — Modified behavior in docs/embedding.md: The documentation adds that Windows console output uses UTF-16 through WriteConsoleW, and that linking the engine sets the RTL code page to UTF-8 and configures the main thread’s standard output and error; previously it mentioned only UTF-8 output when redirected.
  • observed — Modified behavior in source/shared/ConsoleOutput.Test.pas: Adds the test program’s imports, console code-page and text fixtures, test-suite declarations, and shared probe/writer state.
  • observed — Modified behavior in source/shared/ConsoleOutput.Test.pas: Adds probe functions that record the handle and distinguish console from redirected output, a writer that captures bytes and decodes each call separately, and helpers for UTF-8 encoding, raw byte construction, and complete-length checks.
Pre-merge checks: Passed 5

Check name Status Explanation
Title check Passed The title clearly and concisely describes the main Windows console output fix.
Description check Passed The description includes the required Summary section, explains the change, and documents key implementation constraints and non-goals.
Linked Issues check Passed Issue #1890 requires Unicode text on interactive Windows stdout and stderr, unchanged console code page, and UTF-8 bytes for redirected output. ProcessEncoding.pas installs UseUnicodeOutput for `O…
Out of Scope Changes check Passed The changes stay within issue #1890. The new ConsoleOutput unit, Windows integration, tests, and documentation directly implement or validate console Unicode output and redirected UTF-8 behavior. Th…
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Full details: Linked Issues check

Explanation

Issue #1890 requires Unicode text on interactive Windows stdout and stderr, unchanged console code page, and UTF-8 bytes for redirected output. ProcessEncoding.pas installs UseUnicodeOutput for Output, StdOut, ErrOutput, and StdErr in console applications. ConsoleOutput.pas detects console handles and routes complete UTF-8 sequences to WriteConsoleW; non-console handles keep UTF-8 text-file output. The tests cover console detection, redirected bytes, split UTF-8 characters, line flushing, close handling, and writer failure. The implementation covers other Write and WriteLn calls through the standard text files. The documentation records the thread and GUI limitations.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #1890. The new ConsoleOutput unit, Windows integration, tests, and documentation directly implement or validate console Unicode output and redirected UTF-8 behavior. The embedding documentation describes the changed output behavior. No unrelated product behavior or unrelated files are changed.

Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 0 files. (5 skipped: 5 unsupported.)

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 7c6c822 and ac1e358.

Files selected for processing: 5

  • docs/contributing/tooling.md
  • docs/embedding.md
  • source/shared/ConsoleOutput.Test.pas
  • source/shared/ConsoleOutput.pas
  • source/shared/ProcessEncoding.pas

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

test262 Conformance

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

Category Run Passed Δ Pass Failed Timeouts Δ Timeout Wrap-Infra Pass-rate Δ Rate
built-ins 23,852 23,543 ±0 309 0 ±0 0 98.7% ±0pp
harness 116 116 ±0 0 0 ±0 0 100.0% ±0pp
intl402 3,382 3,360 -1 21 1 +1 0 99.3% ±0pp
language 23,828 22,072 ±0 1,756 0 ±0 0 92.6% ±0pp
staging 1,487 1,406 -1 71 10 +1 0 94.6% -0.1pp
total 52,665 50,497 -2 2,157 11 +2 0 95.9% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
intl402/Temporal 100.0% ±0pp 2,028 / 2,029
built-ins/Promise 99.7% ±0pp 730 / 732
built-ins/TypedArray 99.7% ±0pp 1,449 / 1,453
Per-test deltas (+0 / -0 / timeout +2 / -0)

New timeouts (2):

  • intl402/Temporal/ZonedDateTime/prototype/equals/canonical-not-equal.js
  • staging/sm/Date/two-digit-years.js

Steady-state failures and timeouts are non-blocking; PASS → non-timeout failure transitions fail the conformance gate. Measured on ubuntu-latest x64. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached main baseline.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Web Tooling Benchmark

Workload Status Goccia
acorn pass 0.05 runs/s
babel pass 0.03 runs/s
babel-minify pass 0.35 runs/s
babylon pass 0.17 runs/s
buble pass 0.24 runs/s
chai pass 0.37 runs/s
coffeescript pass 0.01 runs/s
espree pass 0.09 runs/s
esprima pass 0.10 runs/s
jshint pass 0.15 runs/s
lebab pass 0.24 runs/s
postcss pass 0.08 runs/s
prepack pass 0.33 runs/s
prettier pass 0.21 runs/s
source-map pass 0.07 runs/s
terser pass 0.35 runs/s
typescript pass 0.28 runs/s
uglify-js pass 0.13 runs/s

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

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

AWFY Results

Target Status Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v27.0.0-alpha.0.0.0 Δ PR vs main
Bounce pass 2.91ms 2.92ms 0.61ms 0.67ms ~ overlap (-0.40%)
CD pass 30.13ms 29.95ms 6.06ms 6.82ms ~ overlap (+0.61%)
DeltaBlue pass 0.74ms 0.73ms 191.30µs 0.91ms ~ overlap (+1.14%)
Havlak pass 15.94s 16.21s 2699.25ms 122.24ms ~ overlap (-1.74%)
Json pass 44.96ms 45.13ms 8.04ms 2.51ms ~ overlap (-0.37%)
List pass 1.45ms 1.44ms 0.61ms 0.57ms ~ overlap (+0.75%)
Mandelbrot pass 12.76µs 12.77µs 5.33µs 63.35µs ~ overlap (-0.08%)
NBody pass 82.09µs 80.76µs 23.60µs 260.80µs ~ overlap (+1.62%)
Permute pass 3.45ms 3.35ms 0.97ms 462.16µs ~ overlap (+3.00%)
Queens pass 2.01ms 1.92ms 0.80ms 0.84ms ~ overlap (+4.27%)
Richards pass 81.27ms 80.82ms 31.56ms 3.70ms ~ overlap (+0.55%)
Sieve pass 0.84ms 0.83ms 335.65µs 327.25µs ~ overlap (+0.88%)
Storage pass 7.19ms 7.27ms 1.88ms 0.67ms ~ overlap (-1.15%)
Towers pass 5.05ms 5.02ms 1.71ms 0.90ms ~ overlap (+0.63%)

Geomean Ratios

Ratio (row / column) Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v27.0.0-alpha.0.0.0
Goccia main 1.000 1.007 3.491 4.084
Goccia PR 0.993 1.000 3.466 4.055
QuickJS 2026-06-04 0.286 0.288 1.000 1.170
NodeJS v27.0.0-alpha.0.0.0 0.245 0.247 0.855 1.000

14 pinned AWFY benchmarks. Medians from 5 interleaved samples per engine; raw JSON includes min/max/CV and is attached as the awfy-report artifact. Δ compares PR Goccia median against the same-runner main Goccia median; overlapping min/max ranges are treated as unchanged noise. Hardware counters were requested but not recorded: perf stat failed: Error: No supported events found. Rows below 0.5ms are timer-floor sensitive.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

JetStream 3 Performance Barometer

Workload Status Goccia main Goccia PR QuickJS Node.js vs QuickJS vs Node.js
hash-map pass 1.91 1.89 17.88 401.71 9.44× 212.05×
ai-astar pass 3.25 3.28 40.91 345.39 12.46× 105.16×
gaussian-blur pass 0.92 0.91 7.99 291.94 8.81× 321.86×
raytrace-public-class-fields pass 2.09 2.07 21.16 326.07 10.24× 157.86×
sync-fs pass 1.63 1.63 27.36 223.02 16.83× 137.22×
lazy-collections pass 6.01 6.06 81.90 161.55 13.51× 26.65×

Geomean reference ratio: QuickJS 11.58×; Node.js 126.73×.

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

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

447 benchmarks · PR vs same-runner main build

🟢 32 improved · 🔴 72 regressed · 343 unchanged · avg -1.6%

Typical per-run noise (median variance): ±2.3%. Deltas within noise overlap and read as unchanged.

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

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 Nov 5, 2026

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (17,283 passed)
Metric Value
Total 17283
Passed 17283 ✅
Workers 4
Test Duration 19.43s
Lex (cumulative) 848.6ms
Parse (cumulative) 880.3ms
Compile (cumulative) 1.14s
Execute (cumulative) 43.57s
Engine Total (cumulative) 46.44s
Lex (avg/worker) 212.1ms
Parse (avg/worker) 220.1ms
Compile (avg/worker) 284.3ms
Execute (avg/worker) 10.89s
Engine Total (avg/worker) 11.61s

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 Value
GC Live 23.8 KiB
GC Peak Live 522.51 MiB
GC Allocated During Run 3.22 GiB
GC Limit 7.80 GiB
GC Collections 3,671
GC Collected Objects 17,729,882
Heap Start Allocated 369.4 KiB
Heap End Allocated 3.04 MiB
Heap Delta Allocated 2.68 MiB
Heap Delta Free 2.14 MiB
Benchmarks (447)
Metric Value
Total 447
Workers 4
Duration 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 Value
GC Live 5.6 KiB
GC Peak Live 230.73 MiB
GC Allocated During Run 41.08 GiB
GC Limit 7.80 GiB
GC Collections 10,691
GC Collected Objects 575,857,414
Heap Start Allocated 1.22 MiB
Heap End Allocated 1.22 MiB
Heap Delta Allocated 3.3 KiB
Boot
Metric Value
Boot (median) 3.9ms
Boot (min) 3.9ms

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

Measured on ubuntu-latest x64.

@frostney
frostney marked this pull request as ready for review November 5, 2026 13:37
@frostney

frostney commented Nov 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor
Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@frostney

frostney commented Nov 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor
Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@frostney
frostney merged commit 1932074 into main Nov 5, 2026
126 checks passed
@frostney
frostney deleted the fix/1890-windows-console-unicode branch November 5, 2026 21:55

This branch was successfully deployed

1 active deployment
Preview — ac1e3585 Deployed Nov 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working os specific This issue is only for a specific platform/OS runtime TGocciaRuntime: optional host extensions (console, fetch, JSON5, FFI, test assertions, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

On Windows, console.log to an interactive console prints characters outside the console's code page as ?

1 participant