什么是最快的?循环内部或外部的条件?
Posted
技术标签:
【中文标题】什么是最快的?循环内部或外部的条件?【英文标题】:What is quickest? Conditions inside a loop or outside? 【发布时间】:2012-09-10 21:59:47 【问题描述】:什么是最快的? 基于循环外的变量在循环内部或外部执行条件,或者它甚至重要(编译器是否为您执行),或者您是否应该使用完全不同的解决方法?
示例 #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";
【问题讨论】:
【参考方案1】:您可能已经猜到了,示例 #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 个测试中最慢的一个(比 example #2 慢 71%,比 example #3 慢 32%)示例 #2 专业人士
其中最快的一个示例 #2 缺点
它需要您多次声明循环(与您拥有的条件数量一样多)示例 #3 专业人士
您不必多次声明循环,就像在 示例 #1 中一样 比#example 1快示例#3 缺点
还是比#example 2慢(大约30%) 看起来比较凌乱示例 #4 专业人士
语法看起来很简单示例 #4 缺点
它是最慢的一个(比第二慢的大约慢 100%(example #1))。可能是因为它必须调用一个函数 1,000,000 次。 您不在全局范围内,必须global
全局范围内的所有变量。
结论
PHP 编译器不会为你做这件事,如果你想要性能,你应该去 example #2,然而这个测试是用一个数组进行的有一百万个条目。您的数组可能不会有那么多条目,因此您可能会选择 example #1 或 example #3。 哦,不要使用 示例 #4。
【讨论】:
【参考方案2】:如果条件测试的结果在循环期间不会改变,那么将测试移出循环总是会更快。 (做一件事显然比多次做同样的事情要快)。
但是,当将条件移出循环时,您不想为每种情况一遍又一遍地重复相同的代码。这就是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
函数)。
【讨论】:
虽然这不是对确切示例的错误答案,但问题更多的是关于性能,$listItem .= " - number"
是一个纯粹的示例。可能是 $number += 12
、$number += 23
和 $number += 34
或者更高级的东西。
我应该补充一点,我正要将此添加到基准测试中,但是; Warning: array_map() [function.array-map]: Argument #3 should be an array in benchmark.php on line 15
(第 15 行是 array_map("append_str", $list, " - two");
)。根据 PHP 的语法是 array array_map ( callable $callback , array $arr1 [, array $... ] )
,因此没有“参数”本身,但是,它应该可以工作,但前提是您添加一个名为 " - two"
的包含 1,000,000 个条目的数组。也就是说,array_walk
可能是您正在寻找的,与之前最慢的 0.25 秒相比,它需要 0.49 秒。
这是一个相当令人惊讶的结果......甚至可能是语言设计失败。不过很高兴您对其进行了测试。以上是关于什么是最快的?循环内部或外部的条件?的主要内容,如果未能解决你的问题,请参考以下文章