138 lines
3.6 KiB
PHP
138 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace PHPNative\Framework;
|
|
|
|
class Profiler
|
|
{
|
|
private static array $timings = [];
|
|
private static array $counters = [];
|
|
private static bool $enabled = false;
|
|
private static float $lastReportTime = 0;
|
|
private static float $reportInterval = 2.0; // Report every 2 seconds
|
|
|
|
public static function enable(): void
|
|
{
|
|
self::$enabled = true;
|
|
self::$lastReportTime = microtime(true);
|
|
}
|
|
|
|
public static function disable(): void
|
|
{
|
|
self::$enabled = false;
|
|
}
|
|
|
|
public static function isEnabled(): bool
|
|
{
|
|
return self::$enabled;
|
|
}
|
|
|
|
public static function start(string $label): void
|
|
{
|
|
if (!self::$enabled) {
|
|
return;
|
|
}
|
|
|
|
if (!isset(self::$timings[$label])) {
|
|
self::$timings[$label] = [
|
|
'total' => 0.0,
|
|
'count' => 0,
|
|
'min' => PHP_FLOAT_MAX,
|
|
'max' => 0.0,
|
|
'start' => null,
|
|
];
|
|
}
|
|
|
|
self::$timings[$label]['start'] = microtime(true);
|
|
}
|
|
|
|
public static function end(string $label): void
|
|
{
|
|
if (!self::$enabled) {
|
|
return;
|
|
}
|
|
|
|
if (!isset(self::$timings[$label]) || self::$timings[$label]['start'] === null) {
|
|
return;
|
|
}
|
|
|
|
$duration = microtime(true) - self::$timings[$label]['start'];
|
|
self::$timings[$label]['total'] += $duration;
|
|
self::$timings[$label]['count']++;
|
|
self::$timings[$label]['min'] = min(self::$timings[$label]['min'], $duration);
|
|
self::$timings[$label]['max'] = max(self::$timings[$label]['max'], $duration);
|
|
self::$timings[$label]['start'] = null;
|
|
}
|
|
|
|
public static function increment(string $label, int $amount = 1): void
|
|
{
|
|
if (!self::$enabled) {
|
|
return;
|
|
}
|
|
|
|
if (!isset(self::$counters[$label])) {
|
|
self::$counters[$label] = 0;
|
|
}
|
|
|
|
self::$counters[$label] += $amount;
|
|
}
|
|
|
|
public static function report(): void
|
|
{
|
|
if (!self::$enabled) {
|
|
return;
|
|
}
|
|
|
|
$now = microtime(true);
|
|
if ($now - self::$lastReportTime < self::$reportInterval) {
|
|
return;
|
|
}
|
|
|
|
echo "\n=== Performance Report ===\n";
|
|
|
|
if (!empty(self::$timings)) {
|
|
echo "\nTimings:\n";
|
|
foreach (self::$timings as $label => $data) {
|
|
if ($data['count'] === 0) {
|
|
continue;
|
|
}
|
|
|
|
$avg = $data['total'] / $data['count'];
|
|
echo sprintf(
|
|
" %s: avg=%.3fms, total=%.3fms, count=%d, min=%.3fms, max=%.3fms\n",
|
|
$label,
|
|
$avg * 1000,
|
|
$data['total'] * 1000,
|
|
$data['count'],
|
|
$data['min'] * 1000,
|
|
$data['max'] * 1000
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!empty(self::$counters)) {
|
|
echo "\nCounters:\n";
|
|
foreach (self::$counters as $label => $count) {
|
|
echo sprintf(" %s: %d\n", $label, $count);
|
|
}
|
|
}
|
|
|
|
echo "=========================\n\n";
|
|
|
|
// Reset for next interval
|
|
self::reset();
|
|
self::$lastReportTime = $now;
|
|
}
|
|
|
|
public static function reset(): void
|
|
{
|
|
foreach (self::$timings as $label => $data) {
|
|
self::$timings[$label]['total'] = 0.0;
|
|
self::$timings[$label]['count'] = 0;
|
|
self::$timings[$label]['min'] = PHP_FLOAT_MAX;
|
|
self::$timings[$label]['max'] = 0.0;
|
|
}
|
|
|
|
self::$counters = [];
|
|
}
|
|
}
|