Skip to content

Add re-runnable router benchmark vs FastRoute and Symfony Routing - #8

Merged
tylersriver merged 4 commits into
mainfrom
claude/issue-7-gk4shy
Jun 11, 2026
Merged

tylersriver merged 4 commits into
mainfrom
claude/issue-7-gk4shy

Conversation

@tylersriver

Copy link
Copy Markdown
Owner

Closes #7

What

Adds a re-runnable benchmark comparing ruta against nikic/fast-route and symfony/routing (including Symfony's compiled matcher) under various configurations, plus the measured results and an evaluation.

  • benchmark/ — standalone composer project so the comparison libraries never become dependencies of ruta itself (ruta is pulled in through a path repository). Run with cd benchmark && composer install && php run.php; flags for route counts, shapes, subjects, iterations and repeats.
  • Subjects: ruta, ruta (cached) via Ruta\cachedRouter(), FastRoute simple + cached dispatcher, Symfony UrlMatcher + CompiledUrlMatcher.
  • Methodology: deterministically generated route sets in two shapes (REST-style mixed static/dynamic, purely static) at 60/600/1200 routes; measures setup cost and per-dispatch time for static hits, dynamic hits, deep dynamic hits and misses (median of 7 repeats × 20k dispatches). Every subject is verified to actually match/miss each scenario before timing.
  • .github/workflows/benchmark.yml — manually triggerable workflow that prints the result tables to the job summary.
  • benchmark/README.md — methodology, fairness notes, full results and interpretation.

Headline results (PHP 8.4, opcache off)

  • ruta's tree lookup scales with URI depth, not route count: ~1.2 µs → ~3 µs per dispatch going from 60 to 1200 routes; misses stay ~1 µs flat on static sets.
  • FastRoute owns static hits (~0.2 µs at any size), but from 600 REST routes up ruta matches/beats it on dynamic hits and is 3–4× faster on misses.
  • Symfony's non-compiled matcher degrades linearly (100+ µs/op at 1200 routes); its compiled matcher is the strongest all-rounder at scale.
  • ruta has the cheapest cold registration (1.5 ms for 1200 routes vs 9.1 ms FastRoute), and cachedRouter() cuts setup ~3× at 600+ routes.

Note: benchmark/composer.lock is intentionally git-ignored — a path-repository lock pins ruta to the branch name it was generated on and would break composer install after merge.

https://claude.ai/code/session_01HFuiFYMtQfuPKMX4rCifzu


Generated by Claude Code

claude added 3 commits June 11, 2026 01:48
Standalone composer project in benchmark/ comparing ruta (in-memory and
cached) with nikic/fast-route (simple and cached dispatcher) and
symfony/routing (UrlMatcher and compiled matcher) across REST-style and
static route sets of configurable size, measuring setup cost and
static/dynamic/deep/not-found dispatch scenarios. Includes a manually
triggerable Benchmark workflow that prints results to the job summary.

Closes #7

https://claude.ai/code/session_01HFuiFYMtQfuPKMX4rCifzu
@tylersriver
tylersriver force-pushed the claude/issue-7-gk4shy branch from a91d2f0 to b7747ce Compare June 11, 2026 01:50
@tylersriver
tylersriver merged commit 1ffcda3 into main Jun 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Performance evaluation

2 participants