PHP:使用join的output[]与$output .=有什么区别?

3

我正在修改一些代码,原作者使用数组构建了一个网页,如下所示:

 $output[]=$stuff_from_database;
 $output[]='more stuff';
 // etc
 echo join('',$output);

有人能想到这样做更好的原因吗(反之亦然):

 $output =$stuff_from_database;
 $output .='more stuff';
 // etc
 echo $output;
10个回答

14

很可能是由来自字符串不可变的语言的人编写的,因此连接操作代价昂贵。但PHP并非这些语言之一,如下所示,第二种方法在性能上更好。我能想到使用第一种方法的唯一其他原因是能够用另一个数组替换某些部分,但这意味着要跟踪索引,而这没有指定。

~$ cat join.php
<?php

for ($i=0;$i<50000;$i++) {
$output[] = "HI $i\n";
}

echo join('',$output);
?>


~$ time for i in `seq 100`; do php join.php >> outjoin ; done

real    0m19.145s
user    0m12.045s
sys     0m3.216s

~$ cat dot.php
<?php

for ($i=0;$i<50000;$i++) {
$output.= "HI $i\n";
}

echo $output;
?>


~$ time for i in `seq 100`; do php dot.php >> outdot ; done

real    0m15.530s
user    0m8.985s
sys     0m2.260s

这是与 PHP 4 相比明显的改进,那时情况完全相反。 - staticsan

2

再次偏离主题一点(不是非常远),但是如果你想在输出的数组项之间放置一些内容,那么如果只有几行要连接,则join(',',$ output)可以轻松快捷地完成。这样写起来更容易,避免了检查列表末尾(您不希望出现尾随“,”)。

对于程序员而言,由于它的成本是CPU周期的1000倍以上,所以我通常会将其放到join中,如果它不会每秒运行10,000次以上。

像这样进行后编码微优化很少值得花费时间来节省CPU时间。


2

这个话题有点偏离主题,但是

$output =$stuff_from_database;
$output .='more stuff';
// etc
echo $output;

比以下方法慢得多:
echo = $stuff_from_database;
echo 'more stuff';

实际上,在PHP中构建字符串的最快方法是:
ob_start();
echo = $stuff_from_database;
echo 'more stuff';
$output = ob_get_contents();
ob_end_clean();

由于输出缓冲区的工作方式等原因,这是构建字符串最快的方法。显然,只有在真正需要优化字符串构建时才会这样做,因为它不美观且不便于代码的易读性。而且每个人都知道,“过早地进行优化是万恶之源”。


通过对“echo =”进行微小的代码更正并输出“$output”,这是最快的方法,因为输出缓冲区以4或8KB块分配,而不仅仅是所需的(至少1字节)。 - Alister Bulman

1

<!-- 已编辑的先前评论 -->

看起来我的代码有错误,所以我在执行无操作并忘记检查。

与之前的测试和阅读有关主题的博客相反,以下结论实际上是(经过测试)不正确,至少对于我可以排列的所有上述代码变体。

  1. 不正确:字符串插值比字符串连接慢。(!)
  2. 不正确:SprintF最快。

在实际测试中,Sprintf是最慢的,而插值是最快的

PHP 5.2.6-pl7-gentoo (cli) (built: Sep 21 2008 13:43:03) 
版权所有(c)1997-2008 PHP Group
Zend Engine v2.2.0,版权所有(c)1998-2008 Zend Technologies
    Xdebug v2.0.3,版权所有(c)2002-2007,作者Derick Rethans

可能是因为我的设置有条件限制,但这仍然很奇怪。 :/


1

我认为最快的方法是使用回声。虽然这种方法不够美观,而且可能并没有足够的速度优势来抵消可读性上的成本。

echo $stuff_from_database
   , 'more stuff'
   , 'yet more'
   // etc
   , 'last stuff';

0

底部将重复重新分配 $output 字符串,而我认为顶部只会将每个片段存储在数组中,然后在最后将它们全部连接起来。因此,原始示例可能会因此变得更快。如果这不是性能敏感的话,我可能会选择追加而不是连接。


0
如果与implode()join()一起使用,PHP能够更好地进行优化。它会遍历列表中的所有字符串,计算长度并分配所需空间并填充空间。与".="相比,它必须不断地free()malloc()字符串的空间。

你提出了一个很好的观点。测量内存消耗会很有趣...也许这对于大型数据集来说可能是一个瓶颈。 - Camilo Díaz Repka

0

这部分代码不太注重性能;它用于在低流量网站上格式化和显示用户的购物车信息。此外,数组(或字符串)每次都是从头开始构建的,没有必要寻找特定元素。听起来数组有点更有效率,但我想对于这种用途来说也无所谓了。感谢您提供的所有信息!


0

虽然已经有人提到过,但我认为一个明确的答案会更有帮助。

原始程序员编写代码时认为这样更快。实际上,在 PHP 4 下,特别是对于较大的字符串,确实更快。


0
如果您正在生成一个列表(例如购物车),那么您应该有一些代码从数据库获取每个条目并生成相应的HTML。
for ($prod in $cart)
{
  $prod->printHTML();
}

或者类似的方式。这样,代码就变得更加清晰。当然,这是建立在你有良好的对象化代码的前提下,而不是像我们公司一样整个代码混乱无章(正在进行替换)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接