对于字符串累加的处理,在 PHP 或 JavaScript 中似乎都可以通过类似 += (.= for PHP) 的方式实现,但有不少人抱怨道,这种方式效率很低。事实上,在我还在用 VB 的时候我就注意到这样的效率很低,当时的效率低是因为累加需要反复申请内存,而解决方法也很简单,就是用 Space$ 命令事先申请内存,然后用 Mid$ 来修改,这样效率大大提高!
然而在这里就不一样了,PHP 和 JavaScript 的内存机制我不是非常了解,同时我们似乎也不再使用预申请的方法来加速了(似乎也比较困难……),而是直接用上了 += 这样的符号。
下面就是问题了:这样的效率低吗?
很多人(包括我自己最初)根据自己的想象,认为使用添加数组内容,最后合并数组为字符串,这样效率比简单的 += 要快,但我经过反复实验认为并不是这样的。首先是 JavaScript,我使用的测试代码如下:
function getTime() { return (new Date()).getTime(); } function testit() { var st, et, ta, tb; for (i = 0; i < 10; ++i) { st = getTime(); t = ''; for (j = 0; j < 100000; ++j) { t += 'test'; } et = getTime(); ta = et - st; st = getTime(); a = []; for (j = 0; j < 100000; ++j) { a.push('test'); } t = a.join(); et = getTime(); tb = et - st; console.log(ta, ' ', tb); } }
以下是我在 Firefox 3.0.6 下执行的结果:
196 207 195 215 199 203 196 203 200 197 110 111 104 111 107 111 108 113 105 107
可以看出,+= 的效率并不比数组合并低,甚至略快于数组合并。
下面我们看看 PHP 呢?
下面是测试用 PHP 代码:
<?php for ($i = 0; $i < 10; ++$i) { $st = microtime(true); $str = ''; for ($j = 0; $j < 10000; ++$j) { $str .= 'test'; } $et = microtime(true); printf("%.7F\t", $et - $st); $st = microtime(true); $arr = array(); for ($j = 0; $j < 10000; ++$j) { $arr[] = 'test'; } $str = implode($arr); $et = microtime(true); printf("%.7F\n", $et - $st); } ?>
结果则如下:
0.0039599 0.0461071 0.0070710 0.0408709 0.0052779 0.0322330 0.0061541 0.0294971 0.0051920 0.0230181 0.0039949 0.0204601 0.0038750 0.0246589 0.0043111 0.0245950 0.0047810 0.0232542 0.0038841 0.0230379
可以看出,数组合并的效率远低于字符串直接叠加!
上一次用 spidermonkey-bin 中的 js 命令做了一下实验,结果在这种条件下,字符串叠加的效率也是远优于数组合并,而不像在 Firefox 中这样。
我对于这些脚本语言对字符串和数组的具体实现机理不是很清楚,但可以肯定的是,个个常用的脚本引擎都对字符串处理做了许多优化,我猜测(因为 Ubuntu 下暂时没有 stable 的 Chrome)Chrome 的 V8 引擎中,字符串直接叠加的效率将继续远超数组。因此,我们不应该想当然地认为某某方式效率高,而应该用测试结果说话……
Comments !