Benchmark
How long custos and other PHP tools take on real projects, and how much memory they need. The benchmark workflow refreshes these numbers every week, with the latest release of every tool and project.
Different tools, different jobs
Type checkers infer much more than custos, linters mostly check style, and fixers rewrite code. Compare times within a kind, and read finding counts only as a sign that a tool did its work: each counts what its own rules look for.
Measured on 2026-11-08 on linux/amd64, AMD EPYC 7763 64-Core Processor, 4 cores, 16 GB of memory, with PHP 8.4.27. Each time is the median of 3 runs.
guzzle
guzzle/guzzle at 8.3.1, 74 PHP files.
| Tool | Kind | Version | Time | vs custos | Peak memory | Findings |
|---|---|---|---|---|---|---|
| Mago analyze | analyzer | 1.59.0 | 0.21 s | 0.3× | 211 MB | 584 |
| custos analyse | analyzer | 0.1.10-3-ga032132c | 0.62 s | 1.0× | 98 MB | 48 |
| Phan | analyzer | 6.0.11 | 1.47 s | 2.4× | 223 MB | 281 |
| PHPStan | analyzer | 2.3.5 | 4.79 s | 7.7× | 313 MB | 50 |
| Psalm | analyzer | 7.1.0 | 5.36 s | 8.7× | 448 MB | 172 |
| Mago lint | linter | 1.59.0 | 0.10 s | 0.2× | 163 MB | 846 |
| PHP_CodeSniffer | linter | 4.0.4 | 1.02 s | 1.7× | 96 MB | 720 |
| custos fix | fixer | 0.1.10-3-ga032132c | 0.56 s | 1.0× | 100 MB | 25 |
| PHP-CS-Fixer | fixer | 3.95.29 | 1.69 s | 3.0× | 157 MB | 0 |
| Rector | fixer | 2.8.4 | 8.55 s | 15× | 498 MB | 26 |
composer
composer/composer at 2.11.1, 321 PHP files.
| Tool | Kind | Version | Time | vs custos | Peak memory | Findings |
|---|---|---|---|---|---|---|
| Mago analyze | analyzer | 1.59.0 | 0.73 s | 0.2× | 231 MB | 5050 |
| custos analyse | analyzer | 0.1.10-3-ga032132c | 3.40 s | 1.0× | 187 MB | 757 |
| Phan | analyzer | 6.0.11 | 5.71 s | 1.7× | 547 MB | 2238 |
| PHPStan | analyzer | 2.3.5 | 11.6 s | 3.4× | 820 MB | 242 |
| Psalm | analyzer | 7.1.0 | 19.0 s | 5.6× | 1.1 GB | 1198 |
| Mago lint | linter | 1.59.0 | 0.21 s | 0.06× | 189 MB | 4757 |
| PHP_CodeSniffer | linter | 4.0.4 | 3.01 s | 0.9× | 105 MB | 10174 |
| custos fix | fixer | 0.1.10-3-ga032132c | 3.23 s | 1.0× | 201 MB | 511 |
| PHP-CS-Fixer | fixer | 3.95.29 | 6.80 s | 2.1× | 162 MB | 320 |
| Rector | fixer | 2.8.4 | 14.2 s | 4.4× | 1.9 GB | 138 |
laravel
laravel/framework at v13.40.0, 1746 PHP files.
| Tool | Kind | Version | Time | vs custos | Peak memory | Findings |
|---|---|---|---|---|---|---|
| Mago analyze | analyzer | 1.59.0 | 1.13 s | 0.1× | 392 MB | 21385 |
| custos analyse | analyzer | 0.1.10-3-ga032132c | 8.29 s | 1.0× | 654 MB | 10997 |
| Phan | analyzer | 6.0.11 | 20.0 s | 2.4× | 1.7 GB | 9102 |
| PHPStan | analyzer | 2.3.5 | 27.7 s | 3.3× | 1.6 GB | 3826 |
| Psalm | analyzer | 7.1.0 | 69.6 s | 8.4× | 3.6 GB | 7040 |
| Mago lint | linter | 1.59.0 | 0.31 s | 0.04× | 197 MB | 9047 |
| PHP_CodeSniffer | linter | 4.0.4 | 8.61 s | 1.0× | 132 MB | 9854 |
| custos fix | fixer | 0.1.10-3-ga032132c | 8.47 s | 1.0× | 692 MB | 4617 |
| PHP-CS-Fixer | fixer | 3.95.29 | 13.9 s | 1.6× | 180 MB | 446 |
| Rector | fixer | 2.8.4 | 34.6 s | 4.1× | 3.5 GB | 1325 |
Features
What each tool offers besides speed. A tool that lacks a feature may still get it from a third-party plugin; the table lists what the tool itself provides.
| Feature | custos | PHPStan | Psalm | Phan | Mago | PHP_CodeSniffer | PHP-CS-Fixer | Rector |
|---|---|---|---|---|---|---|---|---|
| Written in | Go | PHP | PHP | PHP | Rust | PHP | PHP | PHP |
| Runs without PHP | ✓ | — | — | — | ✓ | — | — | — |
| Type checking | — infers types for its rules | ✓ | ✓ | ✓ | ✓ analyze | — | — | — |
| Taint analysis | ✓ across files and into vendor/ | — | ✓ --taint-analysis | — | partial: superglobals echoed directly | — | — | — |
| Automatic fixes | ✓ custos fix | partial: --fix, experimental | ✓ psalter | partial: --automatic-fix, few issues | ✓ --fix | ✓ phpcbf | ✓ | ✓ |
| Formatting | — | — | — | — | ✓ fmt | ✓ phpcbf | ✓ | — |
| Language server | ✓ custos lsp | — | ✓ | ✓ | — planned | — | — | — |
| MCP server for AI agents | ✓ custos mcp | — | — | — | — | — | — | — |
| Baseline | ✓ | ✓ | ✓ | ✓ | ✓ | — | — | — |
| Custom rules | — | ✓ | ✓ | ✓ | ✓ | ✓ sniffs | ✓ | ✓ |
| SARIF output | ✓ | — | ✓ | — | ✓ | — | — | — |
Checked against each tool's documentation on 2026-11-08; linked cells cite it.
Method
- Every tool analyzes the project's source directories with its own configuration from
bench/configs, after the project's dependencies are installed, so that analyzers can resolve vendor symbols. - Each run starts from an empty cache, after a warm-up run that fills the operating system's file cache. Tools use their default parallelism, or every core when they have to be told.
- Peak memory sums the resident memory of the tool's processes, including its parallel workers.
- Findings: problems reported by analyzers and linters, edits
custos fixwould apply, and files other fixers would change. Fixers run in dry-run mode. - vs custos divides a tool's time by the time of the custos command of the same kind (
custos analyse, orcustos fixfor fixers). - Run it yourself with
make compare; the tools, versions and projects are listed inbench/competitors.json.
