3v4l.org

run code in 200+ php & hhvm versions
Bugs & Features
<?php <?php /* * This file is part of the SensioLabsProfiler SDK package. * * (c) SensioLabs <contact@sensiolabs.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class SensioLabsProfilerProbe { private static $fileFormat = __CLASS__; private static $profiler = false; private static $outputStream; private static $flags; private static $options; private static $defaultOptions = array( 'dump_extensions' => false, 'agent_timeout' => 0.25, 'server_keys' => array( 'HTTP_HOST', 'HTTP_USER_AGENT', 'HTTPS', 'REQUEST_METHOD', 'REQUEST_URI', 'SERVER_ADDR', 'SERVER_SOFTWARE', ), 'ignored_functions' => array( 'array_map', 'array_filter', 'array_reduce', 'array_walk', 'array_walk_recursive', 'call_user_func', 'call_user_func_array', 'call_user_method', 'call_user_method_array', 'forward_static_call', 'forward_static_call_array', 'iterator_apply', ), ); public static function enable($destination, $flags = null, array $options = array()) { if (isset(self::$outputStream)) { self::disable(); } isset($flags) or $flags = UPROFILER_FLAGS_MEMORY | UPROFILER_FLAGS_CPU; $requestTime = microtime(true); if (!$destination) { return false; } if (!empty($options['mock_profile_data']) && is_array($options['mock_profile_data'])) { self::$profiler = $options['mock_profile_data']; } elseif (function_exists('uprofiler_enable')) { self::$profiler = 'uprofiler'; } elseif (function_exists('xhprof_enable')) { self::$profiler = 'xhprof'; } else { $flags = 0; if (!isset(self::$outputStream)) { user_error('Neither uprofiler nor xhprof extension is enabled'); } } $options = array_merge_recursive(self::$defaultOptions, $options); self::$flags = $flags; self::$options = $options; self::profilerEnable(); if (!self::doEnable($destination, $requestTime, $response)) { self::profilerDisable(); if (null === $response) { $response = false; } } return null !== $response ? $response : true; } public static function disable() { if (self::$outputStream) { self::onEnd('', PHP_OUTPUT_HANDLER_END); self::$outputStream = false; return true; } } private static function doEnable($h, $requestTime, &$response) { $response = null; set_error_handler(function ($type, $message, $file, $line) { throw new ErrorException($message, 0, $type, $file, $line); }); try { if (!is_resource($h)) { if (($f = strpos($h, '://')) && in_array(substr($h, 0, $f), stream_get_transports(), true)) { if ($h = stream_socket_client($h, $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT)) { stream_set_timeout($h, 0, self::$options['agent_timeout']*1000000); $f = array(null, array($h), null); if (stream_select($f[0], $f[1], $f[2], 0, self::$options['agent_timeout']*1000000)) { self::fwrite($h, 'SensioLabsProfiler-Request: '.self::$options['agent_request']."\n"); $response = fgets($h, 4096); if (0 === strpos($response, 'SensioLabsProfiler-Response: ')) { self::$options['dump_extensions'] = "SensioLabsProfiler-Options: ext\n" === fgets($h, 4096); } else { fclose($h); $h = false; if (0 !== strpos($response, 'SensioLabsProfiler-Error: ')) { $response = "SensioLabsProfiler-Error: 102 Invalid agent response ($response)"; } } } else { fclose($h); $h = false; $response = "SensioLabsProfiler-Error: 101 agent connection timeout"; } $f = false; } else { $response = "SensioLabsProfiler-Error: 101 $errstr ($errno)"; } } else { $f = sprintf('%019.6F', $requestTime).'-'; $f .= substr(str_replace(array('+', '/'), array('', ''), base64_encode(md5(mt_rand(), true))), 0, 6); $h = fopen($h.'/'.$f.'.log', 'wb'); } if (!$h) { restore_error_handler(); return false; } } // This shared lock allows readers to wait for the end of the stream stream_is_local($h) and flock($h, LOCK_SH); stream_set_write_buffer($h, 0); // Loaded extensions list helps understanding runtime behavior $extensions = array(); if (self::$profiler && self::$options['dump_extensions']) { foreach (get_loaded_extensions() as $e) { $extensions[$e] = phpversion($e); } } // Keep only keys from $_COOKIE $data = array($_COOKIE, array()); array_walk_recursive($data, function (&$v) {$v = strlen($v);}); foreach (self::$options['server_keys'] as $e) { if (isset($_SERVER[$e])) { $data[1][$e] = $_SERVER[$e]; } } if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) { $e = $_SERVER['HTTP_X_ORIGINAL_URL']; } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { $e = $_SERVER['HTTP_X_REWRITE_URL']; } elseif (!empty($_SERVER['IIS_WasUrlRewritten']) && !empty($_SERVER['UNENCODED_URL'])) { $e = $_SERVER['UNENCODED_URL']; } elseif (isset($_SERVER['REQUEST_URI'][0])) { $e = $_SERVER['REQUEST_URI']; if ('/' !== $e[0]) { $e = preg_replace('#^https?://[^/]+#', '', $e); } } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { $e = $_SERVER['ORIG_PATH_INFO']; if (!empty($_SERVER['QUERY_STRING'])) { $e .= '?'.$_SERVER['QUERY_STRING']; } } else { $e = ''; } if (!empty($e)) { $data[1]['REQUEST_URI'] = $e; } $data = 'file-format: '.self::$fileFormat."\n" .'request-mu: '.memory_get_usage(true)."\n" .'request-pmu: '.memory_get_peak_usage(true)."\n" .'request-start: '.$requestTime."\n" .'php-os: '.PHP_OS."\n" .'php-sapi: '.PHP_SAPI."\n" .'php-version: '.PHP_VERSION_ID."\n" // json_encode would loose non-UTF8 data .'php-extensions: '.base64_encode(serialize($extensions))."\n" .'_COOKIE: '.base64_encode(serialize($data[0]))."\n" .'_SERVER: '.base64_encode(serialize($data[1]))."\n"; $e = set_error_handler('var_dump'); restore_error_handler(); restore_error_handler(); $data .= self::getErrorHandler('error', array(__CLASS__, 'onError')) .self::getErrorHandler('exception', array(__CLASS__, 'onException')); set_error_handler($e); if (self::$profiler && function_exists('sys_getloadavg')) { $data .= 'sys-load-avg: '.implode(' ', sys_getloadavg())."\n"; } $data .= "\nmain()//1 0 0 0 0\n\n"; self::fwrite($h, $data); if (null === self::$outputStream) { register_shutdown_function(__CLASS__.'::onShutdown'); } self::$outputStream = $h; restore_error_handler(); return true; } catch (ErrorException $e) { $response = "SensioLabsProfiler-Error: 101 ".rawurlencode($e->getMessage()."\n\n".$e->getTraceAsString()); } restore_error_handler(); return self::$outputStream = false; } private static function getErrorHandler($type, $default = 'var_dump') { $s = "set_{$type}_handler"; if ($h = $s($default)) { $s = "restore_{$type}_handler"; $s(); } elseif ('var_dump' !== $default) { $h = $default; } $type .= '-handler: '; if ($h instanceof Closure) { $h = new ReflectionFunction($h); if (PHP_VERSION_ID >= 50400 && $s = $h->getClosureScopeClass()) { $h = $s->name.'::{closure}/'.$h->getStartLine().'-'.$h->getEndLine(); } else { $h = $h->name.'::'.implode('/', array_slice(explode('/', $h->getFileName()), -2)).'/'.$h->getStartLine().'-'.$h->getEndLine(); } } else { if (!is_array($h)) { if (is_object($h)) { $h = array($h, '__invoke'); } else { $h = explode('::', $h, 2); } } if (isset($h[1])) { $h = new ReflectionMethod($h[0], $h[1]); $h = $h->getDeclaringClass()->name.'::'.$h->name; } else { $h = $h[0]; } } $type .= "$h\n"; return $type; } private static function profilerEnable() { if (is_string(self::$profiler)) { $p = self::$profiler.'_enable'; return $p(self::$flags, self::$options); } } private static function profilerDisable() { if (is_string(self::$profiler)) { $p = self::$profiler.'_disable'; return $p(); } elseif (is_array(self::$profiler)) { return self::$profiler; } else { return array(); } } private static function profilerWrite($disable, $chunk = '') { set_error_handler('var_dump', 0); $e = error_reporting(81); $data = self::profilerDisable(); if (!$disable) { self::profilerEnable(); } $h = self::$outputStream; $chunk .= "\n"; $i = 50; // 50 ~= 4Ko chunks // Speed optimized paths if (!$data) { // No-op } elseif ((UPROFILER_FLAGS_CPU & self::$flags) && (UPROFILER_FLAGS_MEMORY & self::$flags)) { foreach ($data as $k => $v) { $chunk .= "{$k}//{$v['ct']} {$v['wt']} {$v['cpu']} {$v['mu']} {$v['pmu']}\n"; if (0 === --$i) { self::fwrite($h, $chunk); $chunk = ''; $i = 50; } } } elseif (UPROFILER_FLAGS_MEMORY & self::$flags) { foreach ($data as $k => $v) { $chunk .= "{$k}//{$v['ct']} {$v['wt']} 0 {$v['mu']} {$v['pmu']}\n"; if (0 === --$i) { self::fwrite($h, $chunk); $chunk = ''; $i = 50; } } } elseif (UPROFILER_FLAGS_CPU & self::$flags) { foreach ($data as $k => $v) { $chunk .= "{$k}//{$v['ct']} {$v['wt']} {$v['cpu']} 0 0\n"; if (0 === --$i) { self::fwrite($h, $chunk); $chunk = ''; $i = 50; } } } else { foreach ($data as $k => $v) { $chunk .= "{$k}//{$v['ct']} {$v['wt']} 0 0 0\n"; if (0 === --$i) { self::fwrite($h, $chunk); $chunk = ''; $i = 50; } } } if (isset($data['main()'])) { $chunk .= "main()//-{$data['main()']['ct']} 0 0 0 0\n"; } $chunk .= "\nrequest-end: ".microtime(true) ."\nrequest-mu: ".memory_get_usage(true) ."\nrequest-pmu: ".memory_get_peak_usage(true) ."\n"; $h = self::fwrite($h, $chunk); error_reporting($e); restore_error_handler(); return $h; } private static function fwrite($stream, $data) { $len = strlen($data); $written = fwrite($stream, $data); if (false !== $written) { while ($written < $len) { fflush($stream); $w = fwrite($stream, substr($data, $written)); $written += $w ?: $len + 1; } if ($written === $len) { return true; } } } /** * @internal */ public static function onError() { return false; // Delegate error handling to the internal handler, but adds a line in profiler's data } /** * @internal */ public static function onException($e) { // Rethrow only, but adds a line in profiler's data if ('xhprof' === self::$profiler && PHP_VERSION_ID >= 50500) { self::profilerWrite(true); // Prevents a crash with XHProf } throw $e; } /** * @internal */ public static function onShutdown() { // Get and write data now so that any later fatal error // do not prevent collecting what we already have. if (!self::$outputStream) { return; } $e = error_get_last(); register_shutdown_function(__CLASS__.'::onShutdownTail'); $extra = array(); foreach (headers_list() as $data) { $data = explode(': ', $data, 2); switch ($data[0]) { case 'X-Powered-By': continue 2; case 'Set-Cookie': $data[1] = preg_replace('/=.+?;/', '=[...];', $data[1]); } $extra[] = implode(': ', $data); } $extra = 'response-headers: '.base64_encode(serialize($extra))."\n" .(function_exists('http_response_code') ? 'response-code: '.http_response_code()."\n" : '') .self::getErrorHandler('error') .self::getErrorHandler('exception'); if (self::$profiler) { if (isset($e['type'])) { switch ($e['type']) { case E_ERROR: case E_PARSE: case E_USER_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_RECOVERABLE_ERROR: $data = explode("\r", $e['message'], 2); $data = explode("\n", $data[0], 2); $data[1] = " in {$e['file']}:{$e['line']}"; $data[0] = str_replace($data[1], '', $data[0]); $extra .= "fatal-error: {$data[0]}{$data[1]}\n"; break; } } } self::profilerWrite(false, $extra); } /** * @internal */ public static function onShutdownTail() { // Cleanup remaining output buffers as much as possible $l = ob_get_level(); while ($l-- && ($s = ob_get_status()) && (!empty($s['del']) || (isset($s['flags']) && ($s['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE))) ) { if (!isset($s['flags']) || ($s['flags'] & PHP_OUTPUT_HANDLER_FLUSHABLE)) { ob_end_flush(); } elseif ($s['flags'] & PHP_OUTPUT_HANDLER_CLEANABLE) { ob_end_clean(); } else { break; } } ob_start(__CLASS__.'::onEnd', 4096); } /** * @internal */ public static function onEnd($buffer, $mode) { if (PHP_OUTPUT_HANDLER_END & $mode) { if (self::profilerWrite(true)) { stream_is_local(self::$outputStream) and flock(self::$outputStream, LOCK_UN); fclose(self::$outputStream); } } return $buffer; } }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).
Note: hhvm uses a JIT which only kicks in after a few runs. Since we run scripts only once, hhvm always runs slower.

VersionSystem time (s)User time (s)Memory (MiB)
5.4.310.0100.03312.49
5.4.300.0080.03712.50
5.4.290.0030.04012.49
5.4.280.0060.03512.39
5.4.270.0050.03712.39
5.4.260.0070.03612.39
5.4.250.0080.03612.39
5.4.240.0050.03812.39
5.4.230.0030.04112.38
5.4.220.0090.03212.38
5.4.210.0050.03612.38
5.4.200.0070.03712.38
5.4.190.0070.03512.38
5.4.180.0030.03912.38
5.4.170.0070.03412.39
5.4.160.0060.03712.38
5.4.150.0050.03712.38
5.4.140.0080.03812.07
5.4.130.0040.03812.05
5.4.120.0070.03512.02
5.4.110.0030.03812.01
5.4.100.0090.03112.01
5.4.90.0040.03812.01
5.4.80.0050.03712.01
5.4.70.0060.03512.01
5.4.60.0040.04212.01
5.4.50.0030.03712.01
5.4.40.0050.03612.00
5.4.30.0100.03511.99
5.4.20.0030.03811.98
5.4.10.0070.03411.99
5.4.00.0070.03511.49
5.3.290.0060.03812.80
5.3.280.0060.04012.71
5.3.270.0040.04312.72
5.3.260.0060.04512.72
5.3.250.0110.03912.72
5.3.240.0130.03412.72
5.3.230.0080.03512.71
5.3.220.0060.03812.68
5.3.210.0110.04012.68
5.3.200.0110.04712.68
5.3.190.0100.03712.68
5.3.180.0060.03712.67
5.3.170.0030.03912.67
5.3.160.0030.03912.68
5.3.150.0060.04312.67
5.3.140.0060.03912.66
5.3.130.0070.03912.66
5.3.120.0060.04012.66
5.3.110.0050.04012.65
5.3.100.0070.03612.12
5.3.90.0070.03512.08
5.3.80.0070.04212.07
5.3.70.0080.04712.07
5.3.60.0050.03812.06
5.3.50.0080.03612.00
5.3.40.0070.03512.00
5.3.30.0070.03311.95
5.3.20.0060.03511.73
5.3.10.0080.03911.70
5.3.00.0090.03311.68
5.2.170.0050.0319.19
5.2.160.0040.0309.19
5.2.150.0040.0339.19
5.2.140.0060.0299.19
5.2.130.0070.0279.14
5.2.120.0040.0299.15
5.2.110.0040.0309.15
5.2.100.0060.0319.15
5.2.90.0030.0309.15
5.2.80.0080.0279.14
5.2.70.0030.0319.14
5.2.60.0050.0379.10
5.2.50.0070.0299.07
5.2.40.0050.0289.04
5.2.30.0040.0349.02
5.2.20.0050.0299.01
5.2.10.0050.0278.93
5.2.00.0030.0308.79
5.1.60.0040.0278.07
5.1.50.0040.0258.07
5.1.40.0050.0298.05
5.1.30.0030.0298.41
5.1.20.0070.0268.43
5.1.10.0040.0298.14
5.1.00.0070.0258.15
5.0.50.0020.0236.63
5.0.40.0030.0266.48
5.0.30.0050.0296.30
5.0.20.0020.0216.28
5.0.10.0080.0226.25
5.0.00.0040.0336.23
4.4.90.0050.0134.78
4.4.80.0030.0144.75
4.4.70.0010.0174.76
4.4.60.0010.0224.76
4.4.50.0030.0194.77
4.4.40.0060.0324.71
4.4.30.0070.0114.76
4.4.20.0030.0154.84
4.4.10.0030.0154.85
4.4.00.0050.0234.76
4.3.110.0030.0184.67
4.3.100.0030.0144.66
4.3.90.0040.0164.63
4.3.80.0030.0254.58
4.3.70.0050.0134.63
4.3.60.0030.0144.63
4.3.50.0040.0224.63
4.3.40.0040.0274.54
4.3.30.0020.0203.29
4.3.20.0030.0263.27
4.3.10.0030.0203.22
4.3.00.0000.0236.80