<?php /** * Class Rendertime * * This helper class is for uncomplicated profiling of executed code. * Just place anywhere in your code: * ```php * Rendertime::start('key'); * // your code * Rendertime::end('key'); * ``` * * You can start multiple keys at the same time. The time is recorded for each key separately. * * To receive the rendertime statistics, just call: `Rendertime::getRendertime()`. */ class Rendertime { private $lastCall; private $stack = []; private $renderTimes = []; // singleton instance /** @var Rendertime */ private static $instance = null; private function __construct(float $start = 0) { $this->lastCall = ($start > 0) ? $start : microtime(true); $this->stack[] = ['other', 0]; } private function __clone() { } /** @return Rendertime */ public static function getInstance($fStartTime = 0) { if (null === self::$instance) { self::$instance = new self($fStartTime); } return self::$instance; } public static function __callStatic($name, $arguments) { return call_user_func_array([self::getInstance(), $name], $arguments); } private function start(string $key) { $now = microtime(true); $past = $now - $this->lastCall; $currentItem = &$this->stack[count($this->stack) - 1]; $currentItem[1] += $past; $this->stack[] = [$key, 0]; $this->lastCall = microtime(true); return true; } private function end(string $key) { $now = microtime(true); if (!in_array($key, array_column(array_reverse($this->stack), 0))) { return false; } $past = $now - $this->lastCall; do { $this->recordTime($past); [$currentKey] = array_pop($this->stack); $past = 0; } while ($key != $currentKey); $this->lastCall = microtime(true); return true; } private function recordTime(float $past) { [$currentKey, $value] = $this->stack[count($this->stack) - 1]; if (!isset($this->renderTimes[$currentKey])) { $this->renderTimes[$currentKey] = []; } $this->renderTimes[$currentKey][] = $value + $past; } private function getRendertime(string $key = null): array { $this->recordTime(microtime(true) - $this->lastCall); $this->lastCall = microtime(true); if (is_null($key)) { $renderTimes = array_map([$this, 'buildStatistics'], $this->renderTimes); $renderTimes['overall'] = $this->buildStatistics(array_merge(...array_values($this->renderTimes))); return $renderTimes; } else { return $this->buildStatistics($this->renderTimes[$key] ?? []); } } private function buildStatistics(array $times): array { if (empty($times)) { return ['count' => 0, 'min' => 0, 'max' => 0, 'avg' => 0, 'sum' => 0]; } $count = count($times); $min = min($times); $max = max($times); $sum = array_sum($times); $avg = $sum / $count; return compact('count', 'min', 'max', 'avg', 'sum'); } }