什么是最快的?循环内部或外部的条件?

h2o*_*ooo 7 php performance foreach for-loop performance-testing

什么是最快的?要根据循环内部或外部循环之外的变量做一个条件,或者它是否重要(编译器是否为你做了),或者你应该使用完全不同的变通方法?

示例#1中包含循环内的条件(单个foreach):

$test = 2;  
foreach ($list as $listItem) {
    if ($test == 1) {
        $listItem .= " - one";
    } else if ($test == 2) {
        $listItem .= " - two";
    } else if ($test == 3) {
        $listItem .= " - three";
    }
}
Run Code Online (Sandbox Code Playgroud)

示例#2,循环外的条件(多个foreach的丑陋):

$test = 2;  
if ($test == 1) {
    foreach ($list as $listItem) {
        $listItem .= " - one";
    }
} else if ($test == 2) {
    foreach ($list as $listItem) {
        $listItem .= " - two";
    }
} else if ($test == 3) {
    foreach ($list as $listItem) {
        $listItem .= " - three";
    }
}
Run Code Online (Sandbox Code Playgroud)

h2o*_*ooo 11

正如您可能已经猜到的那样,示例#2更快,并且编译器不会为您执行此操作.

概观

条件内部或外部循环图


性能测试

示例#1,循环内部的条件:

Time taken: 0.2501 seconds
Time taken: 0.2336 seconds
Time taken: 0.2335 seconds
Time taken: 0.2319 seconds
Time taken: 0.2337 seconds 
Average:    0.2364 seconds
Run Code Online (Sandbox Code Playgroud)

和代码:

<?php
    $list = array();
    for ($i = 0; $i < 1000000; $i++) {
        $list[] = md5(rand(0, 100000) * $i);
    }
    $a = microtime(true);
    $test = 2;
    foreach ($list as $listItem) {
        if ($test == 1) {
            $listItem .= " - one";
        } else if ($test == 2) {
            $listItem .= " - two";
        } else if ($test == 3) {
            $listItem .= " - three";
        }
    }
    echo "Time taken: " . number_format(microtime(true) - $a, 4) . " seconds";
?>
Run Code Online (Sandbox Code Playgroud)

示例#2,循环外的条件:

Time taken: 0.1424 seconds
Time taken: 0.1426 seconds
Time taken: 0.1364 seconds
Time taken: 0.1348 seconds
Time taken: 0.1347 seconds
Average:    0.1382 seconds
Run Code Online (Sandbox Code Playgroud)

和代码:

<?php
    $list = array();
    for ($i = 0; $i < 1000000; $i++) {
        $list[] = md5(rand(0, 100000) * $i);
    }
    $a = microtime(true);
    $test = 2;
    if ($test == 1) {
        foreach ($list as $listItem) {
            $listItem .= " - one";
        }
    } else if ($test == 2) {
        foreach ($list as $listItem) {
            $listItem .= " - two";
        }
    } else if ($test == 3) {
        foreach ($list as $listItem) {
            $listItem .= " - three";
        }
    }
    echo "Time taken: " . number_format(microtime(true) - $a, 4) . " seconds";
?>
Run Code Online (Sandbox Code Playgroud)

好吧,对于循环之外的条件来说,这是一个非常明显的胜利,但如果我们尝试与布尔值而不是int进行比较呢?

示例#3,循环内部条件,但使用布尔值进行调整:

Time taken: 0.1845 seconds
Time taken: 0.1821 seconds
Time taken: 0.1745 seconds
Time taken: 0.1777 seconds
Time taken: 0.1767 seconds
Average:    0.1791 seconds
Run Code Online (Sandbox Code Playgroud)

和代码:

<?php
    $list = array();
    for ($i = 0; $i < 1000000; $i++) {
        $list[] = md5(rand(0, 100000) * $i);
    }
    $a = microtime(true);
    $test = 2;
    $result1 = ($test == 1);
    $result2 = ($test == 2);
    $result3 = ($test == 3);
    foreach ($list as $listItem) {
        if ($result1) {
            $listItem .= " - one";
        } else if ($result2) {
            $listItem .= " - two";
        } else if ($result3) {
            $listItem .= " - three";
        }
    }
    echo "Time taken: " . number_format(microtime(true) - $a, 4) . " seconds";
?>
Run Code Online (Sandbox Code Playgroud)

有趣.如果我们使用内置函数array_walk如何?

示例#4 array_walk,:

Time taken: 0.4950 seconds
Time taken: 0.4946 seconds
Time taken: 0.4947 seconds
Time taken: 0.4937 seconds
Time taken: 0.4918 seconds
Average:    0.4940 seconds
Run Code Online (Sandbox Code Playgroud)

和代码:

<?php
    function append_string($value, $suffix) {
        return $value . $suffix;
    }

    $list = array();
    for ($i = 0; $i < 1000000; $i++) {
        $list[] = md5(rand(0, 100000) * $i);
    }
    $a = microtime(true);
    $test = 2;
    if ($test == 1) {
        array_walk($list, "append_string", " - one");
    } else if ($test == 2) {
        array_walk($list, "append_string", " - two");
    } else if ($test == 3) {
        array_walk($list, "append_string", " - three");
    }
    echo "Time taken: " . number_format(microtime(true) - $a, 4) . " seconds";
?>
Run Code Online (Sandbox Code Playgroud)

什么?! 您可能认为内置函数会将其抽象为C或C++函数,并且可能非常好,但问题是函数调用使此方法非常慢.


优点缺点

示例#1专业人员

  • 您不必多次声明循环(如果您有多个条件,这可能会很烦人)

示例#1缺点

  • 它是前3个测试中最慢的一个(比例子#2慢71%,比例子#3慢32%)

例#2专业人士

  • 所有这些中最快的一个

例2#cons

  • 它要求您多次声明循环(与您拥有的条件数量一样多)

例#3专业人士

  • 您不必多次声明循环,就像示例#1中一样
  • 它比#example 1

例#3缺点

  • 它仍然比#example 2慢(约30%)
  • 它看起来更乱

例#4专业人士

  • 语法看起来非常简单

例#4缺点

  • 它是该地段中最慢的一个(比第二个最慢(示例#1)慢约100%).可能是因为它必须调用一个功能1,000,000次.
  • 您已脱离全局范围,并且必须拥有全局范围内的global所有变量.

结论

PHP编译器不会为您执行此操作,如果您需要性能,则应该以#2为例,但是此测试是使用具有一百万个条目的数组进行的.您的阵列可能不会有那么多条目,因此您可能会使用示例#1示例#3.哦,不要以#4为例.