8

什么是最快的?要在循环内部或外部基于循环外部的变量执行条件,或者它甚至重要(编译器是否为您执行),或者您是否应该使用完全不同的解决方法?

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

2 回答 2

12

正如您可能已经猜到的那样,示例 #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

和代码:

<?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 缺点

  • 它是其中最慢的一个(比第二慢的大约 100%(例如 #1))。可能是因为它必须调用一个函数 1,000,000 次。
  • 您不在全局范围内,必须使用全局范围内的global所有变量。

结论

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

于 2012-09-18T15:40:42.713 回答
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函数)。

于 2012-09-18T15:49:24.077 回答