Created
February 21, 2019 11:58
-
-
Save abbadon1334/345428619fc6603225be9e94be0d6a02 to your computer and use it in GitHub Desktop.
Suppression bench @ vs isset
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Copyright (c) 2019. | |
* | |
* Francesco "Abbadon1334" Danti <fdanti@gmail.com> | |
* | |
* Permission is hereby granted, free of charge, to any person | |
* obtaining a copy of this software and associated documentation | |
* files (the "Software"), to deal in the Software without | |
* restriction, including without limitation the rights to use, | |
* copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the | |
* Software is furnished to do so, subject to the following | |
* conditions: | |
* | |
* The above copyright notice and this permission notice shall be | |
* included in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
* OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
$a = function($cycleN) { | |
$ret = []; | |
$i = ['test' => 1]; | |
for($a=0;$a<$cycleN;$a++) | |
{ | |
if(@$i['test']==1) | |
{ | |
//$ret[] = 1; | |
} | |
} | |
return count($ret); | |
}; | |
$b = function($cycleN) { | |
$ret = []; | |
$i = ['test' => 1]; | |
for($a=0;$a<$cycleN;$a++) | |
{ | |
if(isset($i['test']) && $i['test'] ==1) | |
{ | |
//$ret[] = 1; | |
} | |
} | |
return count($ret); | |
}; | |
$c = function($cycleN) { | |
$ret = []; | |
$i = ['test' => 1]; | |
for($a=0;$a<$cycleN;$a++) | |
{ | |
if(@$i['not_exists']==1) | |
{ | |
//$ret[] = 1; | |
} | |
} | |
return count($ret); | |
}; | |
$d = function($cycleN) { | |
$ret = []; | |
$i = ['test' => 1]; | |
for($a=0;$a<$cycleN;$a++) | |
{ | |
if(isset($i['not_exists']) && $i['not_exists'] ==1) | |
{ | |
//$ret[] = 1; | |
} | |
} | |
return count($ret); | |
}; | |
$bm = new benchmark(); | |
$bm->_sample_output = 0; | |
$bm->show_differences = 1; // it will check the return value if is the same throw cycles | |
$cycleN = 10000; | |
$bm->time_this('exists key : @$val["key"]', $a, [$cycleN]); | |
$bm->time_this('exists key : isset($val["key"]) && $val["key"] == 1', $b, [$cycleN]); | |
$bm->time_this('not exists key : @$val["key"]', $c, [$cycleN]); | |
$bm->time_this('not exists key : isset($val["key"]) && $val["key"] == 1', $d, [$cycleN]); | |
$bm->html_summary(); | |
// https://github.com/scottchiefbaker/php-benchmark | |
class benchmark { | |
public $_sample_output = 0; // sample out in HTML summary | |
public $show_differences = 0; // Highlight if one test has diferent output than the others | |
public $test_seconds = 1; // Time to run each test | |
private $results = array(); // Array that will store the results | |
public function time_this($name, $func, $args = array()) { | |
$seconds = $this->test_seconds; | |
$count = 0; | |
$start = microtime(1); | |
$time = 0; | |
while ($time < $seconds) { | |
$ret = call_user_func_array($func,$args); | |
$time = microtime(1) - $start; | |
$count++; | |
} | |
$this->results['count'][$name] = intval($count / $seconds); | |
$this->results['return'][$name] = $ret; | |
} | |
public function summary($type = "") { | |
if ($type != "html" && php_sapi_name() === 'cli') { | |
$this->text_summary(); | |
} else { | |
$this->html_summary(); | |
} | |
} | |
public function text_summary() { | |
if (sizeof($this->results['count']) === 0) { | |
print "No results found"; | |
return false; | |
} | |
$use_color = 1; | |
if ($use_color) { | |
$red = "\033[38;5;9m"; | |
$white = "\033[38;5;15m"; | |
$blue = "\033[38;5;51m"; | |
$yellow = "\033[38;5;227m"; | |
$reset = "\033[0m"; | |
} else { | |
$red = ""; | |
$white = ""; | |
$blue = ""; | |
$yellow = ""; | |
$reset = ""; | |
} | |
$php_version = phpversion(); | |
print $white . "PHP Version: $blue$php_version$reset\n\n"; | |
arsort($this->results['count']); | |
$test_names = array_keys($this->results['count']); | |
$max_len = 0; | |
$total_len = 0; | |
foreach ($test_names as $name) { | |
// Minimum allowed length for alignment is 8 in text mode | |
$len = strlen($name); | |
if ($len < 8) { | |
$len = 8; | |
} | |
$total_len += $len; | |
if (strlen($name) > $max_len) { | |
$max_len = strlen($name); | |
} | |
} | |
############################################## | |
print str_repeat(" ",$max_len + 4); // Indent | |
$pad_names = $test_names; | |
foreach ($pad_names as &$i) { | |
$i = sprintf("$yellow%8s$reset",$i); | |
} | |
print join(" | ",$pad_names) . "\n"; | |
// The length of the bar is the total length of the test names, | |
// plus the " | " between each word test pair, | |
// plus four because there are two spaces at the start and end | |
$additional = (sizeof($test_names) - 1) * 3; | |
$bar = str_repeat(" ",$max_len + 2) . "+" . str_repeat("-",$total_len + $additional + 2) . "+\n"; | |
print $bar; | |
foreach($test_names as $y_name) { | |
printf(" $yellow%{$max_len}s$reset |",$y_name); | |
foreach ($test_names as $x_name) { | |
$x_val = $this->results['count'][$x_name]; | |
$y_val = $this->results['count'][$y_name]; | |
$percent = round(($y_val / $x_val) * 100,2) . "%"; | |
$x_name = sprintf("%8s",$x_name); | |
$col_width = strlen($x_name) + 1; | |
if ($y_val === $x_val) { | |
$percent = "N/A"; | |
printf("$red%{$col_width}s$reset |",$percent); | |
} else { | |
printf("$white%{$col_width}s$reset |",$percent); | |
} | |
} | |
print "\n"; | |
} | |
print $bar; | |
print "\n"; | |
$max_len += 1; | |
$expected_results = reset($this->results['return']); | |
//print_r($this->results['count']); | |
foreach($test_names as $name) { | |
$count = $this->results['count'][$name]; | |
$ret = $this->results['return'][$name]; | |
if ($this->_sample_output) { | |
printf(" %s = %s iterations per second\n",$name,number_format($count)); | |
if ($this->show_differences && ($ret !== $expected_results)) { | |
print " ** Return value from this function differs from the first test **\n"; | |
} | |
$print_r_output = trim(print_r($ret,true)); | |
$print_r_output = preg_replace("/^/m"," ",$print_r_output); | |
print " Sample output: \n$print_r_output\n\n"; | |
} else { | |
printf("%{$max_len}s = %s iterations per second\n",$name,number_format($count)); | |
} | |
} | |
print "\n"; | |
} | |
public function html_summary() { | |
if (sizeof($this->results['count']) === 0) { | |
print "<div>No results found</div>"; | |
return false; | |
} | |
arsort($this->results['count']); | |
$tests = array_keys($this->results['count']); | |
array_unshift($tests,' '); | |
$first = 1; | |
$php_version = phpversion(); | |
$out = "<h2>PHP Version: $php_version</h2>"; | |
$header_color = '#CCE6FF'; | |
$out .= '<table style="border-collapse: collapse; border: 1px solid black; width: 100%;">'; | |
$x = 0; | |
foreach ($tests as $name) { | |
$out .= "<tr>"; | |
// If it's the first row, output all the headers | |
if ($first) { | |
foreach ($tests as $i) { | |
$out .= '<td style="padding: 5px; white-space: nowrap; text-align: center; font-weight: bold; background-color: '.$header_color.'; border: 1px solid black; width: 10em;">'.$i.'</td>'; | |
} | |
$first = 0; | |
// It's not the first row so loop through outputting each data cell | |
} else { | |
$column = 0; | |
$y = 0; | |
foreach ($tests as $i) { | |
// If it's the first column, it's the row header (on the left) | |
if ($column == 0) { | |
$content = $tests[$x + 1]; | |
$color = $header_color; | |
$align = 'right'; | |
$fw = 'bold'; | |
$x++; | |
} else { | |
$y++; | |
$x_name = $tests[$x]; | |
$y_name = $tests[$y]; | |
$a = $this->results['count'][$x_name]; | |
$b = $this->results['count'][$y_name]; | |
$percentage = sprintf("%.2f%%",($a / $b) * 100); | |
$color = 'white'; | |
$align = 'center'; | |
$fw = 'normal'; | |
// Row/Column are the same so we output n/a | |
if ($x === $y) { | |
$color = "#FF9999"; | |
$content = "<b>n/a</b>"; | |
// It's a legit data point | |
} else { | |
$content = "$percentage"; | |
} | |
} | |
// Output each data cell | |
$out .= '<td style="padding: 5px; white-space: nowrap; background-color: '.$color.'; font-weight: '.$fw.'; text-align: '.$align.'; border: 1px solid black; width: 10em;">'.$content.'</td>'; | |
$column++; | |
} | |
} | |
$out .= "</tr>"; | |
} | |
$out .= "</table>"; | |
$out .= "<br />"; | |
$slowest = min($this->results['count']); | |
$fastest = max($this->results['count']); | |
$expected_results = reset($this->results['return']); | |
$out .= "<table>"; | |
foreach ($this->results['count'] as $test => $speed) { | |
$ret = $this->results['return'][$test]; | |
$speed_str = number_format($speed); | |
$out .= '<tr><td style="padding: 1px 3px; text-align: right;"><b>'.$test.':</b></td><td style="padding: 0 3px;">'.$speed_str.' iterations per second'; | |
if ($this->show_differences && ($ret !== $expected_results)) { | |
$out .= '<div style="margin: 0 0 1em 2em; "><span style="color: red;"><b>!!!</b></span> Return value from this function differs from the first test</div>'; | |
} | |
if ($this->_sample_output) { | |
$out .= '<div style="margin: 0 0 1em 2em; "><b>Sample output:</b> ' . print_r($ret,true) . '</div>'; | |
} | |
$out .= "</td></tr>"; | |
} | |
$out .= "</table>"; | |
print $out; | |
} | |
public function reset() { | |
$this->results = array(); | |
} | |
} // End of class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment