Skip to content

Instantly share code, notes, and snippets.

@Vovan-VE
Last active October 29, 2019 16:08
Show Gist options
  • Save Vovan-VE/992eee28ba66b352b24a to your computer and use it in GitHub Desktop.
Save Vovan-VE/992eee28ba66b352b24a to your computer and use it in GitHub Desktop.
Test if value is array or not, when value mostly is null
<?php
/**
* Compare performance of alternative functions
*
* Cases functions in `$functions` are all should perform the same task, but in different
* implementation. This benchmark function runs every cases functions and display a report to
* STDOUT, so you can compare performance.
*
* Example:
*
* ```php
* $array = [42, 42, 42, 42, 42, 'foo' => null, 'bar' => 37, 42, 42, 42, 42, 42];
*
* foreach (
* [
* 'existing foo' => [true, $array, 'foo'],
* 'existing bar' => [true, $array, 'bar'],
* 'unknown baz' => [false, $array, 'baz'],
* ]
* as $describe => [$return, $arr, $key]
* ) {
* countthese($describe, 5, [
* 'array_key_exists()' => function () use ($arr, $key) {
* return array_key_exists($key, $arr);
* },
* 'isset() || array_key_exists()' => function () use ($arr, $key) {
* return isset($arr[$key]) || array_key_exists($key, $arr);
* },
* ], $return);
* }
* ```
*
* Output:
*
* ```
* ==========[ existing foo ]======================================================
* Benchmark: counting 5 seconds of `array_key_exists()`, `isset() || array_key_exists()`
*
* function : count @ iterations/sec. / total sec.
* --------------------------------------------------------------------------
* array_key_exists() : 30315947 @ 6063189.4000 / 5.000
* isset() || array_key_exists(): 26433156 @ 5286631.2000 / 5.000
*
* array_key_exists() ######################################### 100.0%
* isset() || array_key_exists() #################################### 87.2%
*
* ==========[ existing bar ]======================================================
* Benchmark: counting 5 seconds of `array_key_exists()`, `isset() || array_key_exists()`
*
* function : count @ iterations/sec. / total sec.
* --------------------------------------------------------------------------
* array_key_exists() : 30914238 @ 6182847.6000 / 5.000
* isset() || array_key_exists(): 33205106 @ 6641021.2000 / 5.000
*
* array_key_exists() ###################################### 93.1%
* isset() || array_key_exists() ######################################### 100.0%
*
* ==========[ unknown baz ]=======================================================
* Benchmark: counting 5 seconds of `array_key_exists()`, `isset() || array_key_exists()`
*
* function : count @ iterations/sec. / total sec.
* --------------------------------------------------------------------------
* array_key_exists() : 31766575 @ 6353315.0000 / 5.000
* isset() || array_key_exists(): 28409213 @ 5681842.6000 / 5.000
*
* array_key_exists() ######################################### 100.0%
* isset() || array_key_exists() ##################################### 89.4%
* ```
*
* @param string $describe Short description
* @param int $timeout Duration in seconds for every case function
* @param \Closure[] $functions Case functions. Array keys are short names for cases.
* @param mixed $checkReturnValue Optional. The extected return value to check. To NOT check return
* value this parameter must be omitted, sot the function should be called with only 3 parameters.
*/
function countthese($describe, $timeout, array $functions, $checkReturnValue = null) {
if (!$functions) {
throw new LogicException("No callback function specified");
}
if (func_num_args() >= 4) {
foreach ($functions as $name => $function) {
$result = $function();
if ($checkReturnValue !== $result) {
var_dump($result);
throw new RuntimeException("Return value mismatch for `$name`");
}
}
}
$names = array_keys($functions);
$width = max(8, ...array_map('strlen', $names));
echo "==========[ $describe ]", str_repeat("=", max(0, 80 - strlen($describe) - 14)), PHP_EOL;
printf(
"Benchmark: counting %d seconds of %s" . PHP_EOL
, number_format($timeout, 0, "", "_")
, join(", ", array_map(function ($name) { return "`$name`"; }, $names))
);
echo PHP_EOL;
printf(" %-{$width}s: %10s @ %16s / %10s", "function", "count", "iterations/sec.", "total sec.");
echo PHP_EOL, "---------", str_repeat("-", $width + 10 + 16 + 10), PHP_EOL;
$totals = [];
foreach ($functions as $name => $function) {
printf(" %-{$width}s: ", $name);
$start = microtime(true);
$end = $start + $timeout;
$count = 0;
while ( ($now = microtime(true)) < $end ) {
$function();
++$count;
}
$total = $now - $start;
$speed = $count / $total;
$totals[$name] = $speed;
printf("%10d @ %16.4F / %10.3F ", $count, $speed, $total);
echo PHP_EOL;
}
echo PHP_EOL;
$bar_width = 80 - 4 - $width - 5 - 1;
$max_speed = max($totals);
foreach ($totals as $name => $speed) {
$coeff = $speed / $max_speed;
printf(" %-{$width}s %-{$bar_width}s %5.1F%%"
, $name
, str_repeat("#", round($bar_width * $coeff))
, $coeff * 100
);
echo PHP_EOL;
}
echo PHP_EOL;
}
<?php
require_once '_benchmark.php';
foreach (
[
'null' => [false, null],
'42' => [false, 42],
'array' => [true, []],
]
as $describe => [$return, $value]
) {
countthese($describe, 5, array(
'is_array()' => function () use ($value) {
return is_array($value);
},
'null !== && is_array()' => function () use ($value) {
return null !== $value && is_array($value);
},
), $return);
}
==========[ null ]==============================================================
Benchmark: counting 5 seconds of `is_array()`, `null !== && is_array()`
function : count @ iterations/sec. / total sec.
-------------------------------------------------------------------
is_array() : 40115122 @ 8023024.4000 / 5.000
null !== && is_array(): 37800462 @ 7560092.4000 / 5.000
is_array() ################################################ 100.0%
null !== && is_array() ############################################# 94.2%
==========[ 42 ]================================================================
Benchmark: counting 5 seconds of `is_array()`, `null !== && is_array()`
function : count @ iterations/sec. / total sec.
-------------------------------------------------------------------
is_array() : 39369570 @ 7873914.0000 / 5.000
null !== && is_array(): 36663397 @ 7332679.4000 / 5.000
is_array() ################################################ 100.0%
null !== && is_array() ############################################# 93.1%
==========[ array ]=============================================================
Benchmark: counting 5 seconds of `is_array()`, `null !== && is_array()`
function : count @ iterations/sec. / total sec.
-------------------------------------------------------------------
is_array() : 39915046 @ 7983009.2000 / 5.000
null !== && is_array(): 37932799 @ 7586559.8000 / 5.000
is_array() ################################################ 100.0%
null !== && is_array() ############################################## 95.0%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment