对于字符串累加的处理,在 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 引擎中,字符串直接叠加的效率将继续远超数组。因此,我们不应该想当然地认为某某方式效率高,而应该用测试结果说话……
There are comments.