Skip to content

Instantly share code, notes, and snippets.

@vhenzl
Last active September 18, 2021 05:05
Show Gist options
  • Save vhenzl/6cbc9edbfb269a86f2c960a4d6823062 to your computer and use it in GitHub Desktop.
Save vhenzl/6cbc9edbfb269a86f2c960a4d6823062 to your computer and use it in GitHub Desktop.
`array_map()` vs `foreach` vs an utility (PHP benchmark)

A benchmark to compare various ways how to map array of values in PHP. Inspired by changes in https://github.com/webonyx/graphql-php/commit/b370b8f7a018d149fe513281128ae651d7c60f78

Using https://github.com/phpbench/phpbench

vendor/bin/phpbench run benchmarks/MapBench.php --progress=blinken --report=aggregate

Results:

#0  158.3 153.8 158.4 158.9 154.3 (μs) Mo158.4μs (±1.41%)
#1  155.4 157.9 159.5 156.2 156.4 (μs) Mo156.3μs (±0.92%)
#2  134.4 133.1 132.3 133.5 133.8 (μs) Mo133.6μs (±0.53%)
#3  133.8 136.5 133.6 135.2 134.5 (μs) Mo134.2μs (±0.78%)
#4  48.0  48.7  48.1  48.6  48.0 (μs) Mo48.1μs (±0.59%)
#5  69.0  68.0  69.0  69.8  68.6 (μs) Mo68.9μs (±0.87%)
#6  47.7  48.4  48.1  47.4  47.1 (μs) Mo47.7μs (±0.96%)
#7  55.1  56.5  55.9  54.9  55.6 (μs) Mo55.4μs (±1.00%)
#8  49.1  48.5  49.0  50.0  49.3 (μs) Mo49.1μs (±1.02%)
#9  68.2  69.4  67.5  68.1  69.0 (μs) Mo68.1μs (±1.01%)
#10 49.1  47.3  47.7  48.8  48.1 (μs) Mo48.0μs (±1.42%)
#11 70.2  69.3  68.1  69.1  69.2 (μs) Mo69.3μs (±0.96%)

Subjects: 12, Assertions: 0, Failures: 0, Errors: 0
+-----------+----------------------------+-----+------+-----+-----------+---------+--------+
| benchmark | subject                    | set | revs | its | mem_peak  | mode    | rstdev |
+-----------+----------------------------+-----+------+-----+-----------+---------+--------+
| MapBench  | benchUtilsMapArray         |     | 1000 | 5   | 606.984kb | 158.4μs | ±1.41% |
| MapBench  | benchUtilsMapOldArray      |     | 1000 | 5   | 606.984kb | 156.3μs | ±0.92% |
| MapBench  | benchUtilsMapList          |     | 1000 | 5   | 582.464kb | 133.6μs | ±0.53% |
| MapBench  | benchUtilsMapOldList       |     | 1000 | 5   | 582.464kb | 134.2μs | ±0.78% |
| MapBench  | benchUtilsForeachArray     |     | 1000 | 5   | 582.376kb | 48.1μs  | ±0.59% |
| MapBench  | benchUtilsForeachKeysArray |     | 1000 | 5   | 606.960kb | 68.9μs  | ±0.87% |
| MapBench  | benchUtilsForeachList      |     | 1000 | 5   | 582.376kb | 47.7μs  | ±0.96% |
| MapBench  | benchUtilsForeachKeysList  |     | 1000 | 5   | 582.384kb | 55.4μs  | ±1.00% |
| MapBench  | benchArrayMapArray         |     | 1000 | 5   | 586.504kb | 49.1μs  | ±1.02% |
| MapBench  | benchArrayMapKeysArray     |     | 1000 | 5   | 619.368kb | 68.1μs  | ±1.01% |
| MapBench  | benchArrayMapList          |     | 1000 | 5   | 582.408kb | 48.0μs  | ±1.42% |
| MapBench  | benchArrayMapKeysList      |     | 1000 | 5   | 619.400kb | 69.3μs  | ±0.96% |
+-----------+----------------------------+-----+------+-----+-----------+---------+--------+
<?php declare(strict_types=1);
namespace GraphQL\Benchmarks;
function identity($value, $key = null)
{
return $value;
}
/**
* @BeforeMethods({"setUp"})
* @OutputTimeUnit("microseconds", precision=1)
* xWarmup(2)
* @Revs(1000)
* @Iterations(5)
* @RetryThreshold(2.0)
*/
class MapBench
{
private static array $array;
private static array $list;
public function setUp(): void
{
self::$list = array_fill(0, 1000, 'abcd');
$keys = array_map(fn($x) => 'key' . $x, range(0, 999));
self::$array = array_fill_keys($keys, 'abcd');
}
public function benchUtilsMapArray(): void
{
$result = self::map(self::$array, '\GraphQL\Benchmarks\identity');
}
public function benchUtilsMapOldArray(): void
{
$result = self::mapOld(self::$array, '\GraphQL\Benchmarks\identity');
}
public function benchUtilsMapList(): void
{
$result = self::map(self::$list, '\GraphQL\Benchmarks\identity');
}
public function benchUtilsMapOldList(): void
{
$result = self::mapOld(self::$list, '\GraphQL\Benchmarks\identity');
}
public function benchUtilsForeachArray(): void
{
$result = [];
foreach (self::$array as $value) {
$result[] = identity($value);
}
}
public function benchUtilsForeachKeysArray(): void
{
$result = [];
foreach (self::$array as $key => $value) {
$result[$key] = identity($value, $key);
}
}
public function benchUtilsForeachList(): void
{
$result = [];
foreach (self::$list as $value) {
$result[] = identity($value);
}
}
public function benchUtilsForeachKeysList(): void
{
$result = [];
foreach (self::$list as $key => $value) {
$result[$key] = identity($value, $key);
}
}
public function benchArrayMapArray(): void
{
$result = array_map('\GraphQL\Benchmarks\identity', self::$array);
}
public function benchArrayMapKeysArray(): void
{
$result = array_map('\GraphQL\Benchmarks\identity', self::$array, array_keys(self::$array));
}
public function benchArrayMapList(): void
{
$result = array_map('\GraphQL\Benchmarks\identity', self::$list);
}
public function benchArrayMapKeysList(): void
{
$result = array_map('\GraphQL\Benchmarks\identity', self::$list, array_keys(self::$array));
}
public static function map(iterable $iterable, callable $fn): array
{
$map = [];
foreach ($iterable as $key => $value) {
$map[$key] = $fn($value, $key);
}
return $map;
}
public static function mapOld($iterable, callable $fn): array
{
self::invariant(
is_array($iterable) || $iterable instanceof \Traversable,
__METHOD__ . ' expects array or Traversable'
);
$map = [];
foreach ($iterable as $key => $value) {
$map[$key] = $fn($value, $key);
}
return $map;
}
public static function invariant($test, $message = ''): void
{
if ($test) {
return;
}
throw new \Exception();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment