foreach的性能,带有lambda的array_map和带有静态函数的array_map

foreach的性能,带有lambda的array_map和带有静态函数的array_map

这三种方法之间的性能差异(如果有的话)是什么,都用于将数组转换为另一个数组?

  1. 运用 foreach

  2. 使用array_maplambda / closure函数

  3. 使用array_map'静态'功能/方法

  4. 还有其他方法吗?

为了使自己清楚,让我们看看这些例子,都做同样的事情 - 将数字数组乘以10:

$numbers = range(0, 1000);

的foreach

$result = array();foreach ($numbers as $number) {
    $result[] = $number * 10;}return $result;

用lambda映射

return array_map(function($number) {
    return $number * 10;}, $numbers);

使用'static'函数映射,作为字符串引用传递

function tenTimes($number) {
    return $number * 10;}return array_map('tenTimes', $numbers);

还有其他方法吗?我将很高兴听到上述案例之间的所有差异,以及为什么应该使用一个而不是其他案例的任何输入。


函数式编程
浏览 635回答 3
3回答

哔哔one

FWIW,我刚刚做了基准,因为海报没有这样做。在PHP 5.3.10 + XDebug上运行。更新2015-01-22与mcfedr的答案进行比较,以获得没有XDebug和更新的PHP版本的其他结果。function lap($func) {   $t0 = microtime(1);   $numbers = range(0, 1000000);   $ret = $func($numbers);   $t1 = microtime(1);   return array($t1 - $t0, $ret);}function useForeach($numbers)  {   $result = array();   foreach ($numbers as $number) {       $result[] = $number * 10;   }   return $result;}function useMapClosure($numbers) {   return array_map(function($number) {       return $number * 10;   }, $numbers);}function _tenTimes($number) {     return $number * 10;}function useMapNamed($numbers) {   return array_map('_tenTimes', $numbers);}foreach (array('Foreach', 'MapClosure', 'MapNamed') as $callback) {   list($delay,) = lap("use$callback");   echo "$callback: $delay\n";}在十几次尝试中,我获得了非常一致的结果,包括1M数字:Foreach:0.7秒关闭地图:3.4秒功能名称上的映射:1.2秒。假设关闭时地图的速度低迷是因为关闭可能每次都被评估,我也测试过这样:function useMapClosure($numbers) {   $closure = function($number) {     return $number * 10;   };   return array_map($closure, $numbers);}但结果是相同的,证实封闭只评估一次。以下是三个回调的操作码转储。第一useForeach():compiled vars:  !0 = $numbers, !1 = $result, !2 = $numberline     # *  op                           fetch          ext  return  operands---------------------------------------------------------------------------------  10     0  >   EXT_NOP                                                           1      RECV                                                     1  11     2      EXT_STMT                                                          3      INIT_ARRAY                                       ~0               4      ASSIGN                                                   !1, ~0  12     5      EXT_STMT                                                          6    > FE_RESET                                         $2      !0, ->15         7  > > FE_FETCH                                         $3      $2, ->15         8  >   OP_DATA                                                           9      ASSIGN                                                   !2, $3  13    10      EXT_STMT                                                         11      MUL                                              ~6      !2, 10        12      ASSIGN_DIM                                               !1        13      OP_DATA                                                  ~6, $7  14    14    > JMP                                                      ->7        15  >   SWITCH_FREE                                              $2  15    16      EXT_STMT                                                         17    > RETURN                                                   !1  16    18*     EXT_STMT                                                         19*   > RETURN                                                   null那么 useMapClosure()compiled vars:  !0 = $numbersline     # *  op                           fetch          ext  return  operands---------------------------------------------------------------------------------  18     0  >   EXT_NOP                                                           1      RECV                                                     1  19     2      EXT_STMT                                                          3      EXT_FCALL_BEGIN                                                   4      DECLARE_LAMBDA_FUNCTION                                  '%00%7Bclosure%7D%2Ftmp%2Flap.php0x7f7fc1424173'  21     5      SEND_VAL                                                 ~0         6      SEND_VAR                                                 !0         7      DO_FCALL                                      2  $1      'array_map'         8      EXT_FCALL_END                                                     9    > RETURN                                                   $1  22    10*     EXT_STMT                                                         11*   > RETURN                                                   null它调用的闭包:compiled vars:  !0 = $numberline     # *  op                           fetch          ext  return  operands---------------------------------------------------------------------------------  19     0  >   EXT_NOP                                                           1      RECV                                                     1  20     2      EXT_STMT                                                          3      MUL                                              ~0      !0, 10         4    > RETURN                                                   ~0  21     5*     EXT_STMT                                                          6*   > RETURN                                                   null那么useMapNamed()功能:compiled vars:  !0 = $numbersline     # *  op                           fetch          ext  return  operands---------------------------------------------------------------------------------  28     0  >   EXT_NOP                                                           1      RECV                                                     1  29     2      EXT_STMT                                                          3      EXT_FCALL_BEGIN                                                   4      SEND_VAL                                                 '_tenTimes'         5      SEND_VAR                                                 !0         6      DO_FCALL                                      2  $0      'array_map'         7      EXT_FCALL_END                                                     8    > RETURN                                                   $0  30     9*     EXT_STMT                                                         10*   > RETURN                                                   null以及它调用的命名函数_tenTimes():compiled vars:  !0 = $numberline     # *  op                           fetch          ext  return  operands---------------------------------------------------------------------------------  24     0  >   EXT_NOP                                                           1      RECV                                                     1  25     2      EXT_STMT                                                          3      MUL                                              ~0      !0, 10         4    > RETURN                                                   ~0  26     5*     EXT_STMT                                                          6*   > RETURN                                                   null

喵喵时光机

这真有趣。但是我从以下代码得到了相反的结果,这些代码从我当前的项目中简化了://&nbsp;test&nbsp;a&nbsp;simple&nbsp;array_map&nbsp;in&nbsp;the&nbsp;real&nbsp;world.function&nbsp;test_array_map($data){ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array_map(function($row){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'productId'&nbsp;=>&nbsp;$row['id']&nbsp;+&nbsp;1, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'productName'&nbsp;=>&nbsp;$row['name'], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'desc'&nbsp;=>&nbsp;$row['remark'] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;$data);}//&nbsp;Another&nbsp;with&nbsp;local&nbsp;variable&nbsp;$ifunction&nbsp;test_array_map_use_local($data){ &nbsp;&nbsp;&nbsp;&nbsp;$i&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array_map(function($row)&nbsp;use&nbsp;($i)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$i++; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'productId'&nbsp;=>&nbsp;$row['id']&nbsp;+&nbsp;$i, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'productName'&nbsp;=>&nbsp;$row['name'], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'desc'&nbsp;=>&nbsp;$row['remark'] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;$data);}//&nbsp;test&nbsp;a&nbsp;simple&nbsp;foreach&nbsp;in&nbsp;the&nbsp;real&nbsp;worldfunction&nbsp;test_foreach($data){ &nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($data&nbsp;as&nbsp;$row)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp['productId']&nbsp;=&nbsp;$row['id']&nbsp;+&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp['productName']&nbsp;=&nbsp;$row['name']; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp['desc']&nbsp;=&nbsp;$row['remark']; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result[]&nbsp;=&nbsp;$tmp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result;}//&nbsp;Another&nbsp;with&nbsp;local&nbsp;variable&nbsp;$ifunction&nbsp;test_foreach_use_local($data){ &nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;$i&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($data&nbsp;as&nbsp;$row)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$i++; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp['productId']&nbsp;=&nbsp;$row['id']&nbsp;+&nbsp;$i; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp['productName']&nbsp;=&nbsp;$row['name']; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmp['desc']&nbsp;=&nbsp;$row['remark']; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result[]&nbsp;=&nbsp;$tmp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result;}这是我的测试数据和代码:$data&nbsp;=&nbsp;array_fill(0,&nbsp;10000,&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;'id'&nbsp;=>&nbsp;1, &nbsp;&nbsp;&nbsp;&nbsp;'name'&nbsp;=>&nbsp;'test', &nbsp;&nbsp;&nbsp;&nbsp;'remark'&nbsp;=>&nbsp;'ok'));$tests&nbsp;=&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;'array_map'&nbsp;=>&nbsp;array(), &nbsp;&nbsp;&nbsp;&nbsp;'foreach'&nbsp;=>&nbsp;array(), &nbsp;&nbsp;&nbsp;&nbsp;'array_map_use_local'&nbsp;=>&nbsp;array(), &nbsp;&nbsp;&nbsp;&nbsp;'foreach_use_local'&nbsp;=>&nbsp;array(),);for&nbsp;($i&nbsp;=&nbsp;0;&nbsp;$i&nbsp;<&nbsp;100;&nbsp;$i++){ &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($tests&nbsp;as&nbsp;$testName&nbsp;=>&nbsp;&$records)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$start&nbsp;=&nbsp;microtime(true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call_user_func("test_$testName",&nbsp;$data); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$delta&nbsp;=&nbsp;microtime(true)&nbsp;-&nbsp;$start; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$records[]&nbsp;=&nbsp;$delta; &nbsp;&nbsp;&nbsp;&nbsp;}}//&nbsp;output&nbsp;result:foreach&nbsp;($tests&nbsp;as&nbsp;$name&nbsp;=>&nbsp;&$records)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;printf('%.4f&nbsp;:&nbsp;%s&nbsp;'.PHP_EOL,&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array_sum($records)&nbsp;/&nbsp;count($records),&nbsp;$name);}结果是:0.0098:array_map0.0114:foreach0.0114:array_map_use_local0.0115:foreach_use_local我的测试是在没有xdebug的LAMP生产环境中进行的。我徘徊xdebug会降低array_map的性能。
打开App,查看更多内容
随时随地看视频慕课网APP