我一直认为in_array
严格模式会比非严格模式更快或更慢。但是在进行一些基准测试后,我发现在搜索整数时,它们之间的执行时间存在巨大差异。字符串和数组测试表明严格模式更快。为什么?
测试代码-(PHP 7.2.1):
<?php
$array = array_fill(0, 10000, 12345);
for ($i=0; $i<100000; $i++) {
in_array($i, $array, true);
}
时间php test.php
php -c test.php 12.98s用户0.04s系统98%cpu 13.234总
<?php
$array = array_fill(0, 10000, 12345);
for ($i=0; $i<100000; $i++) {
in_array($i, $array, false);
}
时间php test.php
php -c test.php 6.44s用户0.04s系统99%cpu 6.522总计
答案 0 :(得分:4)
通过对in_array
的C源代码进行跟踪,我可以提供一些小见识。
事实证明,比较整数时,达到非严格模式的实际相等性检查的路径比严格模式要少。
如果strict
的{{1}}标志为true,则会发生以下情况:
We call fast_is_identical_function
for each element in the array
fast_is_identical_function
首先
测试每个操作数的类型是否不同(in_array
),以期能够尽早返回Z_TYPE_P(op1) != Z_TYPE_P(op2)
;这是比较#1 。
如果类型相同(以您的测试用例为准),则我们测试false
;我不知道这是做什么的,但这是比较#2 。
在两次比较后得出我们的第一个函数调用(Z_TYPE_P(op1) <= IS_TRUE
,we jump into zend_is_identical
。
zend_is_identical
首先通过 测试Z_TYPE_P(op1) != Z_TYPE_P(op2)
开始,这是另一种尽早失败的尝试。这是比较#3 。
如果类型相同,我们可以通过false
语句比较#4
最后我们到达比较Z_LVAL_P(op1) == Z_LVAL_P(op2)
,该比较实际上测试了两个值比较#5 的相等性。
总共,要测试数组的每个元素是否等于我们要搜索的值,有5个比较和1个函数调用。
通过比较,专门用于整数(真的switch (Z_TYPE_P(op1))
s)的非严格流要简单得多,如下所示:
代替数组中的每个元素的LONG
,we instead use fast_equal_check_function
。
方法fast_equal_check_function
开始了一个比较复杂的过程,该过程将两个值与各种类型转换逻辑进行比较。但是,它的 first 测试确实针对整数进行了优化,如下所示:
fast_is_identical_function
我们可以看到它...
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
return Z_LVAL_P(op1) == Z_LVAL_P(op2);
的类型是否为op1
,然后LONG
的类型是否为op2
,然后LONG
的结果对于非严格情况,总共有3个简单相等比较和0个函数调用,而对于严格情况,至少有 5个比较和1个跳转。
在这种情况下,尝试进行早期优化会使严格检查变得更慢(通过反复测试操作数的类型,希望我们能够更快找到不等式),而不是特定的非严格情况比较两个整数。
答案 1 :(得分:1)
似乎与针和/或干草堆中的元素类型有关,请注意:
来自http://sandbox.onlinephpfunctions.com/的PHP 7.3.5
$iterations = 10000000;
$needle = false;
$haystack = [ true ];
$start = microtime( true );
for( $i = 0; $i < $iterations; ++$i )
{
in_array( $needle, $haystack, true );
}
echo ( microtime( true ) - $start ).' strict'.PHP_EOL;
$start = microtime( true );
for( $i = 0; $i < $iterations; ++$i )
{
in_array( $needle, $haystack, false );
}
echo ( microtime( true ) - $start ).' not strict';
产生:
0.29996585845947 strict
0.40397191047668 not strict
但是如果我们使用:
$needle = 1;
$haystack = [ 2 ];
然后我们得到:
0.34480714797974 strict
0.28275084495544 not strict
但是,PHP 5.6.29产生的差异可以忽略不计,并且多次运行相同的测试可以使严格严格于非严格,反之亦然。