dispatch(new TestRequest($method, $path))->body(); } catch (RouteNotFoundException) { return null; } } function benchMs(float $start): float { return (microtime(true) - $start) * 1000; } echo "miniroute benchmark\n"; echo str_repeat('-', 64) . "\n"; // ── Realistic table: registration + 2000 dispatches ──────────────────────── $resolver = new FakeResolver(); $resolver->bind(RealisticPublicController::class, new RealisticPublicController()); $resolver->bind(RealisticAdminController::class, new RealisticAdminController()); $resolver->bind(AdminLoggingMiddleware::class, new AdminLoggingMiddleware(new ArrayObject())); $resolver->bind(CsrfLoggingMiddleware::class, new CsrfLoggingMiddleware(new ArrayObject())); $real = new Router($resolver); $real->group('/admin', [AdminLoggingMiddleware::class]); $real->group('/admin', [CsrfLoggingMiddleware::class], ['POST']); $start = microtime(true); $real->registerController(RealisticPublicController::class); $real->registerController(RealisticAdminController::class); $regMs = benchMs($start); $paths = ['/entries', '/entries/hello-world', '/notes/42', '/admin', '/admin/notes', '/admin/entries/preview', '/feed.xml', '/robots.txt', '/sitemap.xml']; $start = microtime(true); for ($i = 0; $i < 2000; $i++) { benchHit($real, 'GET', $paths[$i % count($paths)]); } $dispatchMs = benchMs($start); printf("realistic (22 routes): register = %8.3fms | 2000 dispatches = %8.2fms (%0.5fms each)\n", $regMs, $dispatchMs, $dispatchMs / 2000); // ── Scaling: synthetic routes at 100 / 300 / 600 ─────────────────────────── printf("\n%-22s %-20s %s\n", 'routes', 'register', 'leaf dispatch (each)'); foreach ([100, 300, 600] as $n) { $resolver = new FakeResolver(); $bench = new Router($resolver); $start = microtime(true); for ($i = 0; $i < $n; $i++) { $class = 'BenchRoute' . $n . '_' . $i; eval('final class ' . $class . ' { #[' . Get::class . '("/bench/' . $n . '/' . $i . '")] public function run(): ' . ResponseInterface::class . ' { return new ' . TestResponse::class . '(200, "b"); } }'); $resolver->bind($class, new $class()); $bench->registerController($class); } $regMs = benchMs($start); $start = microtime(true); for ($i = 0; $i < 200; $i++) { benchHit($bench, 'GET', '/bench/' . $n . '/' . ($n - 1)); } $dispatchMs = benchMs($start) / 200; printf("%-22d %8.1fms %s %0.5fms\n", $n, $regMs, str_repeat(' ', 11), $dispatchMs); } echo str_repeat('-', 64) . "\n";