Skip to content

Instantly share code, notes, and snippets.

@crhg
Last active November 16, 2017 07:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crhg/45c1f73ca59c9b0f6274412019b19fca to your computer and use it in GitHub Desktop.
Save crhg/45c1f73ca59c9b0f6274412019b19fca to your computer and use it in GitHub Desktop.
<?php
$d = range(1, 20000);
$t0 = microtime(true);
$r = array_reduce(
$d,
function (&$carry, $item) {
$carry []= $item;
return $carry;
},
[]
);
printf("%fms\n", (microtime(true) - $t0) * 1000);
<?php
function my_reduce($array, $func, $init)
{
$result = $init;
foreach ($array as $item) {
$result = $func($result, $item);
}
return $result;
}
$d = range(1, 20000);
$t0 = microtime(true);
$r = my_reduce(
$d,
function (&$carry, $item) {
$carry []= $item;
return $carry;
},
[]
);
printf("%fms\n", (microtime(true) - $t0) * 1000);
@bostin
Copy link

bostin commented Nov 16, 2017

正在艰苦地入门c语言及php c源码学习中....

看了下php的源码,一点个人的想法:

  1. zend引擎在执行函数的时候,会检查函数的参数是否要求是按照引用传参数。如果函数的定义要求按引用传参数,但是实际调用的时候却不是按照引用传参的话,zend引擎在执行函数之前,会自动帮你创建一个引用类型的值来替换原来的参数。
  2. php代码的普通赋值操作,只要没有改变原来的值,就可以简单地理解为是一个引用
    参考:(写时复制)
    https://github.com/pangudashu/php7-internal/blob/master/2/zval.md#213-%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86
    https://www.cnblogs.com/lonelyxmas/p/4205183.html

基于上面的两点

对于array_reduce:
在每次reduce完成之后,php内核会进行一次数据的拷贝,即将当前reduce的结果拷贝为下次reduce的初始值。
对于my_reduce:
在每次foreach的循环中,$result = $func($result, $item); 前面的$result其实和$func参数中的$result都是指向同一个内存地址。

所以,我个人的看法是,my_reduce胜在2000次循环一值都在操作同一个内存地址,少了对内存的一系列操作。而array_reduce则每完成一次循环,则需要进行一次内存数据的拷贝。

你可以试试看把你的test_my_reduce.php第17行的地址引用符&去掉之后,再测试看看,这时候my_reduce和array_reduce应该就参不多了(实际应该是array_reduce略快,毕竟是c实现的嘛...)

上面仅仅是个人的一点点看法,如果理解的不对,还请见谅,欢迎一起学习交流

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment