奇技淫巧一:循环加速
奇技淫巧一:循环加速
循环通常是程序性能问题的多发地段。优化某些循环能极大的提高某段程序的性能。
以下的测试环境为:win xampp1.7.3 PHP5.3.1
【数组长度】
也许,maybe,可能,你看到如下类似的代码:
以上的程序运行在我的电脑上基本上是3.3秒到3.4秒的样子。
如果我们把count($data)的计算提前到循环前,以局部变量在循环中迭代。如下所示代码:
在同样的环境下运行,基本上是0.32到0.4秒。
对比一下,整整一个数量级的提升。只是优化了一点,性能有如此大的提升。对于这样的操作我们需要在平时注意,养成习惯。虽然PHP内部取数组的长度是从Hash Table中直接取的count值。可是这个相对于局部变量,在性能上还是有较大差别的。
这里想到一个点,如果是HTML中使用JS取DOM集合,然后计算DOM的长度,此时如果有增加或删除节点,可能最后得到的结果并不是你要的那个结果。
【计数变量】
和数组长度一样,计数变量也是一个在循环中每次迭代都会使用的变量。如果我们优化这个点,此时性能上应该也有部分提高。如下所示代码:
以上的代码将计数变量从大到小递减,当为0时自动停止。从而将判断语句和计数加1两条语句变成了一条语句。
最后的运行时间大概为0.26到0.27秒。与前面的0.3到0.4秒,又有了大约30%的提升。
只是,只是这些是针对for语句,在PHP中我们还有foreach。
【foreach】
将上面的for语句换成foreach,如下所示代码:
$data = range(0, 1000000);
$start = xdebug_time_index();
foreach ($data as $row) {
}
$end = xdebug_time_index();
echo $end - $start;
运行时间为:0.11~0.13秒,也许此时我们应该去内核里面看下为什么了,只是这不是今天的重点。嘿嘿
结果已经很明显了,如果可以,我们还是用foreach吧。
【循环展开】
在《编程珠玑》中介绍了这样一种方案。只是他是针对特定的数组查找的问题。
$data = range(0, 1000005);
$start = xdebug_time_index();
$len = count($data);
$left = $len % 8;
$i = 0;
while($left-- > 0) {
$i++;
}
for(; $i < $len; $i+=8) {
$t = $data[$i];
$t = $data[$i + 1];
$t = $data[$i + 2];
$t = $data[$i + 3];
$t = $data[$i + 4];
$t = $data[$i + 5];
$t = $data[$i + 6];
$t = $data[$i + 7];
}
$end = xdebug_time_index();
echo $end - $start;
以上的方法运行时间为0.3多一些,这和前面的方法类似,但是需要考虑到这里多了8个赋值语句。如果去掉这8个赋值语句,其时间为0.04秒。
以上的一些方法只是针对数量级比较大的数组,此时一些微小的优化都会产生巨大的能量。平时中,也许我们使用foreach就足够了。
【纠结的轮子】
最开始生成一百万的数组使用的是如下方式:
$data = array();
for ($i = 0; $i < 1000005; $i++) {
$data[$i] = $i;
}
纠结的轮子!