当前位置: 首页 > 面试题库 >

PHP中FOR与FOREACH的性能

吕英豪
2023-03-14
问题内容

首先,我了解90%的应用程序中的性能差异完全无关紧要,但是我只需要知道哪个是更快的构造即可。那…

当前网上可用的信息令人困惑。许多人说foreach不好,但是从技术上讲应该更快,因为它假定可以简化使用迭代器编写数组遍历的过程。再次被认为是更快的迭代器,但是在PHP中显然还很慢(或者这不是PHP吗?)。我说的是数组函数:next()prev()reset()等,如果它们甚至是函数,而不是看起来像函数的PHP语言功能之一。

稍微缩小一点
:我对以大于1的步长遍历数组并不感兴趣(也没有负步长,即反向迭代)。我也对遍历任意点(长度为0)不感兴趣。我也看不到有规则地操纵具有1000个以上键的数组,但是我确实看到一个数组在应用程序的逻辑中被遍历了多次!另外,对于操作,主要仅是字符串操作和回显。

我到处都能听到:

  • foreach慢,因此for/ while
  • PHP foreach复制它遍历的数组;为了更快,您需要使用参考
  • 像这样的代码:比$key = array_keys($aHash); $size = sizeOf($key); for ($i=0; $i < $size; $i++)``foreach

这是我的问题。我写了这个测试脚本:http :
//pastebin.com/1ZgK07US,无论我运行脚本多少次,都会得到如下信息:

foreach 1.1438131332397
foreach (using reference) 1.2919359207153
for 1.4262869358063
foreach (hash table) 1.5696921348572
for (hash table) 2.4778981208801

简而言之:

  • foreachforeach参考更快
  • foreachfor
  • foreachfor散列表快

有人可以解释吗?

  1. 难道我做错了什么?
  2. PHP foreach参考对象是否真的有所作为?我的意思是,如果您通过引用,为什么不复制它?
  3. foreach语句的等效迭代器代码是什么?我已经在网上看到了一些,但是每次测试它们时,时机都会变差。我还测试了一些简单的迭代器构造,但似乎从未获得过像样的结果-PHP中的数组迭代器太糟糕了吗?
  4. 除了FOR / FOREACH(和WHILE)以外,是否有更快的方法/方法/构造来迭代数组?

PHP版本5.3.0

编辑:答案 在这里人们的帮助下,我得以整理出所有问题的答案。我在这里总结一下:

  1. “难道我做错了什么?” 共识似乎是:是的,我不能在基准测试中使用echo。就我个人而言,我仍然看不到回声是具有随机执行时间的某个函数是如何实现的,或者其他函数在某种程度上是如何有所不同的-以及该脚本能够产生比所有函数更好的foreach完全相同结果的能力很难解释一下“您正在使用echo”(我应该一直使用什么)。但是,我承认应该用更好的方法来进行测试。尽管没有想到理想的折衷方案。
  2. “ PHP foreach参考对象真的有所作为吗?我的意思是,如果您通过参考传递,为什么它不复制它?” ircmaxell表明,是的,进一步的测试似乎证明了在大多数情况下引用应该更快-尽管鉴于我上面的代码片段,但绝对不是全部。我接受这个问题可能太不直观了,以至于无法在这样的水平上打扰,并且需要一些极端的事情,例如反编译才能真正确定哪种情况更适合每种情况。
  3. “ foreach语句的等效迭代器代码是什么;我已经在网上看到了一些,但是每次测试它们的时机都不对劲;我也测试了一些简单的迭代器构造,但似乎从未获得过像样的结果-PHP中的数组迭代器很糟糕吗?” ircmaxell在下面给出了答案;尽管该代码可能仅对PHP版本> = 5有效
  4. “是否有更快的方法/方法/构造来迭代除FOR / FOREACH(和WHILE)以外的其他数组?” 感谢去戈登的答案。在PHP5中使用新的数据类型应该可以提高性能或增加内存(根据您的情况,可能需要两者之一)。尽管速度上很多新类型的数组似乎并不比array()更好,但splpriorityqueue和splobjectstorage确实确实快得多。戈登(Gordon)提供的链接:http : //matthewturland.com/2010/05/20/new-spl-features-in-php-5-3/

谢谢所有尝试提供帮助的人。

对于任何简单的遍历,我可能都会坚持使用foreach(非参考版本)。


问题答案:

我个人的观点是在上下文中使用有意义的内容。我个人几乎从未使用for过数组遍历。我将其用于其他类型的迭代,但是foreach太简单了……在大多数情况下,时间差异将很小。

要注意的最大事情是:

for ($i = 0; $i < count($array); $i++) {

这是一个昂贵的循环,因为它在每次迭代中都调用计数。只要您不这样做,我就认为这并不重要…

至于有区别的参考,PHP使用写时复制,因此,如果您不写数组,则循环时的开销相对较小。但是,如果您开始修改数组中的数组,那么您将开始看到它们之间的差异(因为一个人将需要复制整个数组,而引用只能进行内联修改)…

至于迭代器,foreach等效于:

$it->rewind();
while ($it->valid()) {
    $key = $it->key();     // If using the $key => $value syntax
    $value = $it->current();

    // Contents of loop in here

    $it->next();
}

至于有更快的迭代方法,这实际上取决于问题。但是我真的要问,为什么?我知道想要提高效率,但我认为您在浪费时间进行微优化。记住Premature Optimization Is The Root Of All Evil

编辑: 根据评论,我决定进行快速基准测试…

$a = array();
for ($i = 0; $i < 10000; $i++) {
    $a[] = $i;
}

$start = microtime(true);
foreach ($a as $k => $v) {
    $a[$k] = $v + 1;
}
echo "Completed in ", microtime(true) - $start, " Seconds\n";

$start = microtime(true);
foreach ($a as $k => &$v) {
    $v = $v + 1;
}
echo "Completed in ", microtime(true) - $start, " Seconds\n";

$start = microtime(true);
foreach ($a as $k => $v) {}
echo "Completed in ", microtime(true) - $start, " Seconds\n";

$start = microtime(true);
foreach ($a as $k => &$v) {}    
echo "Completed in ", microtime(true) - $start, " Seconds\n";

结果:

Completed in 0.0073502063751221 Seconds
Completed in 0.0019769668579102 Seconds
Completed in 0.0011849403381348 Seconds
Completed in 0.00111985206604 Seconds

因此,如果您要在循环中修改数组,则使用引用的速度要快几倍…

而且,仅引用的开销实际上比复制数组要少(这在5.3.2上)…因此(至少在5.3.2上)看起来好像引用的速度明显更快…



 类似资料:
  • 本文向大家介绍请比较下for、forEach、for of的性能的性能相关面试题,主要包含被问及请比较下for、forEach、for of的性能的性能时的应答技巧和注意事项,需要的朋友参考一下 1.for 最好 2.forEach与for of 相差无几 平均测试下来forEach略高for of 3.forEach 无法通过 break跳出 for of内存占用上有一定的优势

  • 问题内容: 当我的研究使我相信循环是PHP中最快的迭代构造…为了使它更清晰时,您认为以下哪个会更快? 示例一 示例二 我的逻辑是,在示例中的每次迭代中,在每次迭代中访问myLargeArray的长度比在示例二中访问简单的整数值要昂贵。那是对的吗? 问题答案: 第一种方法较慢,因为必须在循环的每次迭代中都调用该函数。该方法本身非常快,但是调用该函数仍然有一些开销。通过将其移动到循环之外,您正在执行所

  • 问题内容: 如下代码: 输出: 两次运行“ foreach”不是我的目的,我很好奇为什么两个“ foreach”语句仅输出一次结果? 以下是类似情况: 输出: 但是,当我从上述代码中删除第一个“ foreach”时,输出将变为正常: 输出: 为什么会这样? 问题答案: 一个(你有)是向前光标。这意味着,一旦消耗(第一次迭代),就不会后退到结果集的开头。 您可以在之后关闭光标,然后再次执行该语句:

  • 问题内容: 我正在开发一个使用数据库类查询mySQL的php应用程序。 该类在这里:http : //net.tutsplus.com/tutorials/php/real-world-oop-with-php-and- mysql/ 我根据自己的需要对课程进行了一些调整,但存在一个问题(可能是一个愚蠢的问题) 使用select()时,它返回一个多维数组,类似于具有3个cols(id,firstn

  • 问题内容: 我有一个嵌套的数组,我想在其中显示结果的子集。例如,在下面的数组中,我想遍历嵌套array [1]中的所有值。 我试图使用foreach函数,但似乎无法正常工作。这是我的原始语法(尽管我意识到这是错误的)。 我试图避免对键是否与我要搜索的键相同的变量进行比较,即 有任何想法吗? 问题答案: 如果您知道嵌套数组中的级别数,则可以简单地执行嵌套循环。像这样: 如果您不知道数组的深度,则需要

  • 本文向大家介绍浅谈php中的循环while、do...while、for、foreach四种循环,包括了浅谈php中的循环while、do...while、for、foreach四种循环的使用技巧和注意事项,需要的朋友参考一下 php中的while循环,循环执行代码块制定的次数,或者当指定的条件为真时循环执行代码块。 ----------------------------------------