PHP Parser Speed Comparison 2026
Quick speed comparison of tools that parse PHP code
#php-parser-comparison
Speed comparison of PHP parsers, run automatically in CI every 12 hours.
Each parser walks the same corpus — a freshly cloned Laravel framework with all Composer dependencies installed (src/ + vendor/) — and parses every .php file. Each tool runs 5 times and the average wall-clock time is reported, along with the peak memory (resident set size) of a single run.
#Parsers
| Subproject | Parser | Language |
|---|---|---|
nikic-PHP-Parser |
nikic/php-parser v5 | PHP |
ext-ast |
php-ast extension | PHP (C ext) |
z7zmey-php-parser-dev |
z7zmey/php-parser | Go |
rector-php-parser-in-go |
rectorphp/php-parser-in-go | Go |
halleck45-go-php-parser |
halleck45/go-php-parser | Go + embedded PHP (cgo) |
mago-syntax |
mago-syntax v1.42 | Rust |
#Latest results
Each run produces two tables — every parser pinned to a single core, vs all runner cores available.
#Single core (taskset -c 0)
Rank | Parser | Avg (5 runs) | Peak mem | vs slowest 1 | nikic/php-parser (v5) | 31121 ms | 211 MB | 1.0x 2 | z7zmey/php-parser | 6266 ms | 41 MB | 5.0x 3 | rectorphp/php-parser-in-go | 5900 ms | 95 MB | 5.3x 4 | halleck45/go-php-parser | 2450 ms | 75 MB | 12.7x 5 | ext-ast | 1620 ms | 99 MB | 19.2x 6 | mago-syntax (single-threaded) | 1201 ms | 73 MB | 25.9x
#All cores
Rank | Parser | Avg (5 runs) | Peak mem | vs slowest 1 | nikic/php-parser (v5) | 30574 ms | 211 MB | 1.0x 2 | z7zmey/php-parser | 4726 ms | 39 MB | 6.5x 3 | rectorphp/php-parser-in-go | 4718 ms | 73 MB | 6.5x 4 | halleck45/go-php-parser | 1700 ms | 65 MB | 18.0x 5 | ext-ast | 1645 ms | 99 MB | 18.6x 6 | mago-syntax (parallel) | 561 ms | 159 MB | 54.5x
#Sample AST dump
Separate CI jobs (dump-*) parse one small fixture — sample-class.php, a ~25-line class — with each parser and print the resulting node tree to that job's Summary page. This shows the shape of each parser's output (each emits a different format) without wading through the full corpus. Run locally with make dump in any subproject.
Timings come from shared GitHub-hosted runners — good for rough ranking, not precise benchmarking. Live numbers appear in every run's Summary page.
Core count matters. The ubuntu-latest standard runner has only 4 vCPUs (16 GB RAM). How each parser reacts to extra cores:
mago-syntax (parallel)— the only one that actually parses files across cores. Scales ~2.1x (1201→561 ms) and stays fastest in absolute terms.nikic,ext-ast— single-threaded PHP. Single-core and all-core numbers match.halleck45,z7zmey,rectorphp/php-parser-in-go— parse sequentially, but the Go runtime (GC, scheduler, sysmon) uses extra cores anyway, so pinning to one core (taskset -c 0) slows them down. The speedup tracksGOMAXPROCS, not the workload — neither does any parallel parsing:halleck45gains the most (~1.4x: 2450→1700 ms) — Go + cgo around an embedded PHP, so more runtime/allocation work to offload.z7zmeyis pure Go with less heap churn, so its gain is smaller (~1.3x: 6266→4726 ms).rectorphp/php-parser-in-goshares the z7zmey lineage and behaves similarly (~1.25x: 5900→4718 ms).
Memory. The Go parsers are the leanest (z7zmey 39–41 MB, halleck45 65–75 MB, rectorphp/php-parser-in-go 73–95 MB); the PHP tools carry the interpreter's footprint (nikic ~211 MB, ext-ast ~99 MB). mago-syntax is tiny single-threaded (73 MB) but jumps to 159 MB in parallel mode — rayon buffering file contents across worker threads is the memory price of its speed.
Absolute numbers reflect a noisy-neighbour VM, not bare metal; only the relative ranking is meaningful, and even that can shift with runner contention.