calculateMedian($durations); $p95Time = $this->calculatePercentile($durations, 95); $p99Time = $this->calculatePercentile($durations, 99); $avgMemory = array_sum($memoryUsages) / count($memoryUsages); $peakMemory = $endMemory - $startMemory; $operationsPerSecond = 1000 / $avgTime; return new PerformanceBenchmarkResult( name: $name, iterations: $iterations, totalTimeMs: $totalTime, avgTimeMs: $avgTime, minTimeMs: $minTime, maxTimeMs: $maxTime, medianTimeMs: $medianTime, p95TimeMs: $p95Time, p99TimeMs: $p99Time, avgMemoryBytes: (int) $avgMemory, peakMemoryBytes: $peakMemory, operationsPerSecond: $operationsPerSecond ); } /** * Assert performance meets threshold */ protected function assertPerformanceThreshold( PerformanceBenchmarkResult $result, float $maxAvgTimeMs, ?int $maxMemoryBytes = null ): void { if ($result->avgTimeMs > $maxAvgTimeMs) { throw new \RuntimeException( "Performance threshold exceeded: {$result->name} took {$result->avgTimeMs}ms (limit: {$maxAvgTimeMs}ms)" ); } if ($maxMemoryBytes !== null && $result->peakMemoryBytes > $maxMemoryBytes) { $peakMb = round($result->peakMemoryBytes / 1024 / 1024, 2); $limitMb = round($maxMemoryBytes / 1024 / 1024, 2); throw new \RuntimeException( "Memory threshold exceeded: {$result->name} used {$peakMb}MB (limit: {$limitMb}MB)" ); } } /** * Record benchmark result in performance collector */ protected function recordBenchmark( PerformanceBenchmarkResult $result, PerformanceCategory $category = PerformanceCategory::CUSTOM ): void { $this->collector->recordMetric( "benchmark_{$result->name}", $category, $result->avgTimeMs, [ 'iterations' => $result->iterations, 'min_ms' => $result->minTimeMs, 'max_ms' => $result->maxTimeMs, 'median_ms' => $result->medianTimeMs, 'p95_ms' => $result->p95TimeMs, 'p99_ms' => $result->p99TimeMs, 'ops_per_sec' => $result->operationsPerSecond, 'memory_avg_mb' => round($result->avgMemoryBytes / 1024 / 1024, 2), 'memory_peak_mb' => round($result->peakMemoryBytes / 1024 / 1024, 2) ] ); } /** * Calculate median value */ private function calculateMedian(array $values): float { sort($values); $count = count($values); $middle = floor($count / 2); if ($count % 2 === 0) { return ($values[$middle - 1] + $values[$middle]) / 2; } return $values[$middle]; } /** * Calculate percentile value */ private function calculatePercentile(array $values, int $percentile): float { sort($values); $count = count($values); $index = ceil($count * ($percentile / 100)) - 1; return $values[(int) max(0, min($index, $count - 1))]; } }