Skip to content

Instantly share code, notes, and snippets.

@klaernie
Forked from ak4n/foreach_vs_array_asterix
Last active May 8, 2016 09:59
Show Gist options
  • Save klaernie/6dd1acba42afb347f9a02cdcd18a7c99 to your computer and use it in GitHub Desktop.
Save klaernie/6dd1acba42afb347f9a02cdcd18a7c99 to your computer and use it in GitHub Desktop.
Benchmarking execution time of PHP constructs (list / each, foreach) vs (array_walk, array_map, array_reduce, array_filter)
<?php
/**
* Execution time check for: (list/each,foreach) vs (array_walk, array_map, array_reduce, array_filter)
* @docs to read
* http://www.giorgiosironi.com/2010/02/stop-writing-foreach-cycles.html
* http://www.pastie.org/829318
* http://php.net/manual/en/function.array-walk.php#112722
* http://zaemis.blogspot.com/2013/06/building-array-with-arrayreduce.html
* (!) http://stackoverflow.com/questions/2473989/list-of-big-o-for-php-functions/2484455#2484455
* http://www.faieta.net/wp/performance-implications-of-closures-in-php/
* https://alexatnet.com/articles/php-micro-optimization-tips
*/
version_compare(phpversion(), '5.4.0', '>=') ?: die('5.4.0+ required.');
define('EOL', php_sapi_name() === 'cli' ? PHP_EOL : '<br>');
echo EOL, '1. Walk array and change values', EOL;
$walkArray1 = test_walk('array_walk');
$walkArray2 = test_walk('array_walk_list_each');
$walkArray3 = test_walk('array_walk_foreach');
$walkArray4 = test_walk('array_walk_foreach_by_value');
echo EOL, 'equality check', EOL;
var_dump(
$walkArray1 === $walkArray2,
$walkArray1 === $walkArray3,
$walkArray1 === $walkArray4
);
echo EOL, '2. Walk array and do multiplication of elements', EOL;
$mapArray1 = test_map('array_map');
$mapArray2 = test_map('array_map_list_each');
$mapArray3 = test_map('array_map_list_each_by_value');
$mapArray4 = test_map('array_map_foreach');
$mapArray5 = test_map('array_map_foreach_by_value');
echo EOL, 'equality check', EOL;
var_dump(
$mapArray1 === $mapArray2,
$mapArray1 === $mapArray3,
$mapArray1 === $mapArray4,
$mapArray1 === $mapArray5
);
echo EOL, '3. Walk array and sum the elements', EOL;
$reduceArray1 = test_reduce('array_reduce');
$reduceArray2 = test_reduce('array_reduce_list_each');
$reduceArray3 = test_reduce('array_reduce_foreach');
echo EOL, 'equality check', EOL;
var_dump(
$reduceArray1 === $reduceArray2,
$reduceArray1 === $reduceArray3
);
echo EOL, '4. Walk array and filter even elements', EOL;
$filterArray1 = test_filter('array_filter');
$filterArray2 = test_filter('array_filter_list_each');
$filterArray3 = test_filter('array_filter_foreach');
echo EOL, 'equality check', EOL;
var_dump(
$filterArray1 === $filterArray2,
$filterArray1 === $filterArray3
);
/* ------------------------------- FUNCTIONS ------------------------------ */
/* Walk array and change values
* array_walk(array &$array, callable $function, mixed $userData = null): bool
* $function ($value, $key)
*/
/**
* Test list/each by array[key]
*
* @param $array
* @param $function
* @param null $userData
*/
function array_walk_list_each(& $array, $function, $userData = null)
{
while (list($key, $value) = each($array)) {
$function($array[$key], $key, $userData);
}
}
/**
* Test foreach by array[key]
*
* @param $array
* @param $function
* @param null $userData
*/
function array_walk_foreach(& $array, $function, $userData = null)
{
foreach ($array as $key => $value) {
$function($array[$key], $key, $userData);
}
}
/**
* Test foreach by value
*
* @param $array
* @param $function
* @param null $userData
*/
function array_walk_foreach_by_value(& $array, $function, $userData = null)
{
foreach ($array as $key => & $value) {
$function($value, $key, $userData);
}
}
/**
* Change value in array passed by reference
*
* @param $value
* @param $key
* @param $userData
*/
function change_values(& $value, $key, $userData)
{
$value = "$key => $userData";
}
/**
* Walk array and change values using: list / each, foreach, array_walk()
*
* @param $function
* @param int $count
* @param int $arrayElements
* @return array
*/
function test_walk($function, $count = 10000, $arrayElements = 100)
{
$value = 'text value';
$array = array_fill(0, $arrayElements, $value);
echo $function, ' ... ';
$timer = microtime(true);
for ($i = 0; ++$i < $count;) {
$function($array, 'change_values', 'user data');
}
printf('%.4f sec' . EOL, microtime(true) - $timer);
return $array;
}
/* Walk array and do some math
* array_map(callable $function, array $array [,array $array1, ... ]): array
* $function ($value)
*/
/**
* Test each/list by array[key]
*
* @param $function
* @param $array
* @return array
*/
function array_map_list_each($function, $array)
{
$squared = [];
while (list($key) = each($array)) {
$squared[$key] = $function($array[$key]);
}
return $squared;
}
/**
* Test each/list by value
*
* @param $function
* @param $array
* @return array
*/
function array_map_list_each_by_value($function, $array)
{
$squared = [];
while (list($key, $value) = each($array)) {
$squared[$key] = $function($value);
}
return $squared;
}
/**
* Test foreach by array[key]
*
* @param $function
* @param $array
* @return array
*/
function array_map_foreach($function, $array)
{
$squared = [];
foreach ($array as $key => $value) {
$squared[$key] = $function($array[$key]);
}
return $squared;
}
/**
* Test foreach by value
*
* @param $function
* @param $array
* @return array
*/
function array_map_foreach_by_value($function, $array)
{
$squared = [];
foreach ($array as $key => $value) {
$squared[$key] = $function($value);
}
return $squared;
}
/**
* Get array value multiplication
*
* @param $value
* @return integer
*/
function multi_values($value)
{
return $value * $value;
}
/**
* Walk array and do some math using: list/ each, foreach, array_map(), array_reduce()
*
* @param $function
* @param int $count
* @param int $arrayElements
* @return array
*/
function test_map($function, $count = 10000, $arrayElements = 100)
{
$digest = [];
$value = 4;
$testArray = array_fill(0, $arrayElements, $value);
echo $function, ' ... ';
$timer = microtime(true);
for ($i = 0; ++$i < $count;) {
$digest[] = $function('multi_values', $testArray);
}
printf('%.4f sec' . EOL, microtime(true) - $timer);
return $digest;
}
/* Walk array and do some math
* array_reduce(array $array, callable $function, mixed $result = null) mixed
* $function ($result, $item)
*/
/**
* Test foreach
*
* @param array $array
* @param $function
* @param null $init
* @return null
*/
function array_reduce_foreach(array $array, $function, $init = null)
{
$acc = $init;
foreach ($array as $item) {
$acc = $function($acc, $item);
}
return $acc;
}
/**
* Test list/each
*
* @param array $array
* @param $function
* @param null $init
* @return null
*/
function array_reduce_list_each(array $array, $function, $init = null)
{
$acc = $init;
while (list(, $value) = each($array)) {
$acc = $function($acc, $value);
}
return $acc;
}
/**
* Get array values sum
*
* @param $carry
* @param $item
* @return mixed
*/
function sum_values($carry, $item)
{
$carry += $item;
return $carry;
}
/**
* Iteratively reduce array using: list / each, foreach, array_reduce()
*
* @param $function
* @param int $count
* @param int $arrayElements
* @return array
*/
function test_reduce($function, $count = 10000, $arrayElements = 100)
{
$digest = [];
$value = 13;
$testArray = array_fill(0, $arrayElements, $value);
echo $function, ' ... ';
$timer = microtime(true);
for ($i = 0; ++$i < $count;) {
$digest[] = $function($testArray, 'sum_values');
}
printf('%.4f sec' . EOL, microtime(true) - $timer);
return $digest;
}
/* Filters elements of an array with callback
* array_filter(array $array, callable $function = null, $flag = 0) array
* $function ($value); for php 5.6 $function ($value [,$key), if $flag = ARRAY_FILTER_USE_BOTH
*/
/**
* Test list/each
*
* @param $array
* @param $function
* @return array
*/
function array_filter_list_each($array, $function)
{
$digest = [];
while (list($key, $value) = each($array)) {
if ($function($value)) {
$digest[$key] = $value;
}
}
return $digest;
}
/**
* Test foreach
*
* @param $array
* @param $function
* @return array
*/
function array_filter_foreach($array, $function)
{
$digest = [];
foreach ($array as $key => $value) {
if ($function($value)) {
$digest[$key] = $value;
}
}
return $digest;
}
/**
* Returns whether the input integer is odd
*
* @param $value
* @return int
*/
function filter_values($value)
{
return ($value & 1);
}
/**
* Filter array values using: list / each, foreach, array_filter()
*
* @param $function
* @param int $count
* @param int $arrayElements
* @return array
*/
function test_filter($function, $count = 10000, $arrayElements = 100)
{
$digest = [];
$testArray = range(1, $arrayElements);
echo $function, ' ... ';
$timer = microtime(true);
for ($i = 0; ++$i < $count;) {
$digest[] = $function($testArray, 'filter_values');
}
printf('%.4f sec' . EOL, microtime(true) - $timer);
return $digest;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment