Skip to content

Strip release artifacts and bake production version info#211

Merged
frostney merged 2 commits into
mainfrom
t3code/executable-size-optimization
Apr 8, 2026
Merged

Strip release artifacts and bake production version info#211
frostney merged 2 commits into
mainfrom
t3code/executable-size-optimization

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 8, 2026

Summary

  • Generate a production-only version include at build time and use it in Goccia.Version when PRODUCTION is defined.
  • Add artifact staging support for --strip and use it in release packaging to reduce binary size.
  • Remove unused Goccia.Logger dependencies from runtime entrypoints and keep the generated version include out of version control.

Testing

  • Verified the change set is limited to build/release plumbing, version reporting, and import cleanup

Summary by CodeRabbit

  • New Features

    • Production builds now embed version and commit information, eliminating runtime git dependencies.
    • Release binaries are automatically optimized through stripping during packaging.
    • CI pipeline generates and bakes version metadata directly into production builds for consistency.
  • Chores

    • Removed unused internal logger dependencies from core modules.

- Generate production version metadata at build time
- Remove logging dependency from core runtime units
- Add optional artifact stripping for release bundles
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

Warning

Rate limit exceeded

@frostney has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 31 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 6 minutes and 31 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fffae631-6417-4f38-b19c-7df7eafba3e6

📥 Commits

Reviewing files that changed from the base of the PR and between 3742e10 and 634c14b.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • units/Goccia.Version.pas
📝 Walkthrough

Walkthrough

The changes introduce a production build version baking system that generates a compile-time include file with hardcoded version and commit constants, refactor the build script to separate version computation logic, enhance artifact staging with binary stripping capability, and remove unused logger dependencies from multiple units.

Changes

Cohort / File(s) Summary
Version Baking System
build.pas, units/Goccia.Version.pas, .github/workflows/ci.yml, .gitignore
Implements version baking for production builds: CI generates units/Goccia.Version.Generated.inc containing BAKED_VERSION and BAKED_COMMIT constants derived from git; build.pas refactors PrintVersion into ComputeVersion, ComputeCommit, and GenerateVersionInclude functions; Goccia.Version.pas conditionally includes generated file in PRODUCTION builds or runs git commands otherwise.
Artifact Staging Enhancement
.github/scripts/stage-build-artifacts.sh, .github/workflows/ci.yml
Adds --strip named flag support to artifact staging script with flexible argument parsing (allows 2–4 arguments in any order); CI release packaging now passes --strip to strip binaries during artifact staging for both artifacts and per-target release jobs.
Logger Dependency Cleanup
ScriptLoader.dpr, units/Goccia.Interpreter.pas, units/Goccia.Values.FunctionValue.pas
Removes unused Goccia.Logger imports from three units; removes logger initialization from ScriptLoader.dpr.

Sequence Diagram

sequenceDiagram
    participant CI as GitHub Actions<br/>(CI Workflow)
    participant Git as Git Commands
    participant BuildScript as build.pas
    participant GenFile as Version Include<br/>Generator
    participant Pascal as Pascal Compiler
    participant Artifacts as Artifact Staging

    CI->>Git: git describe (version)
    Git-->>CI: version tag info
    CI->>Git: git rev-parse (commit)
    Git-->>CI: commit hash
    
    CI->>BuildScript: Execute with computed<br/>DESCRIBE & COMMIT env vars
    
    BuildScript->>BuildScript: ComputeVersion()<br/>(parse DESCRIBE)
    BuildScript->>BuildScript: ComputeCommit()<br/>(parse COMMIT)
    
    BuildScript->>GenFile: GenerateVersionInclude()<br/>(write BAKED_VERSION,<br/>BAKED_COMMIT)
    GenFile-->>BuildScript: units/Goccia.Version.Generated.inc
    
    BuildScript->>Pascal: Trigger compilation<br/>(-Fu./units includes generated file)
    Pascal->>Pascal: Conditional compile:<br/>PRODUCTION mode
    Pascal->>GenFile: Include BAKED_VERSION<br/>& BAKED_COMMIT constants
    Pascal-->>BuildScript: Binary with baked version
    
    BuildScript->>Artifacts: stage-build-artifacts.sh<br/>with --strip flag
    Artifacts->>Artifacts: Strip binaries
    Artifacts-->>CI: Distribution-ready artifacts
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 A version baked in compile time,
No git commands at runtime to chime,
Binaries stripped clean and lean,
The tidiest build we've seen!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers the main changes but lacks adequate testing documentation required by the repository template. Complete the testing section by checking applicable boxes and specifying which tests were run or explaining why the test suite was not executed.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the two main changes: stripping release artifacts and baking production version info.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/executable-size-optimization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
build.pas (1)

428-431: Note: Include file generated for all build modes.

The include file is generated even for --dev builds where PRODUCTION isn't defined and the file goes unused. This is fine for consistency, but if you want to skip unnecessary I/O in dev mode, you could gate generation on BuildMode = bmProd.

♻️ Optional: Skip include generation in dev mode
   GVersion := ComputeVersion;
   GCommit := ComputeCommit;
+  if BuildMode = bmProd then
+    GenerateVersionInclude(GVersion, GCommit);
   PrintVersion(GVersion, GCommit);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build.pas` around lines 428 - 431, The build currently always calls
GenerateVersionInclude(GVersion, GCommit) regardless of mode; change it to only
generate the include in production builds by checking the build mode (e.g., if
BuildMode = bmProd then call GenerateVersionInclude(GVersion, GCommit)); keep
ComputeVersion, ComputeCommit and PrintVersion unchanged so printing still
occurs in dev, but avoid the I/O when not in production.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@build.pas`:
- Around line 428-431: The build currently always calls
GenerateVersionInclude(GVersion, GCommit) regardless of mode; change it to only
generate the include in production builds by checking the build mode (e.g., if
BuildMode = bmProd then call GenerateVersionInclude(GVersion, GCommit)); keep
ComputeVersion, ComputeCommit and PrintVersion unchanged so printing still
occurs in dev, but avoid the I/O when not in production.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35660cc6-4fb2-49ee-bbf7-b7aa9d7ad6a0

📥 Commits

Reviewing files that changed from the base of the PR and between 50dbfba and 3742e10.

📒 Files selected for processing (8)
  • .github/scripts/stage-build-artifacts.sh
  • .github/workflows/ci.yml
  • .gitignore
  • ScriptLoader.dpr
  • build.pas
  • units/Goccia.Interpreter.pas
  • units/Goccia.Values.FunctionValue.pas
  • units/Goccia.Version.pas
💤 Files with no reviewable changes (3)
  • units/Goccia.Values.FunctionValue.pas
  • units/Goccia.Interpreter.pas
  • ScriptLoader.dpr

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 8, 2026

Benchmark Results

274 benchmarks

Interpreted: 🟢 201 improved · 🔴 20 regressed · 53 unchanged · avg +4.4%
Bytecode: 🟢 195 improved · 🔴 16 regressed · 63 unchanged · avg +4.2%

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

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 8, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 3797 3797
Tests Passed 3756 ✅ 3797 ✅
Tests Skipped 41 0
Tests Test Duration 211.8ms 203.0ms
Tests Lex 72.6ms 47.8ms
Tests Parse 94.7ms 92.6ms
Tests Compile 58.7ms
Tests Execute 226.6ms 229.0ms
Tests Engine Total 393.8ms 428.2ms
Benchmarks Total 274 274
Benchmarks Duration 7.63min 6.26min

Measured on ubuntu-latest x64.

- Generate version/commit constants in CI for every build
- Remove the runtime git probe from `Goccia.Version`
@frostney frostney merged commit d6227fc into main Apr 8, 2026
9 checks passed
@frostney frostney deleted the t3code/executable-size-optimization branch April 8, 2026 09:41
@frostney frostney added the internal Refactoring, CI, tooling, cleanup label Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Refactoring, CI, tooling, cleanup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant