3v4l.org

run code in 300+ PHP versions simultaneously
<?php class Bench { protected $functions = []; protected $cli; public function __construct($cli = false) { $this->cli = $cli; } public function add($label, \Closure $function) { $this->functions[] = [$label, $function]; } public function run($count) { $function = function () {}; $stats = $this->getStats(); for ($i = $count; $i--;) $function(); $stats2 = $this->getStats(); $timeDiff = $stats2[4] - $stats[4]; $this->printStats('Empty test (delta time subtracted from subsequent test)', $stats, $stats2, 0); // TODO: Split runs in pieces and interleave, to avoid bias with first/last runner. foreach ($this->functions as list($label, $function)) { $stats = $this->getStats(); for ($i = $count; $i--;) $function(); $stats2 = $this->getStats(); $this->printStats($label, $stats, $stats2, $timeDiff); } } protected function getStats() { return [memory_get_usage(), memory_get_usage(true), memory_get_peak_usage(), memory_get_peak_usage(true), microtime(1)]; } protected function printStats($label, $stats1, $stats2, $timeDiff) { list($mem, $memReal, $memPeak, $memRealPeak, $time) = $stats1; list($memNew, $memRealNew, $memPeakNew, $memRealPeakNew, $timeNew) = $stats2; $nl = "\n"; $labelLength = 20; $resultsLength = 15; // TODO: Better CLI support. Machine data export. if (PHP_SAPI === 'CLI') { ob_start(); } echo '<p><b>' . $label . '</b></p>' . $nl; echo '<code><p>' . $nl; echo str_pad('Memory', $labelLength, '.', STR_PAD_RIGHT); echo str_pad(number_format(($memNew - $mem) >> 10, 0), $resultsLength, '.', STR_PAD_LEFT) . ' kb<br>' . $nl; echo str_pad('Memory Real', $labelLength, '.', STR_PAD_RIGHT); echo str_pad(number_format(($memRealNew - $memReal) >> 10, 0), $resultsLength, '.', STR_PAD_LEFT) . ' kb<br>' . $nl; echo str_pad('Memory Peak', $labelLength, '.', STR_PAD_RIGHT); echo str_pad(number_format(($memPeakNew - $memPeak) >> 10, 0), $resultsLength, '.', STR_PAD_LEFT) . ' kb<br>' . $nl; echo str_pad('Memory Real Peak', $labelLength, '.', STR_PAD_RIGHT); echo str_pad(number_format(($memRealPeakNew - $memRealPeak) >> 10, 0), $resultsLength, '.', STR_PAD_LEFT) . ' kb<br>' . $nl; echo str_pad('Time', $labelLength, '.', STR_PAD_RIGHT); echo str_pad(number_format($timeNew - $time - $timeDiff, 5), $resultsLength, '.', STR_PAD_LEFT); echo ' sec' . $nl . '</code></p>' . $nl . $nl; if (PHP_SAPI === 'CLI') { $content = ob_end_clean(); echo preg_replace('/<.*?>/', '', $content); } } } class Log { private $has = []; // TODO: Can be replaced with a bitmask. private $events = []; public function __construct() { } /* (non-PHPdoc) * @see \Solver\Logging\Log::log() */ public function log(array $event) { $type = $event['type']; if (!isset($this->has[$type])) $this->has[$type] = true; $this->events[] = $event; } /* (non-PHPdoc) * @see \Solver\Logging\MemoryLog::getEvents() */ public function getEvents($types = null) { if ($types === null || !$this->events) { return $this->events; } else { $types = array_flip($types); // Special optimized case: the given $types mask matches or is a superset of the event types we have. $optimized = true; foreach ($this->has as $key => $val) if (!isset($types[$key])) { $optimized = false; break; } if ($optimized) { return $this->events; } else { $events = []; foreach ($this->events as $event) if (isset($types[$event['type']])) $events[] = $event; return $events; } } } /* (non-PHPdoc) * @see \Solver\Logging\MemoryLog::hasEvents() */ public function hasEvents($types = null) { if ($types === null) { return (bool) $this->has; } else { foreach ($types as $type) if (isset($this->has[$type])) return true; return false; } } /* (non-PHPdoc) * @see \Solver\Logging\ErrorMemoryLog::getErrors() */ public function getErrors() { return $this->getEvents(['error']); } /* (non-PHPdoc) * @see \Solver\Logging\ErrorMemoryLog::hasErrors() */ public function hasErrors() { $o = $this->hasEvents(['error']); $this->events = []; $this->has = []; return $o; } /* (non-PHPdoc) * @see \Solver\Logging\ErrorLog::error() */ public function error($path = null, $message = null, $code = null, array $details = null) { $event = ['type' => 'error']; if (isset($path)) $event['path'] = $path; if (isset($message)) $event['message'] = $message; if (isset($code)) $event['code'] = $code; if (isset($details)) $event['details'] = $details; $this->log($event); } } $log = new Log(); $be = new Bench(true); $be2 = new Bench(); $error = new stdClass(); $a = 0; $b = 0; $be->add('Sentinel', function () use ($error, & $a, & $b) { $x = function ($error) { return mt_rand(0, 1) ? 123 : $error; }; $result = $x($error); if ($result === $error) { $a ++; } else { $b ++; } }); $be->add('Tuple', function () use (& $a, & $b) { $x = function () { return mt_rand(0, 1) ? [true, 123] : [false, null]; }; list($error, $result) = $x(); if ($error) { $a ++; } else { $b ++; } }); $be->add('Exception', function () use (& $a, & $b) { $x = function () { if (mt_rand(0, 1)) throw new \Exception(); return 123; }; try { $result = $x(); $a ++; } catch (\Exception $e) { $b ++; } }); $be->add('Log', function () use ($log, & $a, & $b) { $x = function ($log) { if (mt_rand(0, 1)) { $log->error(); return null; } else { return 123; } }; $result = $x($log); if ($log->hasErrors()) { $a ++; } else { $b ++; } }); if (PHP_VERSION === '7.0.0RC4') $be->run(200000); var_dump($a); var_dump($b);

preferences:
35.16 ms | 402 KiB | 5 Q