- 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.
257 lines
7.3 KiB
PHP
257 lines
7.3 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\Cache\Cache;
|
|
use App\Framework\Cache\CacheKey;
|
|
use App\Framework\Cache\CacheItem;
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
use Tests\Performance\PerformanceTestCase;
|
|
use Tests\Performance\PerformanceBenchmarkResult;
|
|
|
|
/**
|
|
* Performance benchmarks for caching system
|
|
*
|
|
* Tests cache performance including:
|
|
* - Get/Set operations
|
|
* - Batch operations
|
|
* - Cache miss handling
|
|
* - Different data sizes
|
|
*/
|
|
final readonly class CacheBenchmark extends PerformanceTestCase
|
|
{
|
|
public function __construct(
|
|
PerformanceCollectorInterface $collector,
|
|
private Cache $cache
|
|
) {
|
|
parent::__construct($collector);
|
|
}
|
|
|
|
/**
|
|
* Benchmark simple cache SET operation
|
|
*/
|
|
public function benchmarkCacheSet(): PerformanceBenchmarkResult
|
|
{
|
|
$key = CacheKey::fromString('benchmark_test');
|
|
$ttl = Duration::fromMinutes(5);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->set(
|
|
CacheItem::forSetting($key, 'test_value', $ttl)
|
|
),
|
|
iterations: 10000,
|
|
name: 'Cache SET'
|
|
);
|
|
|
|
// Cache SET should be very fast
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.5);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark simple cache GET operation
|
|
*/
|
|
public function benchmarkCacheGet(): PerformanceBenchmarkResult
|
|
{
|
|
// Warmup: Set a value first
|
|
$key = CacheKey::fromString('benchmark_get_test');
|
|
$this->cache->set(
|
|
CacheItem::forSetting($key, 'test_value', Duration::fromHours(1))
|
|
);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->get($key),
|
|
iterations: 10000,
|
|
name: 'Cache GET (hit)'
|
|
);
|
|
|
|
// Cache GET should be extremely fast
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.2);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark cache GET operation (miss)
|
|
*/
|
|
public function benchmarkCacheGetMiss(): PerformanceBenchmarkResult
|
|
{
|
|
$key = CacheKey::fromString('non_existent_key');
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->get($key),
|
|
iterations: 10000,
|
|
name: 'Cache GET (miss)'
|
|
);
|
|
|
|
// Cache miss should still be fast
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.3);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark cache remember pattern
|
|
*/
|
|
public function benchmarkCacheRemember(): PerformanceBenchmarkResult
|
|
{
|
|
$key = CacheKey::fromString('benchmark_remember');
|
|
$ttl = Duration::fromMinutes(10);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->remember(
|
|
key: $key,
|
|
callback: fn() => ['computed' => 'value'],
|
|
ttl: $ttl
|
|
),
|
|
iterations: 5000,
|
|
name: 'Cache Remember Pattern'
|
|
);
|
|
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 1.0);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark batch cache SET operations
|
|
*/
|
|
public function benchmarkBatchSet(): PerformanceBenchmarkResult
|
|
{
|
|
$items = [];
|
|
for ($i = 0; $i < 100; $i++) {
|
|
$items[] = CacheItem::forSetting(
|
|
key: CacheKey::fromString("batch_key_{$i}"),
|
|
value: "value_{$i}",
|
|
ttl: Duration::fromMinutes(5)
|
|
);
|
|
}
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->set(...$items),
|
|
iterations: 100,
|
|
name: 'Batch SET (100 items)'
|
|
);
|
|
|
|
// Batch operations should be efficient
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 20.0);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark cache SET with large data
|
|
*/
|
|
public function benchmarkSetLargeData(): PerformanceBenchmarkResult
|
|
{
|
|
// Generate 1MB of data
|
|
$largeData = str_repeat('A', 1024 * 1024);
|
|
$key = CacheKey::fromString('large_data_key');
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->set(
|
|
CacheItem::forSetting($key, $largeData, Duration::fromMinutes(5))
|
|
),
|
|
iterations: 100,
|
|
name: 'Cache SET (1MB data)'
|
|
);
|
|
|
|
// Large data should still be reasonably fast
|
|
$this->assertPerformanceThreshold(
|
|
$result,
|
|
maxAvgTimeMs: 10.0,
|
|
maxMemoryBytes: 5 * 1024 * 1024 // 5MB
|
|
);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark cache DELETE operation
|
|
*/
|
|
public function benchmarkCacheDelete(): PerformanceBenchmarkResult
|
|
{
|
|
// Warmup: Set values first
|
|
for ($i = 0; $i < 10; $i++) {
|
|
$key = CacheKey::fromString("delete_test_{$i}");
|
|
$this->cache->set(
|
|
CacheItem::forSetting($key, "value_{$i}", Duration::fromMinutes(5))
|
|
);
|
|
}
|
|
|
|
$counter = 0;
|
|
$result = $this->benchmark(
|
|
operation: function() use (&$counter) {
|
|
$key = CacheKey::fromString("delete_test_" . ($counter++ % 10));
|
|
$this->cache->forget($key);
|
|
},
|
|
iterations: 10000,
|
|
name: 'Cache DELETE'
|
|
);
|
|
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.5);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Benchmark cache HAS operation
|
|
*/
|
|
public function benchmarkCacheHas(): PerformanceBenchmarkResult
|
|
{
|
|
// Warmup: Set a value
|
|
$key = CacheKey::fromString('has_test');
|
|
$this->cache->set(
|
|
CacheItem::forSetting($key, 'value', Duration::fromMinutes(5))
|
|
);
|
|
|
|
$result = $this->benchmark(
|
|
operation: fn() => $this->cache->has($key),
|
|
iterations: 10000,
|
|
name: 'Cache HAS'
|
|
);
|
|
|
|
$this->assertPerformanceThreshold($result, maxAvgTimeMs: 0.2);
|
|
|
|
$this->recordBenchmark($result, PerformanceCategory::CACHE);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Run all cache benchmarks and return summary
|
|
*/
|
|
public function runAllBenchmarks(): array
|
|
{
|
|
return [
|
|
'cache_set' => $this->benchmarkCacheSet(),
|
|
'cache_get' => $this->benchmarkCacheGet(),
|
|
'cache_get_miss' => $this->benchmarkCacheGetMiss(),
|
|
'cache_remember' => $this->benchmarkCacheRemember(),
|
|
'batch_set' => $this->benchmarkBatchSet(),
|
|
'set_large_data' => $this->benchmarkSetLargeData(),
|
|
'cache_delete' => $this->benchmarkCacheDelete(),
|
|
'cache_has' => $this->benchmarkCacheHas(),
|
|
];
|
|
}
|
|
}
|