用微时间测量持续时间随机结果为零

Measuring a duration with microtime results randomly in zero

我有一个这样的循环:

<?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) 命令的行,则没有零持续时间。

系统设置

我是 运行 CLI 上的循环并通过浏览器调用它。

数组中的 101 项对于聪明的 php 来说足够小,因为它有 static optimization 的技巧和强大的 cpu.

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

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

P.S。我已经使用 7.1 和 5.6 检查了您的代码,因此存在很大差异:

除了@num8er 的回答,这似乎是答案,我试图了解更多,因为这真的让我有些不眠之夜。我稍微改进了上面的脚本和 运行 一些额外的测量值:

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

我添加了一个 运行dom "fake feature"。随机 25% 的迭代不应该 return 一个肯定的搜索结果。并且在 运行dom 50% 的迭代中,针将被放置在大海捞针的中间而不是末端。 我针对不同的设置(迭代数组长度)多次运行这个脚本,最后我得到了大约 225.000 个结果行。快速添加一个小枢轴 table 显示,其中 PHP (7.0.32 fpm 和 CPU (Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50 GHz) 达到极限:

数字是毫秒/1000,所以即使是困难的(如 500.000 个键,1.000 次迭代)也需要 0,000000953674 微秒 - 感谢优化。厉害了。

有趣的是:最短持续时间(如果不是“0”)是相同的 (0,000953674) 或 加倍 (0,000001907349),即使是不同的迭代!所以,我的假设是,但这是非常幼稚的想法,如果我 运行 使用更大的数组或更多迭代进行测试,下一个即将到来的最小值将是 0.00000381469 微秒.

正如您也看到的,正如 num8er 已经指出的那样,优化的潜力越大,工作越难。

10 次爬行长度为 50.000 个键的数组比 100 或 1.000 次迭代还要慢。在 1.000 次迭代中,超过 10% 的结果是在 "optimized" 时间内交付的。

最后,我想指出,是在大海捞针的中间,还是在大海捞针的尽头,似乎没有什么区别。下一个图表显示了搜索 500.000 键数组时 10、100 和 1.000 次迭代的最小持续时间。如您所见,最小值始终是 "magical" 0,000000953674:

不用说,每次迭代 return 都是正确的结果。因此,in_array() 从来没有 return 得到肯定的结果,当它爬行到没有针的大海捞针阵列时。

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