用微时间测量持续时间会随机产生零

时间:2018-12-03 21:52:46

标签: php duration microtime

我遇到这样的循环:

<?php
ini_set('memory_limit', '16024M');
ini_set('set_time_limit', 9999);
ini_set('max_execution_time', 9999);
ini_set('display_errors',  TRUE);
ini_set('error_reporting',  E_ALL);

for ($k = 1; $k <= 50; $k++) {

    $haystack = array();

    for ($i = 1; $i <= 100; $i++) {

        $randomChar = substr(md5(microtime()),rand(0,26), 1);

        $haystack[] = $randomChar;

    }

    $haystack[] = 'X';

    $startTime = microtime(true);

    // sleep(0);

    $result = in_array('X', $haystack);

    $endTime = microtime(true);

    echo number_format(1000000 * ($endTime - $startTime), 20, ",", " ") . ' ';

 }

这些是输出的前几行:

  

1,90734863281250000000   0,95367431640625000000   1,19209289550781250000   1,90734863281250000000   1,19209289550781250000   0,95367431640625000000   0,95367431640625000000   1,90734863281250000000   0,95367431640625000000   20,02716064453125000000   0,95367431640625000000   1,19209289550781250000   0,95367431640625000000   0,95367431640625000000   0,00000000000000000000   0,95367431640625000000   0,95367431640625000000   0,95367431640625000000   0,00000000000000000000   0,95367431640625000000   0,00000000000000000000

如您所见,有几行说明持续时间为“ 0”-实际上这是不可能的。如果取消对包含 sleep(0)命令的行的注释,则不会存在零持续时间。

系统设置

  • 带有FPM的PHP 7.0
  • nginx 1.10.3
  • Ubuntu 16.04

我正在CLI上运行循环,并通过浏览器进行调用。

2 个答案:

答案 0 :(得分:3)

数组中的101个项目对于static optimization技巧和强大的CPU来说,对于智能php来说已经足够小了。

如果您想看到0-s消失了,请生成1000个项目:

for ($i = 1; $i <= 1000; $i++) {
    $haystack[] = substr(md5(microtime()),rand(0,26), 1);
}

P.S。我已经使用7.1和5.6检查了您的代码,所以有很大的不同:

php7.1 vs php5.6

答案 1 :(得分:0)

除了@ num8er答案(这似乎是THE答案)之外,我还尝试查找更多信息,因为这确实使我无法入睡。我对上述脚本进行了一些改进,并进行了一些其他测量:

  ini_set('memory_limit', '16024M');
  ini_set('set_time_limit', 9999);
  ini_set('set_time_limit', -1);
  ini_set('max_execution_time', 9999);
  ini_set('max_execution_time', -1);
  ini_set('display_errors',  TRUE);
  ini_set('error_reporting', E_ALL);

echo "<table>";
echo "<tr>";
    echo "<th>duration</th>";
    echo "<th>position</th>";
    echo "<th>fake</th>";
    echo "<th>found</th>";
    echo "<th>optimized</th>";
echo "</tr>";

$endPosition = TRUE;

$fake = false;

for ($k = 1; $k <= 10000; $k++) {

    $haystack = array();

    for ($i = 1; $i <= 50000; $i++) {

        $randomChar = substr(md5(microtime()),rand(0,26), 1);

        $haystack[] = $randomChar;

    }

    if ($fake) {

        $needle = NULL;


    } else {

        if ($endPosition) {

            $needle = $haystack[sizeof($haystack) - 1];

        } else {

            $needle = $haystack[floor(sizeof($haystack)/ 2)];

        }

    }

    $startTime = microtime(true);

    //sleep(0);

    $result = in_array($needle, $haystack);

    $endTime = microtime(true);

    $duration = ($endTime - $startTime);

    echo "<tr>";
        echo "<td>";
        echo number_format($duration, 30, ",", " ");
        echo "</td>";
        echo "<td>";
        echo ($endPosition) ? "end": "middle";
        echo "</td>";
        echo "<td>";
        echo ($fake) ? "fake": "no fake";
        echo "</td>";
        echo "<td>";
        echo ($result) ? "found": "not found";
        echo "</td>";
        echo "<td>";
        echo ($duration == 0) ? "optimized": "---";
        echo "</td>";
    echo "</tr>";

    $endPosition = (rand(0,100) < 50) ? TRUE : FALSE;
    $fake = (rand(0,100) < 25) ? TRUE : FALSE;

}

echo "</table>";

我添加了一个随机的“伪造特征”。随机25%的迭代不应返回肯定的搜索结果。并且在随机的50%迭代中,针将放置在干草堆的中间而不是末端。 我针对不同的设置(迭代次数数组长度)多次运行了该脚本,最后我得到了大约225.000个结果行。快速添加一个小的数据透视表,可以看到PHP(7.0.32 fpm和CPU(Intel(R)Xeon(R)CPU E5-2680 v3 @ 2.50GHz)达到极限)

minimum durations when searching arrays, lengths vs iterations

数字是毫秒/ 1000,因此即使是硬数字(如500.000键,1.000迭代)也需要0,000000953674微秒-这要归功于优化。令人印象深刻。

有趣的是:最小持续时间(如果不是“ 0”,则相同)( 0,000953674 )或 doubled 0,000001907349 < / strong>),即使是不同的迭代!因此,我的假设是,但这是一个很幼稚的想法,如果我将运行具有更大数组或更多迭代的测试,那么下一个即将出现的最小值将是 0.00000381469 microseonds

您还可以看到,正如num8er所述,优化的潜力随着工作的增加而增加。

Top 10 of quickest durations for 50.000-key-arrays

对具有50.000个键的长度的数组进行10次爬网甚至慢于100或1.000次迭代。在1.000次迭代中,超过10%的结果是在“优化”时间内交付的。

最后,我想指出的是,如果针头位于干草堆的中间或末端,似乎没有什么区别。下图显示了搜索500.000键数组时10、100和1.000次迭代的最小持续时间。如您所见,最小值始终是“魔术” 0,000000953674:

Minimum durations for 500.000-key-arrays with different needle positions

不用说,每次迭代都会返回正确的结果。因此, in_array()在爬到不带针的干草堆阵列时从未返回阳性结果。

这可能不会为PHP优化功能添加更深层的技术细节,但是我想看到此功能的影响很有趣。