为了账号安全,请及时绑定邮箱和手机立即绑定

什么更快:in_array或isset?

什么更快:in_array或isset?

尚方宝剑之说 2019-11-14 09:44:35
这个问题对我来说只是个问题,因为我一直喜欢编写优化的代码,这些代码也可以在廉价的慢速服务器(或具有大量流量的服务器)上运行我环顾四周,却找不到答案。我想知道在这两个示例之间有什么更快的方法,请记住在我的情况下数组的键并不重要(自然是伪代码):<?php$a = array();while($new_val = 'get over 100k email addresses already lowercased'){    if(!in_array($new_val, $a){        $a[] = $new_val;        //do other stuff    }}?><?php$a = array();while($new_val = 'get over 100k email addresses already lowercased'){    if(!isset($a[$new_val]){        $a[$new_val] = true;        //do other stuff    }}?>因为问题的关键不是数组冲突,所以我想补充一点,如果您担心冲突的插入$a[$new_value],可以使用$a[md5($new_value)]。它仍然可能导致冲突,但是当从用户提供的文件中读取时,它可以避免可能的DoS攻击(http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html)
查看完整描述

3 回答

?
慕运维8079593

TA贡献1876条经验 获得超5个赞

哪个更快:isset()vsin_array()


isset() 是比较快的。


显而易见,isset()仅测试单个值。而in_array()将遍历整个数组,测试每个元素的值。


粗略的基准测试很容易使用microtime()。


结果:

Total time isset():    0.002857

Total time in_array(): 0.017103

注意:无论是否存在,结果都是相似的。


码:

<?php

$a = array();

$start = microtime( true );


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

    isset($a['key']);

}


$total_time = microtime( true ) - $start;

echo "Total time: ", number_format($total_time, 6), PHP_EOL;


$start = microtime( true );


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

    in_array('key', $a);

}


$total_time = microtime( true ) - $start;

echo "Total time: ", number_format($total_time, 6), PHP_EOL;


exit;


查看完整回答
反对 回复 2019-11-14
?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

使用isset()可以提高查找速度,因为它使用哈希表,从而避免了O(n)搜索。


首先使用djb哈希函数对密钥进行哈希处理,以确定中类似哈希密钥的存储桶O(1)。然后重复搜索该存储桶,直到在中找到确切的密钥O(n)。


除非有任何有意的哈希冲突,这种方法产生的性能要比更好in_array()。


请注意,isset()按照显示的方式使用时,将最终值传递给另一个函数需要使用array_keys()创建一个新数组。通过将数据存储在键和值中,可能会造成内存折衷。


更新资料


查看代码设计决策如何影响运行时性能的好方法,可以查看脚本的编译版本:


echo isset($arr[123])


compiled vars:  !0 = $arr

line     # *  op                           fetch      ext  return  operands

-----------------------------------------------------------------------------

   1     0  >   ZEND_ISSET_ISEMPTY_DIM_OBJ              2000000  ~0      !0, 123

         1      ECHO                                                 ~0

         2    > RETURN                                               null

echo in_array(123, $arr)


compiled vars:  !0 = $arr

line     # *  op                           fetch      ext  return  operands

-----------------------------------------------------------------------------

   1     0  >   SEND_VAL                                             123

         1      SEND_VAR                                             !0

         2      DO_FCALL                                 2  $0      'in_array'

         3      ECHO                                                 $0

         4    > RETURN                                               null

不仅in_array()使用效率相对较低的O(n)搜索,还需要将其称为函数(DO_FCALL),而为此isset()使用单个操作码(ZEND_ISSET_ISEMPTY_DIM_OBJ)。


查看完整回答
反对 回复 2019-11-14
  • 3 回答
  • 0 关注
  • 775 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信