php 什么更快:in_array 或isset?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13483219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 05:32:58  来源:igfitidea点击:

what is faster: in_array or isset?

phpperformancemicro-optimization

提问by Fabrizio

This question is merely for me as I always like to write optimized code that can run also on cheap slow servers (or servers with A LOT of traffic)

这个问题仅适用于我,因为我总是喜欢编写优化的代码,这些代码也可以在廉价的慢速服务器(或具有大量流量的服务器)上运行

I looked around and I was not able to find an answer. I was wondering what is faster between those two examples keeping in mind that the array's keys in my case are not important (pseudo-code naturally):

我环顾四周,找不到答案。我想知道这两个示例之间哪个更快,记住在我的情况下数组的键并不重要(自然是伪代码):

<?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
    }
}
?>

As the point of the question is not the array collision, I would like to add that if you are afraid of colliding inserts for $a[$new_value], you can use $a[md5($new_value)]. it can still cause collisions, but would take away from a possible DoS attack when reading from an user provided file (http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html)

由于问题的重点不是数组冲突,我想补充一点,如果您害怕插入冲突$a[$new_value],可以使用$a[md5($new_value)]. 它仍然会导致冲突,但在读取用户提供的文件时会避免可能的 DoS 攻击(http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html

回答by David Harkness

The answers so far are spot-on. Using issetin this case is faster because

到目前为止,答案是准确的。isset在这种情况下使用速度更快,因为

  • It uses an O(1) hash search on the key whereas in_arraymust check every value until it finds a match.
  • Being an opcode, it has less overhead than calling the in_arraybuilt-in function.
  • 它对键使用 O(1) 哈希搜索,而in_array必须检查每个值直到找到匹配项。
  • 作为操作码,它比调用in_array内置函数的开销更少。

These can be demonstrated by using an array with values (10,000 in the test below), forcing in_arrayto do more searching.

这些可以通过使用带有值的数组(在下面的测试中为 10,000)来证明,强制in_array执行更多搜索。

isset:    0.009623
in_array: 1.738441

This builds on Jason's benchmark by filling in some random values and occasionally finding a value that exists in the array. All random, so beware that times will fluctuate.

这建立在 Jason 的基准测试上,通过填充一些随机值并偶尔找到存在于数组中的值。都是随机的,所以要注意时间会波动。

$a = array();
for ($i = 0; $i < 10000; ++$i) {
    $v = rand(1, 1000000);
    $a[$v] = $v;
}
echo "Size: ", count($a), PHP_EOL;

$start = microtime( true );

for ($i = 0; $i < 10000; ++$i) {
    isset($a[rand(1, 1000000)]);
}

$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(rand(1, 1000000), $a);
}

$total_time = microtime( true ) - $start;
echo "Total time: ", number_format($total_time, 6), PHP_EOL;

回答by Jason McCreary

Which is faster: isset()vs in_array()

哪个更快:isset()vsin_array()

isset()is faster.

isset()是比较快的。

While it should be obvious, isset()only tests a single value. Whereas in_array()will iterate over the entire array, testing the value of each element.

虽然应该很明显,但isset()只测试单个值。而in_array()将遍历整个数组,测试每个元素的值。

Rough benchmarking is quite easy using microtime().

使用microtime().

Results:

结果:

Total time isset():    0.002857
Total time in_array(): 0.017103

Note:Results were similar regardless if existed or not.

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

Code:

代码:

<?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;

Additional Resources

其他资源

I'd encourage you to also look at:

我鼓励你也看看:

回答by Ja?ck

Using isset()takes advantage of speedier lookup because it uses a hash table, avoiding the need for O(n)searches.

Usingisset()利用了更快的查找,因为它使用了一个哈希表,避免了O(n)搜索的需要。

The key is hashed first using the djb hash functionto determine the bucket of similarly hashed keys in O(1). The bucket is then searched iteratively until the exact key is found in O(n).

首先使用djb 散列函数对键进行散列,以确定 中类似散列的键的桶O(1)。然后迭代搜索桶,直到在 中找到确切的键O(n)

Barring any intentional hash collisions, this approach yields much better performance than in_array().

除非有任何有意的散列冲突,否则这种方法会产生比in_array().

Note that when using isset()in the way that you've shown, passing the final values to another function requires using array_keys()to create a new array. A memory compromise can be made by storing the data in both the keys and values.

请注意,isset()以您显示的方式使用时,将最终值传递给另一个函数需要使用array_keys()来创建新数组。可以通过将数据存储在键和值中来进行内存妥协。

Update

更新

A good way to see how your code design decisions affect runtime performance, you can check out the compiled versionof your script:

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

echo isset($arr[123])

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)

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  ##代码##      'in_array'
         3      ECHO                                                 ##代码##
         4    > RETURN                                               null

Not only does in_array()use a relatively inefficient O(n)search, it also needs to be called as a function (DO_FCALL) whereas isset()uses a single opcode (ZEND_ISSET_ISEMPTY_DIM_OBJ) for this.

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

回答by Mike Brant

The second would be faster, as it is looking only for that specific array key and does not need to iterate over the entire array until it is found (will look at every array element if it is not found)

第二个会更快,因为它只查找特定的数组键并且不需要遍历整个数组直到找到它(如果找不到,将查看每个数组元素)