首先,我知道在90%的应用程序中,性能差异是完全无关的,但我只需要知道哪种构造更快.还有...

目前网络上关于他们的信息令人困惑.很多人说foreach不好,但从技术上讲,它应该更快,因为它应该简化使用迭代器编写数组遍历的过程.迭代器,也被认为是更快的,但在PHP中也明显非常慢(或者这不是PHP的东西?).我说的是数组函数:next()prev()reset()等等.如果它们是偶数函数,而不是像函数一样的PHP语言特性.

To narrow this down a little:我对以大于1的步长遍历数组不感兴趣(也没有负步长,即.反向迭代).我对往返任意点的遍历也不感兴趣,只对0到长度感兴趣.我也不会经常看到操作超过To narrow this down a little0个键的数组,但是我确实看到一个数组在应用程序的逻辑中被多次遍历!同样对于操作,很大程度上只有字符串操作和 echo .

Here are few reference sites:
http://www.phpbench.com/
http://www.php.lt/benchmark/phpbench.php

我到处都能听到:

  • foreach较慢,因此for/while较快
  • PHPforeach复制它遍历的数组;要使其更快,您需要使用引用
  • code like this: $key = array_keys($aHash); $size = sizeOf($key);
    for ($i=0; $i < $size; $i++)
    is faster than a 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快 for a hash table

有人能解释一下吗?

  1. 我做错什么了吗?
  2. PHP foreach引用真的有意义吗?我的意思是,如果你通过引用,为什么它不会复制它呢?
  3. foreach语句的等效迭代器代码是什么;我在网上看到过几个,但每次测试它们的时间都很不对劲;我还测试了几个简单的迭代器构造,但似乎从来没有得到过像样的结果--PHP中的数组迭代器真的很糟糕吗?
  4. 除了FOR/FOREACH(和WHILE)之外,有没有更快的方法/方法/构造来迭代数组?

PHP 5.3.0版


Edit: Answer With help from people here I was able to piece together the answers to all question. I'll summarize them here:
  1. "我做错什么了吗?" The consensus seems to be: yes, I can't use echo in benchmarks. Personally, I still don't see how echo is some function with random time of execution or how any other function is somehow any different -- that and the ability of that script to just generate the exact same results of foreach better than everything is hard to explain though just "you're using echo" (well what should I have been using). However, I concede the test should be done with something better; though a ideal compromise does not come to mind.
  2. "PHP foreach引用真的有意义吗?我的意思是,如果你通过引用,为什么它不会复制它呢?" ircmaxell shows that yes it is, further testing seems to prove in most cases reference should be faster -- though given my above snippet of code, most definitely doesn't mean all. I accept the issue is probably too non-intuitive to bother with at such a level and would require something extreme such as decompiling to actually determine which is better for each situation.
  3. "foreach语句的等效迭代器代码是什么;我在网上看到过几个,但每次测试它们的时间都很不对劲;我还测试了几个简单的迭代器构造,但似乎从来没有得到过像样的结果--PHP中的数组迭代器真的很糟糕吗?" ircmaxell provided the answer bellow; though the code might only be valid for PHP version >= 5
  4. "除了FOR/FOREACH(和WHILE)之外,有没有更快的方法/方法/构造来迭代数组?" Thanks go to Gordon for the answer. Using new data types in PHP5 should give either a performance boost or memory boost (either of which might be desirable depending on your situation). While speed wise a lot of the new types of array don't seem to be better than array(), the splpriorityqueue and splobjectstorage do seem to be substantially faster. Link provided by Gordon: http://matthewturland.com/2010/05/20/new-spl-features-in-php-5-3/

谢谢所有试图帮忙的人.

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

推荐答案

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

需要注意的一件大事是:

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

这是一个开销很大的循环,因为它在每一次迭代中都调用count.只要你不这么做,我觉得这真的无关紧要.

至于有区别的引用,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...

Edit:基于这条 comments ,我决定做一个快速基准测试.

$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中)似乎引用速度要快得多...

EDIT:使用PHP8.0,我得到了以下结果:

Completed in 0.0005030632019043 Seconds
Completed in 0.00066304206848145 Seconds
Completed in 0.00016379356384277 Seconds
Completed in 0.00056815147399902 Seconds

多次重复该测试,排名结果一致.

Php相关问答推荐

发送给WooCommerce中相关产品作者的通知新订单的邮箱

如何在数据库中添加注册表单中的动态新行?

为什么注册SIGHUP的处理程序函数会阻止在PHP CLI中等待输入时点击X关闭Xterm窗口?""

PHP DateInterval天数不一致

如何将对我的域的请求重定向到子文件夹中的索引,同时保留域URL并使用.htaccess?

Sylius php -如何将购物车传递到小枝模板(Sylius模板事件)

Apache只允许index.php-不从根目录工作

这是在可召回的背景下吗?

我的邮箱中的链接在我的URL中添加了一个

Laravel服务Provider 没有向服务类注入价值

在WooCommercestore 页面上显示库存产品属性的值

WooCommerce 按产品运输插件:仅收取较高的运输费用

Woocommerce 中为空时隐藏显示变体自定义字段数据

为什么 php 只能在我的 Nginx Web 服务器的某些目录中工作?

如何从 PHP 中的 .txt 文件中列出今天生日的人的姓名?

htaccess php 文件,然后是文件夹

计算组合指数

每个发布请求 Laravel 9 的 CSRF 令牌不匹配

password_verify 在 PHP 7.4 中有效,但在 PHP 8.2 中无效

获取具有所有特定相关模型的模型