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

时间:2012-09-18 15:40:43

标签: php performance for-loop foreach performance-testing

最快的是什么?要在循环内部或外部基于循环之外的变量执行条件,或者甚至是否重要(编译器是否为您执行此操作),或者您是否应该使用完全不同的变通方法?< / p>

示例#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";
    }
}

示例#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";
    }
}

2 个答案:

答案 0 :(得分:11)

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

概述

condition inside or outside loop graph


性能测试

示例#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

代码:

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

示例#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

代码:

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

好吧,对于循环之外的条件,这是一个非常明显的胜利,但是如果我们尝试与布尔值而不是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

代码:

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

有趣。如果我们使用内置函数,例如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

代码:

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

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


优点/缺点

示例#1专业人员

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

示例#1缺点

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

示例#2专业人员

  • 其中最快的一个

示例#2缺点

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

示例#3专业人员

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

示例#3缺点

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

示例#4专业人员

  • 语法看起来非常简单

示例#4缺点

  • 这是该地段中最慢的一个(比第二个最慢(示例#1 )慢约100%)。可能是由于它必须调用一个功能1,000,000次。
  • 您已超出全球范围,并且必须global来自全球范围的所有变量。

结论

PHP编译器不会为你做这件事,如果你想要性能你应该去例子#2 然而这个测试是用一个数组做的有一百万条目。您的阵列可能不会包含那么多条目,因此您可能会使用示例#1 示例#3 哦,不要去示例#4

答案 1 :(得分:1)

如果条件测试的结果在循环期间不会改变,那么将测试移出循环总是会更快。 (做一次事情显然比多次做同样事情更快。)

但是,当将条件移出循环时,您不希望为每种情况反复重复相同的代码。这是array_map的用武之地。例如:

function append_str($value, $suffix) {
    return $value . $suffix;
}

if ($test == 1)
    array_map("append_str", $list, " - one");
else if ($test == 2)
    array_map("append_str", $list, " - two");
else if ($test == 3)
    array_map("append_str", $list, " - three");

这使您可以在重复使用代码处理每个案例后检查条件。如示例所示,您可以针对每种情况参数化函数调用,并且可以使函数(append_str)尽可能复杂。

注意:值得对此进行基准比较,因为array_map的循环可能在C / C ++中执行,它应该比本机PHP循环更快(类似于Perl的map功能)。