3

我得到了这个代码:

<?php
// Test results
$array1 = test('array_walk');
$array2 = test('array_walk_list_each');
$array3 = test('array_walk_foreach1');
$array4 = test('array_walk_foreach2');

// Check arrays for equal
var_dump($array1 == $array2, $array1 == $array3, $array1 == $array4);

// Test function 1
function array_walk_list_each(&$array, $function, $userData = null) {
    while ( list($key, $value) = each($array) )
        $function($array[$key], $key, $userData);
}

// Test function 2
function array_walk_foreach1(&$array, $function, $userData = null) {
    foreach ($array as $key => &$value )
        $function($value, $key, $userData);
}

// Test function 3
function array_walk_foreach2(&$array, $function, $userData = null) {
    foreach ($array as $key => $value )
        $function($array[$key], $key, $userData);
}

function some_function(&$value, $key, $userData) {
    $value = "$key => $userData";
}

function test($function, $count = 10000, $arrayElements = 1000) {
    echo $function, ' ... ';
    $array = array_fill(0, $arrayElements, "some text value");

    $timer = microtime(true);
    for( $i = 0; ++$i < $count; )
        $function($array, 'some_function', 'some user data');
    printf("%.3f sec\n", microtime(true) - $timer);

    return $array;
}

我很难理解这个输出:

array_walk ... 1.024 sec
array_walk_list_each ... 0.002 sec
array_walk_foreach1 ... 1.135 sec
array_walk_foreach2 ... 1.359 sec
bool(true)
bool(true)
bool(true)

这些功能之间的性能差异几乎是一个笑话。

这怎么可能?难道我做错了什么?

我正在使用 PHP 7.0 从终端运行脚本

4

2 回答 2

2

foreach 在每次运行之前重置内部数组指针,并在每一步中将其向前移动。这意味着您的测试函数将被称为 10 000 000 ,正如您可能期望的那样。Array walk 根本不使用内部指针,但仍然在每次调用时处理每个元素。这就是为什么时间是可比的。

但是每个只是在每次使用后增加内部指针。它永远不会重置它(谷歌手册了解更多信息)。这意味着您只修改一次数组,并且在以后的运行中永远不会进入 while 循环。由于您的 some_function 是幂等的,因此您检查是否通过,但时间要短得多。

编辑添加:重置不必是明确的。考虑这段代码:

function array_walk_list_each_copy(&$array, $function, $userData = null) {
  $a = $array;
  while ( list($key, $value) = each($a) ) 
    $function($array[$key], $key, $userData);
}

每个每次都在数组的副本上工作,并修改副本的内部指针,而不是原始指针。由于写入时复制开销,它不会胜过其他功能,但速度会更慢

于 2017-08-11T22:20:58.440 回答
2

仅仅是因为each()需要重置数组以再次对其进行迭代。所以你在循环函数中有一个执行。而其他人正在迭代它。

http://php.net/manual/en/function.each.php

您的结果将仅产生 1 次迭代,包含 10000 行,而其他结果将产生 10000 次迭代,包含 10000 行。

$array = array_fill(0, 10000, uniqid('', false));
$fill = [];
$fill2 = [];
$timer = microtime(true);
for ($i = 0; $i < 10; $i++) {
    while (list($key, $value) = each($array)) {
        $fill[] = 'value';
    }
}
printf("While list each %.3f sec\n", microtime(true) - $timer);
$timer = microtime(true);
for ($i = 0; $i < 10; $i++) {
    foreach ($array as $key => $value) {
        $fill2[] = 'value';
    }
}
printf("Foreach %.3f sec\n", microtime(true) - $timer);
var_dump(count($fill), count($fill2));

结果:https ://3v4l.org/bvNdO


要为所有函数获得相同的结果,您需要更改array_walk_list_each函数。

 while ( list($key, $value) = each($array) ){
    $function($array[$key], $key, $userData);
 }
 reset($array);
于 2017-08-11T22:21:09.613 回答