php array 性能,php in_array的低性能

PS:原创文章,如需转载,请注明出处,谢谢!

PHP7最近推出了,首要说的就是性能方面的提升。对于in_array()一直诟病很多,至于性能有多差,先简单测试一下,看看数据。

测试程序如下:

/**

* 获取当前时间戳(毫秒级)

* @return float

*/

function microtime_float(){

list($usec, $sec) = explode(' ', microtime());

return ((float)$usec + (float)$sec);

}

/**

* 数组初始化

*/

$int_arr = $str_arr = [];

for($i=0; $i<200000; $i++){

$int_arr[] = $i;

$str_arr[] = "{$i}";

}

$time_start = microtime_float();

// 具体操作

for($j=0; $j<3000; $j++){

if(in_array(18000, $int_arr)){

continue;

}

// if(isset($int_arr[$key])){

// continue;

// }

}

$time_end = microtime_float();

echo '消耗时间:'.($time_end - $time_start);

测试结果

in_array 方式

1. 字符型字符串

// 3k 消耗时间:1.0687351226807

// 3w 消耗时间:10.569030046463

2. int 型字符串

// 3k 消耗时间:1.0500609874725

// 3w 消耗时间:10.290988922119

isset 方式

1. 字符型字符串

// 3k 消耗时间:0.00010299682617188

// 3w 消耗时间:0.00089907646179199

2. int 型字符串

// 3k 消耗时间:0.00010108947753906

// 3w 消耗时间:0.00085687637329102

结合上面测试数据,两种方式的性能差距还是挺明显的。

利用ltrace来跟踪进程调用库函数的情况:

$ ltrace -c /usr/local/php/bin/php test.php

50161b46e6ddd9ea857cdb5b125069c7.png

看到库函数__strtol_internal的调用非常之频繁,这个库函数__strtol_internal是原来是strtol的别名,简单的说就是把字符串转换成长整形,可以推测PHP引擎已经检测到这是一个字符串型的数字,所以期望将他们转换成长整型来比较,这个转换过程中消耗了太多时间,我们再次执行:

$ ltrace -e "__strtol_internal" /usr/local/php/bin/php test.php

可以轻松抓到大量下图这样的调用,到此,问题找到了,in_array这种松比较,会将两个字符型数字串先转换为长整型再进行比较,却不知性能就耗在这上面了。

b7275b9e2601d6186d9c3b75329184cd.png知道了症结所在,我们解决的办法就很多了,最简单的就是为in_array加第三个参数为true,即变为严格比较,同时还要比较类型,这样避免了PHP自作聪明的转换类型,跑起来果然快多了,代码如下:

in_array(search,array,type)

参考上例,如改为:

in_array(18000, $int_arr, true);

in_array('18000', $str_arr, true);

分别执行3k次的消耗时间分别为:0.88052606582642、0.8897430896759

总结一下,大数组的查询,用in_array函数是个糟糕的选择。应该尽量用isset函数来替代 。in_array函数的复杂度是O(n),而isset函数的复杂度是O(1)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值