在循环期间应用操作与循环完成时的算法性能?

时间:2018-03-30 23:44:12

标签: php algorithm performance optimization

这个问题相当令人困惑,所以让我详细说一下,看下面的两段伪代码片段:

循环和施加

    function moveParticlesAlongCurve(particles,curvePoints){
      particles[0].position.x = curvePoints[i].x;
      particles[0].position.y = curvePoints[i].y;
      setTimeout(function(){ i++; }, 1000);
    }

循环-然后施加:

$numbers = [1, 1, 1]
$final   = 0;
foreach ($numbers as $number) {
  $final = $final + ($number * 0.95);
}

第一个代码段将 95%的每个号码添加到最终号码,第二个代码段添加每个号码的100%,然后一旦完成, 95%

每个结果都会得出相同的结果: 2.85 。但我很好奇性能是否在宏观层面上有所不同。

1 个答案:

答案 0 :(得分:1)

我写了一个简单的测试块并添加了上面的两个变体以及使用array_sum进行循环然后应用的变体。每个函数运行10,000,000次(平均10次迭代,每次1000,000次迭代)。

$tests = [
    function ($numbers) {
        $final   = 0;
        foreach ($numbers as $number) {
            $final = $final + ($number * 0.95);
        }
        return $final;
    },
    function ($numbers) {
        $final   = 0;
        foreach ($numbers as $number) {
            $final = $final + $number;
        }
        return ($final = ($final * 0.95));
    },
    function ($numbers) {
        return array_sum($numbers) * 0.95;
    }
];

$numbers = [1, 1, 1];

$loop = range(1, 1000000);
$reps = range(1,10);

$testRes = [];

foreach($tests as $idx => $test) {

    foreach($reps as $rep) {
        $s = microtime(true);

        foreach($loop as $l) {
            $test($numbers);
        }

        $e = microtime(true);
        if( !isset($testRes[$idx]) ) {
            $testRes[$idx] = [];
        }
        $testRes[$idx][] = $e - $s;
    }

}

foreach($testRes as $idx => $res) {
    $avg = array_sum($res) / count($res);
    print_r("Test {$idx} took an average " . (string) $avg . ' seconds.<br />');
}

结果

// Test 0 took an average 0.1228661775589 seconds.
// Test 1 took an average 0.11786506175995 seconds.
// Test 2 took an average 0.10405595302582 seconds.

测试0是循环和应用功能,耗时最长。 测试1是循环然后应用函数,其速度快了千分之五秒。 测试2是循环然后应用函数,但是使用array_sum而不是脚本化的加法操作,比测试1快一点多于百分之一秒。

为什么呢?为什么循环然后应用比循环和应用更快的答案是简单的数学:你在循环中应用每个数组条目2个数学运算(数组中的3个条目* 2个操作=每个循环6个操作) - 应用示例。将其与循环然后应用函数中每个数组条目的1个数学运算进行比较(数组中的3个条目* 1个操作=每个循环3个操作)。

等等,操作的1/2 ......为什么速度不是快两倍?

PHP有很多开销(例如实际执行部分编译的脚本并不总是完全优化,写入现有变量有开销等等),这就是为什么你看不到一半操作速度的原因

那么为什么array_sum示例最快?它是否与循环然后应用函数相同?原则上,是的。但是,它有一个主要优点 - 循环的部分和从数组中添加值的部分是来自PHP的源代码(用C语言编写)的编译代码,因此它的一部分不必执行部分编译了代码。因此,大多数(但不是全部)内置PHP函数将比使用自己编写相同功能的脚本函数更快。这一切都取决于具体情况和要求。