为了账号安全,请及时绑定邮箱和手机立即绑定

在PHP中FOR FOR FOR FORACH的性能

在PHP中FOR FOR FOR FORACH的性能

HUH函数 2019-07-31 18:45:55
在PHP中FOR FOR FOR FORACH的性能首先,我理解90%的应用程序中性能差异完全不相关,但我只需要知道哪个是更快的构造。那......目前在网上提供的信息令人困惑。很多人说foreach很糟糕,但从技术上讲它应该更快,因为它假设使用迭代器简化了数组遍历的编写。迭代器,再次假设更快,但在PHP中也显然死得很慢(或者这不是PHP的东西?)。我在谈论数组函数:next()prev()reset()等等,如果它们是偶数函数而不是那些看起来像函数的PHP语言特性之一。为了缩小这个范围:我在以超过1的步长遍历数组时没有兴趣(也没有负步骤,即反向迭代)。我也对从任意点到任意点的遍历不感兴趣,只有0到长度。我也没有看到定期操作超过1000个键的数组,但我确实看到一个数组在应用程序的逻辑中被遍历了多次!另外,对于操作,主要是字符串操作和回声。以下是一些参考站点:http://www.phpbench.com/ http://www.php.lt/benchmark/phpbench.php我到处听到的内容:foreach很慢,因此for/ while更快PHP foreach复制它迭代的数组; 为了使它更快你需要使用引用像这样的代码:比a更快$key = array_keys($aHash); $size = sizeOf($key); for ($i=0; $i < $size; $i++)foreach这是我的问题。我写了这个测试脚本:http://pastebin.com/1ZgK07US,无论我运行脚本多少次,我得到这样的东西:foreach 1.1438131332397foreach (using reference) 1.2919359207153for 1.4262869358063foreach (hash table) 1.5696921348572for (hash table) 2.4778981208801简而言之:foreach比foreach参考更快foreach 比...更快 forforeachfor比哈希表更快谁能解释一下?难道我做错了什么?PHP foreach引用的东西真的有所作为吗?我的意思是,如果你通过引用传递它为什么不复制它?foreach语句的等效迭代器代码是什么; 我在网上看到了一些,但每次我测试它们的时机都是关闭的; 我还测试了一些简单的迭代器结构,但似乎从来没有得到过不错的结果 - PHP中的数组迭代器是不是很糟糕?是否有更快的方法/方法/构造来迭代除FOR / FOREACH(和WHILE)之外的数组?PHP版本5.3.0
查看完整描述

3 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞


我个人的意见是使用在上下文中有意义的东西。就个人而言,我几乎从不使用for数组遍历。我将它用于其他类型的迭代,但是foreach太简单了......在大多数情况下,时间差异将是最小的。


值得关注的重点是:


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

这是一个昂贵的循环,因为它会调用每次迭代。只要你不这样做,我认为这不重要......


至于引用差异的参考,PHP使用copy-on-write,因此如果不写入数组,循环时的开销会相对较小。但是,如果您开始修改数组中的数组,那么您将开始看到它们之间的差异(因为需要复制整个数组,并且引用只能修改内联)...


至于迭代器,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上)好像引用明显更快......


查看完整回答
反对 回复 2019-07-31
?
www说

TA贡献1775条经验 获得超8个赞

我不确定这是多么令人惊讶。大多数使用PHP编写代码的人都不熟悉PHP在裸机上的实际操作。我将陈述一些事情,大部分时间都是如此:

  1. 如果您不修改变量,则PHP中的按值更快。这是因为无论如何都要计算它的参考值,并且按值给它做的更少。它知道第二个你修改ZVAL(PHP的大多数类型的内部数据结构),它必须以一种简单的方式将其分解(复制它并忘记其他ZVAL)。但你永远不会修改它,所以没关系。引用使得更复杂,更多的簿记,它必须知道在修改变量时要做什么。所以,如果你是只读的,那么矛盾的是,最好不要用&。我知道,这是违反直觉的,但也是如此。

  2. Foreach并不慢。对于简单的迭代,它正在测试的条件 - “我是在这个数组的末尾” - 是使用本机代码而不是PHP操作码完成的。即使它是APC缓存的操作码,它仍然比在裸机上完成的一堆本机操作慢。

  3. 使用for循环“for($ i = 0; $ i <count($ x); $ i ++)因为count()而缺乏PHP,并且缺乏PHP的能力(或实际上任何解释语言)来解析时间是否有任何修改数组。这可以防止它一次评估计数。

  4. 但即使你用“$ c = count($ x); for($ i = 0; $ i <$ c; $ i ++)修复它,$ i <$ c也是一堆Zend操作码最多,因为$ 100 ++。在100000次迭代过程中,这很重要.Toreach在本机级别知道该怎么做。没有PHP操作码需要测试“我在这个阵列结束时”的条件。

  5. 旧学校怎么样“while(列表(”东西?好吧,使用each(),current()等等)都将涉及至少1个函数调用,这不是很慢,而是不是免费的。是的,那些再次是PHP操作码!所以虽然+ list +每个都有它的成本。

由于这些原因,foreach可以理解为简单迭代的最佳选择。

不要忘记,它也是最容易阅读的,所以它是双赢的。


查看完整回答
反对 回复 2019-07-31
  • 3 回答
  • 0 关注
  • 503 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信