3v4l.org

run code in 300+ PHP versions simultaneously
<?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. */ /** * This is a PHP 5.2 compatible fallback implementation of the Sprofiler extension. * The interfaces and behavior are the same, or as close as possible. * It uses xhprof or uprofiler to gather profiling metrics and push them to SensioLabsProfiler. * When the extension is loaded, this PHP fallback is not loaded. * * A general rule of design is that this fallback (as the extension) does not generate any exception * nor any PHP notice/warning/etc. Instead, a log facility is provided where all messages shall be written. */ class SprofilerProbe { private $fileFormat = 'SensioLabs\Profiler\Probe'; private $profiler; private $outputUrl; private $outputTimeout; private $outputStream; private $logLevel = 1; private $logUrl = 'php://stderr'; private $isEnabled = false; private $responseLine = ''; private $challenge; private $signature; private $flags; private $options = array( 'server_keys' => array( 'HTTP_HOST', 'HTTP_USER_AGENT', 'HTTPS', 'REQUEST_METHOD', 'REQUEST_URI', 'SERVER_ADDR', 'SERVER_SOFTWARE', '_', 'argv', ), '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', ), ); private static $probe; private static $profilerIsEnabled = false; private static $defaultOutputUrl = 'unix:///var/run/sprofiler/agent.sock'; private static $urlEncMap = array( '%21' => '!', '%22' => '"', '%23' => '#', '%24' => '$', '%27' => "'", '%28' => '(', '%29' => ')', '%2A' => '*', '%2C' => ',', '%2F' => '/', '%3A' => ':', '%3B' => ';', '%3C' => '<', '%3D' => '=', '%3E' => '>', '%40' => '@', '%5B' => '[', '%5C' => '\\','%5D' => ']', '%5E' => '^', '%60' => '`', '%7B' => '{', '%7C' => '|', '%7D' => '}', '%7E' => '~', ); /** * Returns a global singleton and enables it by default. * * Uses an HTTP header or an env vars to create this singleton on its first use: * 1. the value of the X-SensioLabsProfiler-Query HTTP header (when applicable) * 2. or the SPROFILER_QUERY environment var * 3. or the empty string otherwise * is used as the first argument of the constructor below to instantiate the main probe. * * Additionally, this function enables the probe, except when the just said string * contains an auto_enable=0 URL parameter. * * @return self * * @api */ public static function getMainInstance() { if (isset($_SERVER['HTTP_X_SENSIOLABSPROFILER_QUERY'])) { $query = $_SERVER['HTTP_X_SENSIOLABSPROFILER_QUERY']; } elseif (isset($_SERVER['SPROFILER_QUERY'])) { $query = $_SERVER['SPROFILER_QUERY']; } else { $query = ''; } if (null !== self::$probe) { return self::$probe; } if (!file_exists(substr(self::$defaultOutputUrl, 7))) { self::$defaultOutputUrl = null; } $probe = new self($query); parse_str($query, $query); if (!isset($query['auto_enable']) || $query['auto_enable']) { if ($probe->isVerified()) { self::boxPostEnable($probe, $probe->enable()); $probe->debug($probe->getResponseLine()); } } return self::$probe = $probe; } /** * Instantiate a probe object. * * @param string $query An URL-encoded string that configures the probe. Part of the string is signed. * @param string $probeId An id that is given to the agent for signature impersonation. * @param string $probeToken The token associated to $probeId. * @param string $outputUrl The URL where profiles will be written (directory, socket or TCP destination). * * @api */ public function __construct($query, $probeId = null, $probeToken = null, $outputUrl = null) { $query = preg_split('/(?:^|&)signature=(.+?)(?:&|$)/', $query, 2, PREG_SPLIT_DELIM_CAPTURE); list($this->challenge, $this->signature, $args) = $query + array(1 => '', ''); $this->signature = rawurldecode($this->signature); parse_str($args, $args); $query = array( 'SPROFILER_PROBE_ID' => null, 'SPROFILER_PROBE_TOKEN' => null, 'SPROFILER_OUTPUT_URL' => null, 'SPROFILER_OUTPUT_TIMEOUT' => null, 'SPROFILER_LOG_LEVEL' => null, 'SPROFILER_LOG_URL' => null, ); foreach ($query as $k => $v) { if (isset($_ENV[$k])) { $query[$k] = $_ENV[$k]; } elseif (isset($_SERVER[$k])) { $query[$k] = $_SERVER[$k]; } } $this->probeId = $probeId ? $probeId : $query['SPROFILER_PROBE_ID']; $this->probeToken = $probeToken ? $probeToken : $query['SPROFILER_PROBE_TOKEN']; $this->outputUrl = $outputUrl; $this->outputUrl or $this->outputUrl = $query['SPROFILER_OUTPUT_URL']; $this->outputUrl or $this->outputUrl = self::$defaultOutputUrl; $this->outputUrl or $this->outputUrl = ini_get('uprofiler.output_dir'); $this->outputUrl or $this->outputUrl = ini_get('xhprof.output_dir'); $this->outputTimeout = 1000000 * $query['SPROFILER_OUTPUT_TIMEOUT']; $this->outputTimeout or $this->outputTimeout = 0.25; $query['SPROFILER_LOG_LEVEL'] and $this->logLevel = $query['SPROFILER_LOG_LEVEL']; $query['SPROFILER_LOG_URL'] and $this->logUrl = $query['SPROFILER_LOG_URL']; $this->aggregSamples = isset($args['aggreg_samples']) && is_string($args['aggreg_samples']) ? max((int) $args['aggreg_samples'], 1) : 1; if (!$this->logUrl || 'stderr' === $this->logUrl) { $this->logUrl = 'php://stderr'; } empty($args['flag_cpu']) or $this->flags |= UPROFILER_FLAGS_CPU; empty($args['flag_memory']) or $this->flags |= UPROFILER_FLAGS_MEMORY; empty($args['flag_no_builtins']) or $this->flags |= UPROFILER_FLAGS_NO_BUILTINS; if (function_exists('uprofiler_enable')) { $this->profiler = 'uprofiler'; } elseif (function_exists('xhprof_enable')) { $this->profiler = 'xhprof'; } if ($this->logLevel >= 4) { $this->debug('New probe instanciated'); foreach ($this as $k => $v) { if ('options' !== $k) { if ('' !== $v = (string) $v) { $this->debug(' '.$k.': '.$v); } } } } } /** * Tells if the probe is cryptographically verified, i.e. if the signature in $query is valid. * * @return bool * * @api */ public function isVerified() { return $this->box('doVerify', false); } /** * Gets the response message/status/line * * This lines gives details about the status of the probe. That can be: * - an error: `SensioLabsProfiler-Error: $errNumber $urlEncodedErrorMessage` * - or not: `SensioLabsProfiler-Response: $rfc1738EncodedMessage` * * @return string The response line * * @api */ public function getResponseLine() { return $this->responseLine; } /** * Enables profiling instrumentation and data aggregation. * * One and only one probe can be enabled at the same time. * * @see getResponseLine() for error/status reporting * * @return bool False if enabling failed. * * @api */ public function enable() { return $this->box('doEnable', false, $this->getErrorHandler('error', array(__CLASS__, 'onError')) .$this->getErrorHandler('exception', array($this, 'onException')) ); } /** * Disables profiling instrumentation and data aggregation. * * As a side-effect, flushes the collected profile to the output. * * @param bool $close Not closing allows to re-enable the probe later and aggregate data in the same profile. Closing means that a later enable() will create a new profile on the output. * * @return bool False if the probe was not enabled. * * @api */ public function disable($close = false) { return $this->box('doDisable', true, $close); } // XXX // XXX - END OF PUBLIC API - XXX // XXX /** * @internal */ private static function boxPostEnable($probe, $isEnabled) { if ($isEnabled) { register_shutdown_function(array($probe, 'onShutdown')); } $probe->box('sendHeaderLine', null); } /** * @internal */ private static function restoreErrorHandler() { restore_error_handler(); } /** * @internal */ public function __destruct() { $this->disable(true); } /** * Wraps internal functions and handles any error/exception. * * @internal */ private function box($method, $returnValue) { set_error_handler(__CLASS__.'::onInternalError'); try { $args = func_get_args(); unset($args[0], $args[1]); $this->debug('Boxing '.$method); $returnValue = call_user_func_array(array($this, $method), $args); } catch (Exception $e) { $this->warn(get_class($e).': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine()); restore_error_handler(); $this->profilerDisable(); $this->responseLine = 'SensioLabsProfiler-Error: 101 '.rawurlencode($e->getMessage().' in '.$e->getFile().':'.$e->getLine()); } self::restoreErrorHandler(); return $returnValue; } /** * @internal */ private function doVerify() { if (null === $this->outputStream) { $signature = strtr($this->signature, '-_', '+/'); $signature = base64_decode($signature, true); // XXX Crypto checks are done here in the C version. // In the PHP version, this is delegated to the agent, // no verification occurs when the output is a directory. if ($signature) { $this->debug('Signature looks OK'); $this->openOutput(); } else { $this->info('Invalid signature'); } } return (bool) $this->outputStream; } /** * @internal */ private function doEnable($extra) { if ($this->isEnabled) { return true; } if (self::$profilerIsEnabled) { $this->responseLine = "SensioLabsProfiler-Error: 101 An other probe is already profiling"; return false; } if ($this->doVerify()) { $this->writeChunkProlog($extra); $this->profilerEnable(); $this->isEnabled = true; } return $this->isEnabled; } /** * @internal */ private function doDisable($close = false) { if (!$this->isEnabled) { return false; } $this->isEnabled = false; $this->profilerWrite(true); if ($close && $this->outputStream) { $this->debug('Closing output stream'); flock($this->outputStream, LOCK_UN); fclose($this->outputStream); $this->outputStream = null; } return true; } /** * @internal */ private function sendHeaderLine() { header('X-'.$this->getResponseLine()); } /** * @internal */ private function openOutput() { if (null !== $this->outputStream) { return $this->outputStream; } $this->outputStream = false; $url = $this->outputUrl; if (($i = strpos($url, '://')) && in_array(substr($url, 0, $i), stream_get_transports(), true)) { $this->debug('Lets open '.$url); if ($h = stream_socket_client($url, $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT)) { stream_set_timeout($h, 0, $this->outputTimeout); stream_set_write_buffer($h, 0); $i = array(null, array($h), null); if (stream_select($i[0], $i[1], $i[2], 0, $this->outputTimeout)) { $this->writeHelloProlog($h); $response = rtrim(fgets($h, 4096)); while ('' !== rtrim(fgets($h, 4096))) { // No-op } if (0 !== strpos($response, 'SensioLabsProfiler-Response: ')) { 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"; } } else { $response = "SensioLabsProfiler-Error: 101 $errstr ($errno)"; } } else { $i = sprintf('%019.6F', microtime(true)).'-'; $i .= substr(str_replace(array('+', '/'), array('', ''), base64_encode(md5(mt_rand(), true))), 0, 6); $url .= '/'.$i.'.log'; $this->debug('Lets open '.$url); $h = fopen($url, 'wb'); if (stream_is_local($h)) { flock($h, LOCK_SH); // This shared lock allows readers to wait for the end of the stream stream_set_write_buffer($h, 0); } else { $this->writeHelloProlog($h); } $response = "SensioLabsProfiler-Response: continue=false"; } $this->responseLine = $response; $this->outputStream = $h; if ($h) { $this->writeMainProlog(); } return $h; } /** * @internal */ private function writeHelloProlog($h) { $hello = ''; if ($this->probeId && $this->probeToken) { $line = $this->probeId.':'.$this->probeToken; if (strlen($line) !== strcspn($line, "\r\n") || 1 < substr_count($line, ':')) { $this->warn('Invalid probe_id/probe_token'); } else { $hello .= 'SensioLabsProfiler-Auth: '.$line."\n"; } } $line = 'signature='.$this->signature.'&aggreg_samples='.$this->aggregSamples."\n"; isset($this->challenge[0]) and $line = $this->challenge.'&'.$line; $hello .= 'SensioLabsProfiler-Query: '.$line."\n"; self::fwrite($h, $hello); } /** * @internal */ private function writeMainProlog() { // Loaded extensions list helps understanding runtime behavior $extensions = array(); foreach (get_loaded_extensions() as $e) { $extensions[$e] = phpversion($e); } // Keep only keys from $_COOKIE $cookies = array_keys($_COOKIE); // Keep selected keys from $_SERVER $servers = array(); foreach ($this->options['server_keys'] as $e) { if (isset($_SERVER[$e])) { $servers[$e] = $_SERVER[$e]; } } // Get request's URI 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)) { $servers['REQUEST_URI'] = $e; } self::fwrite($this->outputStream, 'file-format: '.$this->fileFormat."\n" .'php-os: '.PHP_OS."\n" .'php-sapi: '.PHP_SAPI."\n" .'php-version: '.PHP_VERSION_ID."\n" .'php-extensions: '.strtr(http_build_query($extensions, '', '&'), self::$urlEncMap)."\n" .'_COOKIE: '.strtr(http_build_query($cookies, '', '&'), self::$urlEncMap)."\n" .'_SERVER: '.strtr(http_build_query($servers, '', '&'), self::$urlEncMap)."\n" ."\nmain()//1 0 0 0 0\n\n" ); $this->debug('Main prolog pushed'); } /** * @internal */ private function writeChunkProlog($extra) { $data = 'request-mu: '.memory_get_usage(true)."\n" .'request-pmu: '.memory_get_peak_usage(true)."\n" .'request-start: '.microtime(true)."\n" .$extra; if (function_exists('sys_getloadavg')) { $data .= 'sys-load-avg: '.implode(' ', sys_getloadavg())."\n"; } self::fwrite($this->outputStream, $data); } /** * @internal */ private 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; $this->debug('Extracted '.$type); return $type."\n"; } /** * @internal */ private function profilerEnable() { self::$profilerIsEnabled = true; if (is_string($this->profiler)) { $p = $this->profiler.'_enable'; $this->debug($p); $p($this->flags, $this->options); } else { $this->info('No profiler to enable'); } } /** * @internal */ private function profilerDisable() { self::$profilerIsEnabled = false; if (is_string($this->profiler)) { $p = $this->profiler.'_disable'; $this->debug($p); return $p(); } elseif (is_array($this->profiler)) { $this->debug('data array profiler_disable'); return $this->profiler; } else { $this->info('No profiler to disable'); return array(); } } /** * @internal */ private function profilerWrite($disable, $chunk = '') { $data = $this->profilerDisable(); $chunk .= "request-end: ".microtime(true) ."\nrequest-mu: ".memory_get_usage(true) ."\nrequest-pmu: ".memory_get_peak_usage(true) ."\n\n"; $this->debug('Pushing '.count($data).' call pairs'); if (!$disable) { $this->profilerEnable(); } $h = $this->outputStream; $i = 50; // 50 ~= 4Ko chunks // Speed optimized paths if (!$data) { // No-op } elseif ((UPROFILER_FLAGS_CPU & $this->flags) && (UPROFILER_FLAGS_MEMORY & $this->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 & $this->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 & $this->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 .= "\n"; return self::fwrite($h, $chunk); } /** * @internal */ 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 ? $w : $len + 1; } if ($written === $len) { return true; } } } /** * @internal */ public static function onInternalError($type, $message, $file, $line) { throw new ErrorException($message, 0, $type, $file, $line); } /** * @internal */ public static function onError() { return false; // Delegate error handling to the internal handler, but adds a line in profiler's data } /** * @internal */ public function onException($e) { // Rethrow only, but adds a line in profiler's data $this->box('profilerWrite', null, true); // Prevents a crash with XHProf throw $e; } /** * @internal */ public function onShutdown() { $this->box('doShutdown', null, $this->getErrorHandler('error') .$this->getErrorHandler('exception') ); } /** * @internal */ private function doShutdown($extra) { // Get and write data now so that any later fatal error // does not prevent collecting what we already have. if (!$this->isEnabled) { return; } $e = error_get_last(); if (function_exists('http_response_code')) { $extra .= 'response-code: '.http_response_code()."\n"; } 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: $h = explode("\r", $e['message'], 2); $h = explode("\n", $h[0], 2); $h[1] = " in {$e['file']}:{$e['line']}"; $h[0] = str_replace($h[1], '', $h[0]); $h = "fatal-error: {$h[0]}{$h[1]}\n"; $this->info('Got '.$h); self::fwrite($this->outputStream, $h); break; } } $this->profilerWrite(false, $extra); } /** * @internal */ private function warn($msg) { if ($this->logLevel >= 2) { file_put_contents($this->logUrl, 'WARN: '.$msg."\n", FILE_APPEND); } } /** * @internal */ private function info($msg) { if ($this->logLevel >= 3) { file_put_contents($this->logUrl, 'Info: '.$msg."\n", FILE_APPEND); } } /** * @internal */ private function debug($msg) { if ($this->logLevel >= 4) { file_put_contents($this->logUrl, 'dbug: '.$msg."\n", FILE_APPEND); } } }

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).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0100.01316.50
8.3.50.0100.01121.93
8.3.40.0120.00418.92
8.3.30.0110.00419.26
8.3.20.0000.01020.47
8.3.10.0090.00020.36
8.3.00.0040.00419.38
8.2.180.0060.01517.00
8.2.170.0100.00722.96
8.2.160.0090.00620.60
8.2.150.0000.00824.18
8.2.140.0000.00824.66
8.2.130.0050.00526.16
8.2.120.0080.00022.24
8.2.110.0030.00622.20
8.2.100.0060.00618.03
8.2.90.0040.00419.34
8.2.80.0040.00417.97
8.2.70.0030.00717.75
8.2.60.0050.00518.15
8.2.50.0030.00718.07
8.2.40.0050.00318.28
8.2.30.0060.00319.79
8.2.20.0040.00417.88
8.2.10.0000.00918.27
8.2.00.0050.00317.79
8.1.280.0070.01425.92
8.1.270.0000.00823.83
8.1.260.0080.00026.35
8.1.250.0080.00028.09
8.1.240.0100.00023.91
8.1.230.0040.00719.26
8.1.220.0000.00917.78
8.1.210.0070.00318.77
8.1.200.0070.00417.48
8.1.190.0060.00317.38
8.1.180.0030.00618.10
8.1.170.0060.00318.83
8.1.160.0080.00022.31
8.1.150.0000.00818.95
8.1.140.0090.00017.55
8.1.130.0000.00817.59
8.1.120.0050.00317.58
8.1.110.0030.00617.63
8.1.100.0040.00417.67
8.1.90.0000.00817.62
8.1.80.0040.00417.62
8.1.70.0000.00717.61
8.1.60.0000.00917.63
8.1.50.0060.00317.68
8.1.40.0000.00817.63
8.1.30.0000.00817.72
8.1.20.0030.00617.67
8.1.10.0050.00317.59
8.1.00.0090.00017.60
8.0.300.0040.00418.77
8.0.290.0030.00616.88
8.0.280.0000.00818.45
8.0.270.0020.00517.46
8.0.260.0000.00717.09
8.0.250.0000.00717.11
8.0.240.0030.00617.01
8.0.230.0070.00017.03
8.0.220.0040.00416.93
8.0.210.0000.00817.07
8.0.200.0000.00717.03
8.0.190.0070.00017.00
8.0.180.0000.00817.07
8.0.170.0040.00417.05
8.0.160.0000.00817.05
8.0.150.0060.00317.00
8.0.140.0060.00316.86
8.0.130.0030.00613.52
8.0.120.0080.00016.92
8.0.110.0040.00417.01
8.0.100.0000.00817.01
8.0.90.0040.00416.96
8.0.80.0070.01717.05
8.0.70.0080.00017.05
8.0.60.0030.00617.02
8.0.50.0000.00816.93
8.0.30.0110.00917.27
8.0.20.0160.00917.40
8.0.10.0030.00517.07
8.0.00.0170.00716.83
7.4.330.0000.00515.00
7.4.320.0000.00716.72
7.4.300.0040.00416.60
7.4.290.0040.00416.65
7.4.280.0030.00616.73
7.4.270.0070.00016.75
7.4.260.0040.00416.67
7.4.250.0040.00416.55
7.4.240.0000.00816.76
7.4.230.0040.00416.88
7.4.220.0170.00316.70
7.4.210.0030.01416.63
7.4.200.0040.00416.55
7.4.160.0060.01216.47
7.4.150.0000.02017.40
7.4.140.0070.01617.86
7.4.130.0070.01316.67
7.4.120.0090.01216.71
7.4.110.0110.00716.58
7.4.100.0130.00616.54
7.4.90.0030.01516.62
7.4.80.0060.01616.55
7.4.70.0080.01516.82
7.4.60.0130.00616.70
7.4.50.0030.00616.56
7.4.40.0160.00816.60
7.4.30.0090.00916.67
7.4.00.0030.01315.20
7.3.330.0040.00413.45
7.3.320.0030.00313.45
7.3.310.0070.00016.41
7.3.300.0040.00416.45
7.3.290.0120.00616.50
7.3.280.0110.00916.40
7.3.270.0070.01117.40
7.3.260.0070.01116.63
7.3.250.0120.01316.40
7.3.240.0070.01116.49
7.3.230.0030.01416.68
7.3.210.0120.00616.53
7.3.200.0030.01919.39
7.3.190.0060.01316.51
7.3.180.0140.00416.67
7.3.170.0070.01116.64
7.3.160.0120.00616.36
7.2.330.0030.01616.74
7.2.320.0070.01716.58
7.2.310.0120.01316.54
7.2.300.0070.01116.80
7.2.290.0150.00316.45
7.2.60.0070.01016.47
7.2.00.0060.00618.88
7.1.200.0030.00615.71
7.1.100.0070.00717.53
7.1.70.0060.00316.95
7.1.60.0090.01519.32
7.1.50.0100.01316.77
7.1.00.0100.06322.30
7.0.200.0000.01016.61
7.0.140.0070.07021.95
7.0.100.0500.06320.27
7.0.90.0300.08020.29
7.0.80.0200.07720.16
7.0.70.0130.08020.25
7.0.60.0100.08020.23
7.0.50.0200.06320.64
7.0.40.0070.09020.20
7.0.30.0030.09020.16
7.0.20.0070.08720.11
7.0.10.0070.05320.05
7.0.00.0030.06720.13
5.6.280.0030.07721.20
5.6.250.0070.07720.78
5.6.240.0100.07020.82
5.6.230.0200.06720.83
5.6.220.0070.07020.80
5.6.210.0130.04320.93
5.6.200.0170.06321.20
5.6.190.0070.08021.23
5.6.180.0200.07021.23
5.6.170.0000.08021.14
5.6.160.0100.07321.21
5.6.150.0130.07321.21
5.6.140.0070.09321.23
5.6.130.0100.04321.35
5.6.120.0070.08321.29
5.6.110.0100.05321.34
5.6.100.0070.08721.16
5.6.90.0030.07021.20
5.6.80.0070.04720.57
5.6.70.0170.06320.66
5.6.60.0030.08020.55
5.6.50.0000.08320.63
5.6.40.0100.08020.59
5.6.30.0070.07320.55
5.6.20.0070.03720.57
5.6.10.0030.04320.46
5.6.00.0030.04720.53
5.5.380.0170.06720.53
5.5.370.0100.08720.57
5.5.360.0130.07720.51
5.5.350.0170.07320.63
5.5.340.0130.07321.04
5.5.330.0100.08020.95
5.5.320.0200.07721.08
5.5.310.0100.06021.00
5.5.300.0170.06321.06
5.5.290.0070.06721.09
5.5.280.0130.07021.00
5.5.270.0100.05020.92
5.5.260.0170.07721.10
5.5.250.0200.06320.79
5.5.240.0070.07720.20
5.5.230.0130.07020.47
5.5.220.0070.08020.46
5.5.210.0070.07320.47
5.5.200.0100.06720.41
5.5.190.0130.05020.28
5.5.180.0000.06320.41
5.5.160.0030.04020.35
5.5.150.0100.03320.32
5.5.140.0070.03720.44
5.5.130.0100.04020.44
5.5.120.0070.03720.30
5.5.110.0000.04320.35
5.5.100.0030.05020.33
5.5.90.0030.06020.27
5.5.80.0030.03320.18
5.5.70.0030.04020.24
5.5.60.0070.03320.32
5.5.50.0000.06720.23
5.5.40.0100.03720.30
5.5.30.0030.08020.30
5.5.20.0130.02720.25
5.5.10.0030.05020.21
5.5.00.0030.04020.27
5.4.450.0030.07719.56
5.4.440.0030.05319.68
5.4.430.0200.06719.52
5.4.420.0070.08019.49
5.4.410.0170.05019.35
5.4.400.0030.07019.22
5.4.390.0070.07319.17
5.4.380.0070.07319.14
5.4.370.0030.07319.06
5.4.360.0070.05319.14
5.4.350.0130.07019.29
5.4.340.0000.04319.32
5.4.320.0100.03319.14
5.4.310.0070.03719.29
5.4.300.0000.04019.32
5.4.290.0030.03719.13
5.4.280.0030.03719.21
5.4.270.0000.05018.97
5.4.260.0070.03719.17
5.4.250.0030.03719.11
5.4.240.0070.04719.12
5.4.230.0030.06719.14
5.4.220.0030.03319.15
5.4.210.0030.06719.05
5.4.200.0000.03719.19
5.4.190.0070.06019.15
5.4.180.0100.03718.98
5.4.170.0030.04019.28
5.4.160.0000.06319.30
5.4.150.0030.06718.98
5.4.140.0000.03716.51
5.4.130.0070.03316.30
5.4.120.0000.04316.45
5.4.110.0000.04016.51
5.4.100.0030.03316.65
5.4.90.0070.03316.50
5.4.80.0000.04016.61
5.4.70.0130.02716.52
5.4.60.0070.03016.42
5.4.50.0070.03316.63
5.4.40.0100.03016.55
5.4.30.0030.03716.63
5.4.20.0100.03016.59
5.4.10.0070.03316.50
5.4.00.0030.03715.89

preferences:
37.46 ms | 401 KiB | 5 Q