|
<?php |
|
|
|
class Benchmark |
|
{ |
|
protected $title = null; |
|
protected $startData = null; |
|
protected $reports = array(); |
|
|
|
const TEXT_FORMAT_HTML = 'html'; |
|
const TEXT_FORMAT_PlAIN = 'plain'; |
|
|
|
const DATA_FORMAT_HUMAN = 'human'; |
|
const DATA_FORMAT_PlAIN = 'plain'; |
|
|
|
/** |
|
* start the timer |
|
*/ |
|
public function __construct($title = null, $start = true) |
|
{ |
|
$this->title = $title; |
|
|
|
if ($start === true) { |
|
$this->start(); |
|
} |
|
} |
|
|
|
/** |
|
* start the benchmark |
|
*/ |
|
public function start() |
|
{ |
|
$this->startData = \BenchmarkData::createNow(); |
|
} |
|
|
|
/** |
|
* |
|
*/ |
|
public function dump($textFormat = Benchmark::TEXT_FORMAT_HTML, $dataFormat = Benchmark::DATA_FORMAT_HUMAN) |
|
{ |
|
if ($textFormat === self::TEXT_FORMAT_HTML) { |
|
echo '<pre class="benchmark-dump" dir="ltr">'; |
|
} |
|
|
|
if ($this->title) { |
|
printf("-- %-100s --\n", $this->title); |
|
} |
|
|
|
$lines = array(); |
|
$lastValue = null; |
|
|
|
$lines[] = array( |
|
array("%-30s", ''), |
|
array("%-20s", 'time'), |
|
array("%-20s", 'memory'), |
|
array("%-20s", 'rmemory'), |
|
array("%-20s", 'memoryPeak'), |
|
array("%-20s", 'rmemoryPeak'), |
|
); |
|
|
|
foreach ($this->reports as $report) |
|
{ |
|
$b = $report[1]; |
|
|
|
if ($dataFormat === self::DATA_FORMAT_HUMAN) { |
|
$b = $b->humanFormat(); |
|
} |
|
|
|
$lines[] = array( |
|
array("%-30s", $report[0]), |
|
array("%-20s", $dataFormat === self::DATA_FORMAT_HUMAN ? $b['time'] : $b->getTime()), |
|
array("%-20s", $dataFormat === self::DATA_FORMAT_HUMAN ? $b['memory'] : $b->getMemory()), |
|
array("%-20s", $dataFormat === self::DATA_FORMAT_HUMAN ? $b['rmemory'] : $b->getRMemory()), |
|
array("%-20s", $dataFormat === self::DATA_FORMAT_HUMAN ? $b['memoryPeak'] : $b->getMemoryPeak()), |
|
array("%-20s", $dataFormat === self::DATA_FORMAT_HUMAN ? $b['rmemoryPeak'] : $b->getRMemoryPeak()), |
|
); |
|
$lastValue = $report[1]; |
|
} |
|
|
|
foreach ($lines as $line) |
|
{ |
|
$format = array(); |
|
$output = array(); |
|
|
|
foreach ($line as $row) { |
|
$format[] = $row[0]; |
|
$output['tmp_v' . md5(uniqid())] = $row[1]; |
|
} |
|
|
|
call_user_func_array('printf', array_merge( |
|
array(implode(' ', $format) . PHP_EOL), |
|
$output |
|
)); |
|
} |
|
|
|
if ($textFormat === self::TEXT_FORMAT_HTML) { |
|
echo '</pre>'; |
|
} |
|
} |
|
|
|
/** |
|
* |
|
*/ |
|
public function report($key = null) |
|
{ |
|
if (null !== ($m = $this->getMeasure())) { |
|
$this->reports[] = array($key, $m); |
|
} |
|
} |
|
|
|
public function reportAndDump($key = null, $format = Benchmark::DATA_FORMAT_HUMAN) |
|
{ |
|
$this->report($key); |
|
$this->dump($format); |
|
} |
|
|
|
/** |
|
* Get the current benchmark value |
|
*/ |
|
public function getMeasure() |
|
{ |
|
if (! $this->startData) { |
|
return; |
|
} |
|
|
|
$b = \BenchmarkData::createNow(); |
|
return $b->sub($this->startData); |
|
} |
|
|
|
} |
|
|
|
class BenchmarkData |
|
{ |
|
private $time; |
|
private $memory; |
|
private $rmemory; |
|
private $memoryPeak; |
|
private $rmemoryPeak; |
|
|
|
/** |
|
* |
|
*/ |
|
public function __construct($time, $memory, $rmemory, $memoryPeak, $rmemoryPeak) |
|
{ |
|
$this->time = $time; |
|
$this->memory = $memory; |
|
$this->rmemory = $rmemory; |
|
$this->memoryPeak = $memoryPeak; |
|
$this->rmemoryPeak = $rmemoryPeak; |
|
} |
|
|
|
/** |
|
* |
|
*/ |
|
public static function createNow() |
|
{ |
|
$b = new static(microtime(true), memory_get_usage(), memory_get_usage(true), memory_get_peak_usage(), memory_get_peak_usage(true)); |
|
|
|
return $b; |
|
} |
|
|
|
public function getTime() { |
|
return $this->time; |
|
} |
|
public function getMemory() { |
|
return $this->memory; |
|
} |
|
public function getRMemory() { |
|
return $this->rmemory; |
|
} |
|
public function getMemoryPeak() { |
|
return $this->memoryPeak; |
|
} |
|
public function getRMemoryPeak() { |
|
return $this->rmemoryPeak; |
|
} |
|
|
|
/** |
|
* |
|
*/ |
|
public function sub(BenchmarkData $b) |
|
{ |
|
$this->time -= $b->time; |
|
$this->memory -= $b->memory; |
|
$this->rmemory -= $b->rmemory; |
|
$this->memoryPeak -= $b->memoryPeak; |
|
$this->rmemoryPeak -= $b->rmemoryPeak; |
|
|
|
return $this; |
|
} |
|
|
|
/** |
|
* |
|
*/ |
|
public function humanFormat() |
|
{ |
|
return array( |
|
'time' => round($this->time, 4) . ' s', |
|
|
|
'memory' => $this->formatBytes($this->memory), |
|
'rmemory' => $this->formatBytes($this->rmemory), |
|
|
|
'memoryPeak' => $this->formatBytes($this->memoryPeak), |
|
'rmemoryPeak' => $this->formatBytes($this->rmemoryPeak), |
|
); |
|
} |
|
|
|
/** |
|
* |
|
*/ |
|
private function formatBytes($bytes, $precision = 2) |
|
{ |
|
$units = array('B', 'KB', 'MB', 'GB', 'TB'); |
|
|
|
$bytes = max($bytes, 0); |
|
$pow = floor(($bytes ? log($bytes) : 0) / log(1024)); |
|
$pow = min($pow, count($units) - 1); |
|
|
|
// Uncomment one of the following alternatives |
|
$bytes /= pow(1024, $pow); |
|
// $bytes /= (1 << (10 * $pow)); |
|
|
|
return round($bytes, $precision) . ' ' . $units[$pow]; |
|
} |
|
} |