@ 2014-08-18T08:31:40Z <?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;
}
}
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
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).
Version System time (s) User time (s) Memory (MiB) 5.4.31 0.010 0.033 12.49 5.4.30 0.008 0.037 12.50 5.4.29 0.003 0.040 12.49 5.4.28 0.006 0.035 12.39 5.4.27 0.005 0.037 12.39 5.4.26 0.007 0.036 12.39 5.4.25 0.008 0.036 12.39 5.4.24 0.005 0.038 12.39 5.4.23 0.003 0.041 12.38 5.4.22 0.009 0.032 12.38 5.4.21 0.005 0.036 12.38 5.4.20 0.007 0.037 12.38 5.4.19 0.007 0.035 12.38 5.4.18 0.003 0.039 12.38 5.4.17 0.007 0.034 12.39 5.4.16 0.006 0.037 12.38 5.4.15 0.005 0.037 12.38 5.4.14 0.008 0.038 12.07 5.4.13 0.004 0.038 12.05 5.4.12 0.007 0.035 12.02 5.4.11 0.003 0.038 12.01 5.4.10 0.009 0.031 12.01 5.4.9 0.004 0.038 12.01 5.4.8 0.005 0.037 12.01 5.4.7 0.006 0.035 12.01 5.4.6 0.004 0.042 12.01 5.4.5 0.003 0.037 12.01 5.4.4 0.005 0.036 12.00 5.4.3 0.010 0.035 11.99 5.4.2 0.003 0.038 11.98 5.4.1 0.007 0.034 11.99 5.4.0 0.007 0.035 11.49 5.3.29 0.006 0.038 12.80 5.3.28 0.006 0.040 12.71 5.3.27 0.004 0.043 12.72 5.3.26 0.006 0.045 12.72 5.3.25 0.011 0.039 12.72 5.3.24 0.013 0.034 12.72 5.3.23 0.008 0.035 12.71 5.3.22 0.006 0.038 12.68 5.3.21 0.011 0.040 12.68 5.3.20 0.011 0.047 12.68 5.3.19 0.010 0.037 12.68 5.3.18 0.006 0.037 12.67 5.3.17 0.003 0.039 12.67 5.3.16 0.003 0.039 12.68 5.3.15 0.006 0.043 12.67 5.3.14 0.006 0.039 12.66 5.3.13 0.007 0.039 12.66 5.3.12 0.006 0.040 12.66 5.3.11 0.005 0.040 12.65 5.3.10 0.007 0.036 12.12 5.3.9 0.007 0.035 12.08 5.3.8 0.007 0.042 12.07 5.3.7 0.008 0.047 12.07 5.3.6 0.005 0.038 12.06 5.3.5 0.008 0.036 12.00 5.3.4 0.007 0.035 12.00 5.3.3 0.007 0.033 11.95 5.3.2 0.006 0.035 11.73 5.3.1 0.008 0.039 11.70 5.3.0 0.009 0.033 11.68 5.2.17 0.005 0.031 9.19 5.2.16 0.004 0.030 9.19 5.2.15 0.004 0.033 9.19 5.2.14 0.006 0.029 9.19 5.2.13 0.007 0.027 9.14 5.2.12 0.004 0.029 9.15 5.2.11 0.004 0.030 9.15 5.2.10 0.006 0.031 9.15 5.2.9 0.003 0.030 9.15 5.2.8 0.008 0.027 9.14 5.2.7 0.003 0.031 9.14 5.2.6 0.005 0.037 9.10 5.2.5 0.007 0.029 9.07 5.2.4 0.005 0.028 9.04 5.2.3 0.004 0.034 9.02 5.2.2 0.005 0.029 9.01 5.2.1 0.005 0.027 8.93 5.2.0 0.003 0.030 8.79 5.1.6 0.004 0.027 8.07 5.1.5 0.004 0.025 8.07 5.1.4 0.005 0.029 8.05 5.1.3 0.003 0.029 8.41 5.1.2 0.007 0.026 8.43 5.1.1 0.004 0.029 8.14 5.1.0 0.007 0.025 8.15 5.0.5 0.002 0.023 6.63 5.0.4 0.003 0.026 6.48 5.0.3 0.005 0.029 6.30 5.0.2 0.002 0.021 6.28 5.0.1 0.008 0.022 6.25 5.0.0 0.004 0.033 6.23 4.4.9 0.005 0.013 4.78 4.4.8 0.003 0.014 4.75 4.4.7 0.001 0.017 4.76 4.4.6 0.001 0.022 4.76 4.4.5 0.003 0.019 4.77 4.4.4 0.006 0.032 4.71 4.4.3 0.007 0.011 4.76 4.4.2 0.003 0.015 4.84 4.4.1 0.003 0.015 4.85 4.4.0 0.005 0.023 4.76 4.3.11 0.003 0.018 4.67 4.3.10 0.003 0.014 4.66 4.3.9 0.004 0.016 4.63 4.3.8 0.003 0.025 4.58 4.3.7 0.005 0.013 4.63 4.3.6 0.003 0.014 4.63 4.3.5 0.004 0.022 4.63 4.3.4 0.004 0.027 4.54 4.3.3 0.002 0.020 3.29 4.3.2 0.003 0.026 3.27 4.3.1 0.003 0.020 3.22 4.3.0 0.000 0.023 6.80
preferences:dark mode live preview
180.45 ms | 1386 KiB | 7 Q