- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
212 lines
6.2 KiB
PHP
212 lines
6.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Performance\Benchmarks;
|
|
|
|
use App\Framework\Performance\Contracts\PerformanceCollectorInterface;
|
|
use App\Framework\Performance\PerformanceCategory;
|
|
use App\Framework\Router\HttpRouter;
|
|
use App\Framework\Http\HttpRequest;
|
|
use App\Framework\Http\Method;
|
|
use App\Framework\Http\ServerEnvironment;
|
|
use App\Framework\Http\ParsedUri;
|
|
use Tests\Performance\PerformanceTestCase;
|
|
use Tests\Performance\PerformanceBenchmarkResult;
|
|
|
|
/**
|
|
* Performance benchmarks for routing system
|
|
*
|
|
* Tests routing performance including:
|
|
* - Route matching speed
|
|
* - Parameter extraction
|
|
* - Middleware resolution
|
|
* - Static vs dynamic routes
|
|
*/
|
|
final readonly class RoutingBenchmark extends PerformanceTestCase
|
|
{
|
|
public function __construct(
|
|
PerformanceCollectorInterface $collector,
|
|
private HttpRouter $router
|
|
) {
|
|
parent::__construct($collector);
|
|
}
|
|
|
|
/**
|
|
* Benchmark static route matching (no parameters)
|
|
*/
|
|
public function benchmarkStaticRouteMatching(): PerformanceBenchmarkResult
|
|
{
|
|
$request = $this->createRequest('/api/health', Method::GET);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->router->match($request),
|
|
iterations: 10000,
|
|
name: 'Static Route Matching'
|
|
);
|
|
|
|
// Assert performance threshold: static routes should be very fast
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.1);
|
|
|
|
// Record metrics
|
|
$this->recordBenchmark($result, PerformanceCategory::ROUTING);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark dynamic route matching (with parameters)
|
|
*/
|
|
public function benchmarkDynamicRouteMatching(): PerformanceBenchmarkResult
|
|
{
|
|
$request = $this->createRequest('/api/users/123', Method::GET);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->router->match($request),
|
|
iterations: 10000,
|
|
name: 'Dynamic Route Matching'
|
|
);
|
|
|
|
// Assert performance threshold: dynamic routes can be slightly slower
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.5);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::ROUTING);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark complex route matching (multiple parameters)
|
|
*/
|
|
public function benchmarkComplexRouteMatching(): PerformanceBenchmarkResult
|
|
{
|
|
$request = $this->createRequest('/api/v1/users/123/posts/456/comments', Method::GET);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->router->match($request),
|
|
iterations: 10000,
|
|
name: 'Complex Route Matching'
|
|
);
|
|
|
|
// Assert performance threshold: complex routes with multiple params
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 1.0);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::ROUTING);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark route matching with query parameters
|
|
*/
|
|
public function benchmarkRouteWithQueryParams(): PerformanceBenchmarkResult
|
|
{
|
|
$request = $this->createRequest(
|
|
'/api/search?q=test&limit=10&offset=0&sort=name',
|
|
Method::GET
|
|
);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->router->match($request),
|
|
iterations: 10000,
|
|
name: 'Route Matching with Query Params'
|
|
);
|
|
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.2);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::ROUTING);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark route not found scenario
|
|
*/
|
|
public function benchmarkRouteNotFound(): PerformanceBenchmarkResult
|
|
{
|
|
$request = $this->createRequest('/non-existent-route', Method::GET);
|
|
|
|
$result = $this->benchmark(
|
|
operation: function() use ($request) {
|
|
try {
|
|
$this->router->match($request);
|
|
} catch (\Exception $e) {
|
|
// Expected - route not found
|
|
}
|
|
},
|
|
iterations: 10000,
|
|
name: 'Route Not Found'
|
|
);
|
|
|
|
// Route not found should still be fast (fail fast principle)
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.1);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::ROUTING);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark POST route matching
|
|
*/
|
|
public function benchmarkPostRouteMatching(): PerformanceBenchmarkResult
|
|
{
|
|
$request = $this->createRequest('/api/users', Method::POST);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->router->match($request),
|
|
iterations: 10000,
|
|
name: 'POST Route Matching'
|
|
);
|
|
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.2);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::ROUTING);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Run all routing benchmarks and return summary
|
|
*/
|
|
public function runAllBenchmarks(): array
|
|
{
|
|
return [
|
|
'static_route' => $this->benchmarkStaticRouteMatching(),
|
|
'dynamic_route' => $this->benchmarkDynamicRouteMatching(),
|
|
'complex_route' => $this->benchmarkComplexRouteMatching(),
|
|
'query_params' => $this->benchmarkRouteWithQueryParams(),
|
|
'route_not_found' => $this->benchmarkRouteNotFound(),
|
|
'post_route' => $this->benchmarkPostRouteMatching(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Helper: Create HTTP request for testing
|
|
*/
|
|
private function createRequest(string $uri, Method $method): HttpRequest
|
|
{
|
|
$parsedUri = ParsedUri::fromString('https://localhost' . $uri);
|
|
|
|
$server = new ServerEnvironment([
|
|
'REQUEST_METHOD' => $method->value,
|
|
'REQUEST_URI' => $uri,
|
|
'SERVER_NAME' => 'localhost',
|
|
'SERVER_PORT' => '443',
|
|
'HTTPS' => 'on'
|
|
]);
|
|
|
|
return new HttpRequest(
|
|
method: $method,
|
|
uri: $parsedUri,
|
|
server: $server,
|
|
headers: [],
|
|
body: '',
|
|
parsedBody: null,
|
|
queryParameters: $parsedUri->query ?? [],
|
|
cookies: [],
|
|
files: []
|
|
);
|
|
}
|
|
}
|