Benchmarks for ECMAScript parsers available as npm packages, including pure JavaScript parsers and native parsers (Zig, Rust) via NAPI bindings.
| Property | Value |
|---|---|
| OS | macOS 24.6.0 (arm64) |
| CPU | Apple M3 |
| Cores | 8 |
| Memory | 16 GB |
A tiny, fast JavaScript parser, written completely in JavaScript.
A JavaScript compiler and parser used by the Babel toolchain.
A high-performance JavaScript and TypeScript parser written in Rust.
An extensible Rust-based platform for compiling and bundling JavaScript and TypeScript.
A high-performance & spec-compliant JavaScript/TypeScript compiler written in Zig.
File size: 7.83 MB
| Parser | Mean | Min | Max | Ops/sec | Relative |
|---|---|---|---|---|---|
| Yuku | 49.03 ms | 45.02 ms | 102.32 ms | 20.40 ops/s | baseline |
| Acorn | 133.25 ms | 123.62 ms | 148.70 ms | 7.50 ops/s | 2.72× slower |
| Babel | 184.12 ms | 152.91 ms | 224.53 ms | 5.43 ops/s | 3.76× slower |
| Oxc | 265.42 ms | 261.03 ms | 275.68 ms | 3.77 ops/s | 5.41× slower |
| SWC | 480.21 ms | 465.34 ms | 565.78 ms | 2.08 ops/s | 9.79× slower |
File size: 2.95 MB
| Parser | Mean | Min | Max | Ops/sec | Relative |
|---|---|---|---|---|---|
| Yuku | 17.66 ms | 16.42 ms | 37.12 ms | 56.63 ops/s | baseline |
| Babel | 80.09 ms | 65.20 ms | 94.96 ms | 12.49 ops/s | 4.54× slower |
| Oxc | 82.93 ms | 81.01 ms | 90.72 ms | 12.06 ops/s | 4.70× slower |
| SWC | 157.58 ms | 154.19 ms | 197.62 ms | 6.35 ops/s | 8.92× slower |
| Acorn | Failed to parse | - | - | - | - |
File size: 0.07 MB
| Parser | Mean | Min | Max | Ops/sec | Relative |
|---|---|---|---|---|---|
| Yuku | 0.33 ms | 0.31 ms | 4.77 ms | 3038.30 ops/s | baseline |
| Acorn | 0.98 ms | 0.95 ms | 4.63 ms | 1024.94 ops/s | 2.96× slower |
| Babel | 1.35 ms | 1.14 ms | 3.45 ms | 738.32 ops/s | 4.12× slower |
| Oxc | 1.52 ms | 1.48 ms | 2.80 ms | 659.00 ops/s | 4.61× slower |
| SWC | 2.86 ms | 2.79 ms | 6.95 ms | 349.06 ops/s | 8.70× slower |
- Bun - JavaScript runtime and package manager
- Clone the repository:
git clone https://github.com/yuku-toolchain/ecmascript-parser-benchmark-js.git
cd ecmascript-parser-benchmark-js- Install dependencies:
bun install- Run benchmarks:
bun benchThis will run benchmarks on all test files. Results are saved to the result/ directory.
Each parser is benchmarked using Tinybench with warmup iterations followed by multiple timed runs. Each run measures the time to parse the source text into an AST. Source files are read from disk once and kept in memory for all iterations.
Native parsers (Oxc, SWC, Yuku) run through their respective NAPI bindings, so measured time includes the binding overhead. Pure JS parsers (Acorn, Babel) run directly in the JavaScript runtime.
Why is Oxc slower than Babel? Oxc's npm package serializes the AST to a JSON string on the Rust side, then calls JSON.parse on the JavaScript side to make it available. This overhead makes it slower in end-to-end benchmarks, even though Oxc is very fast at raw parsing speed. If you only call the parse function without accessing the result, Oxc appears faster than Babel because the program field is a getter that defers JSON.parse until access. The benchmarks above measure the time to actually obtain the full AST for all parsers.
Oxc also has an experimentalRawTransfer option that makes oxc-parser roughly 2-3x faster than the results shown above. In practice it is unusable today. It only works in Node.js, so Bun and Deno are out, and it allocates gigabytes of memory upfront for a single parse. That blows up with out-of-memory errors on many systems and falls apart when parsing files in parallel.
Why is Yuku fast? Yuku's AST is designed from the ground up to be transfer-friendly: flat, compact, and near-binary. Instead of serializing to JSON and parsing it back, the AST produced by the Zig parser can be passed to JavaScript with minimal conversion. Zig's comptime makes this safe by design. There are no multi-gigabyte allocations, only the memory the source being parsed actually needs.


