Skip to content

yuku-toolchain/ecmascript-parser-benchmark-native

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

172 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Native ECMAScript Parser Benchmark

Benchmarks for ECMAScript parsers compiled to native binaries (Zig, Rust), measuring raw parsing speed without any JavaScript runtime overhead.

System

Property Value
OS macOS 24.6.0 (arm64)
CPU Apple M3
Cores 8
Memory 16 GB

Parsers

Language: Zig

A high-performance & spec-compliant JavaScript/TypeScript compiler toolchain written in Zig.

Language: Rust

A high-performance JavaScript and TypeScript parser written in Rust.

Language: Rust

An extensible Rust-based platform for compiling and bundling JavaScript and TypeScript.

Benchmarks

File size: 7.83 MB

Bar chart comparing native parser speeds for typescript.js

Parser Median Min p99 Relative
Yuku 22.04 ms 21.76 ms 22.49 ms 1.00×
Oxc 23.94 ms 23.82 ms 24.23 ms 1.09×
SWC 41.21 ms 40.68 ms 41.91 ms 1.87×

File size: 2.95 MB

Bar chart comparing native parser speeds for checker.ts

Parser Median Min p99 Relative
Yuku 7.38 ms 7.34 ms 7.55 ms 1.00×
Oxc 7.73 ms 7.67 ms 7.99 ms 1.05×
SWC 13.51 ms 13.16 ms 15.64 ms 1.83×

File size: 0.07 MB

Bar chart comparing native parser speeds for react.js

Parser Median Min p99 Relative
Yuku 0.14 ms 0.14 ms 0.15 ms 1.00×
Oxc 0.16 ms 0.16 ms 0.17 ms 1.15×
SWC 0.27 ms 0.27 ms 0.28 ms 1.94×

Semantic

The ECMAScript specification defines a set of early errors that conformant implementations must report before execution. Some of these are detectable during parsing from local context alone, like return outside a function, yield outside a generator, invalid destructuring, etc. Others require knowledge of the program's scope structure and bindings, such as redeclarations, unresolved exports, private fields used outside their class, etc.

Parsers handle this differently: SWC checks some scope-dependent errors during parsing itself, while Yuku and Oxc defer them entirely to a separate semantic analysis pass. This keeps parsing fast and lets each consumer opt in only to the work it actually needs. A formatter, for example, only needs the AST and should not pay the cost of scope resolution.

The benchmarks below measure parsing followed by this additional pass, which builds a scope tree and symbol table, resolves identifier references to their declarations, and reports the remaining early errors. Together, parsing and semantic analysis cover the full set of early errors required by the specification.

Bar chart comparing parser speeds with semantic analysis for typescript.js

Parser Median Min p99 Relative
Yuku + Semantic 39.54 ms 39.25 ms 40.57 ms 1.00×
Oxc + Semantic 55.01 ms 53.07 ms 56.58 ms 1.39×

Bar chart comparing parser speeds with semantic analysis for checker.ts

Parser Median Min p99 Relative
Yuku + Semantic 12.93 ms 12.84 ms 13.49 ms 1.00×
Oxc + Semantic 18.11 ms 17.87 ms 36.31 ms 1.40×

Bar chart comparing parser speeds with semantic analysis for react.js

Parser Median Min p99 Relative
Yuku + Semantic 0.27 ms 0.26 ms 0.28 ms 1.00×
Oxc + Semantic 0.34 ms 0.34 ms 0.36 ms 1.28×

Run Benchmarks

Prerequisites

  • Bun - JavaScript runtime and package manager
  • Rust - For building Rust-based parsers
  • Zig - For building Zig-based parsers (requires nightly/development version)

Steps

  1. Clone the repository:
git clone https://github.com/yuku-toolchain/ecmascript-parser-benchmark-native.git
cd ecmascript-parser-benchmark-native
  1. Install dependencies:
bun install
  1. Run benchmarks:
bun bench

This will build all parsers and run benchmarks on all test files. Results are saved to the result/ directory.

Methodology

Parsing is timed in-process to isolate it from process startup, dynamic linking, file I/O, and memory teardown, which would otherwise dominate the measurement on smaller files.

The source is read once, then each parser runs 50 warmup iterations followed by 300 timed iterations. A monotonic clock wraps only the parse call (plus the semantic pass for the semantic variants); allocation and teardown happen outside the timed region, and the result passes through an optimization barrier so the work cannot be elided. Reported figures are the median, minimum, and 99th percentile of the timed runs.

Binaries are built with release optimizations: Rust with cargo build --release (LTO, single codegen unit, symbol stripping) and Zig with zig build --release=fast. Each uses a fast general-purpose allocator (Rust mimalloc, Zig smp_allocator).

About

Benchmarks for ECMAScript parsers compiled to native binaries (Zig, Rust), measuring raw parsing speed without any JavaScript runtime overhead.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors