2009-09-03 116 views
21

我正在读这本书 - 专业的Javascript的Web开发人员提到字符串连接的开发人员比使用数组来存储字符串,然后使用连接方法来创建最终的字符串。出于好奇,我做了几个测试在这里看到多少时间就可节省,这是我得到了什么 -字符串连接vs字符串缓冲区在Javascript中

http://jsbin.com/ivako

不知何故,火狐通常会产生几分相似倍两种方式,但在IE浏览器,串连接速度要快得多。所以,现在这个想法可以被认为是过时的(浏览器可能已经改进了,因为?

+0

我刚刚在IE 7(jsbin.com/ivako)中试过你的例子,它似乎与你所说的相反。我得到:与加号级联:92829毫秒与StringBuffer级联:125毫秒。 在同一台机器上的Firefox 3.5中,我得到串联加上:110毫秒 与StringBuffer串联:113毫秒 – 2009-09-03 00:58:15

+0

这是奇特的。自从我在本地运行脚本以来,我以为自己得到的结果是扭曲的,所以我放上了jsbin。还是一样。我使用IE8和Firefox 3.5。我将在虚拟PC上的IE7上尝试此操作。 – Dhana 2009-09-03 01:01:23

+0

92829毫秒?那1分32秒。你确定? – bucabay 2009-09-03 11:12:51

回答

26

**编辑:我假设人们仍然在查看这篇文章 - 但它已经3+年,所以只需查看以下信息即可:http://jsperf.com/string-concatenation/14

查看此帖子的变化以查看它曾经说过的内容。

+0

很好的答案,但如果串被串联明显延长(至少500字)差异会很明显,无论什么样的电脑运行它 – Rodrigo 2009-09-03 01:17:47

+1

** **的TraceMonkey,不Trackmonkey:) – kangax 2009-09-03 04:41:11

+0

拼写错误:) – 2009-09-04 06:10:36

4

即使它是真实的,并且join()比串联更快也没关系,我们在这里谈论的是微小的毫秒数是完全可以忽略不计。

我总是喜欢结构良好,易于阅读在显微镜的性能提升代码,我觉得用串联看起来更好,更容易阅读。

只是我的两分钱。

+5

多次发生的循环内部的毫秒数并不总是可以忽略的。它可以添加到秒,几天或几年 - 取决于应用程序,我不相信你不知道这一点。你的两美分毫无价值。 – DaveWalley 2014-04-23 21:26:07

+0

完全同意w/@DaveWalley ...如果您不考虑[复杂性](https://en.wikipedia.org/wiki/Big_O_notation),即算法的运行时间/空间,这可能意味着顺利和滞后的反应之间的区别。我认为你的两分钱实际上是值得两分钱的债务。 – 2015-06-25 00:26:54

+1

我认为Richard Knop有一个总有效点。在项目的早期阶段,可读性很重要。只要你不在i> 1000循环中,连接就没有问题。请不要因为这个'过早优化'陷阱...这是一个众所周知的反模式,并导致我的经验最悲伤。 – 2016-03-03 11:54:14

1

我实际上在这方面有一些经验,因为我的主要产品是一个大型的IE浏览器,它为了构建XML文档以发送到服务器而进行了大量的字符串连接。例如,在最糟糕的情况下,页面可能会有5-10个iframe,每个iframe有几百个文本框,每个文本框都有5-10个expando属性。

对于像我们的保存功能一样,我们遍历每个选项卡(iframe)和该选项卡上的每个实体,将每个实体的所有expando属性拉出来,并将它们全部放入一个巨大的XML文档中。

在分析和改进我们的保存方法时,我们发现在IE7中使用字符串连接要比使用字符串数组方法慢很多。其他一些关注点是访问DOM对象expando属性非常慢,所以我们将它们全部放入JavaScript数组中。最后,生成JavaScript数组本身实际上最好是在服务器上完成,然后将其作为文字控件写入页面,然后在页面加载时执行。

+0

我在其中一个应用程序中遇到类似问题,我决定今天尝试这种方法 - whaddya说 - IE7的改进绝对可见。 – Dhana 2009-09-03 03:08:52

2

在我的系统(IE 8在Windows 7)的StringBuilder在该测试非常约70%-100%范围内的时间 - 也就是说,它是不稳定的 - 虽然均值的约95%的正常追加。

虽然很容易,现在只是说“过早优化”(我怀疑,在几乎所有情况下它是)有些事情值得考虑:

反复字符串连接问题就来了重复内存分配和重复数据副本(高级字符串数据类型可以减少/消除大部分内容,但现在让我们继续假设一个简单的模型)。由此可以提出一些问题:

  • 使用什么内存分配?在天真的情况下,每个str + = x都需要分配str.length + x.length新内存。例如,标准C malloc是一个相当差的内存分配器。 JS的实现在多年来经历了变化,其中包括更好的内存子系统。当然,这些变化并不止于此,而是触及现代JS代码的所有方面。因为现在实施方式可以在某些任务已经慢得令人难以置信并不一定意味着同样的问题仍然存在,或以相同的程度。

  • 与Array.join执行上面是非常重要的。如果它在构建它之前不为最终字符串预先分配内存,那么它只会节省数据拷贝的成本 - 这些日子主内存有多少GB/s? 10,000 x 50几乎没有限制。与POOR MEMORY ALLOCATOR的智能Array.join操作预计可以更好地简化执行,因为重新分配的数量会减少。随着分配成本的降低,这种差异预计会最小化。

  • 微基准代码可根据如果JS引擎创建每每个唯一字符串文字或不是一个新的对象是有缺陷的。 (这会偏向Array.join方法,但通常需要考虑)。

  • 基准确实是一个微基准:) 增加生长尺寸应具有的性能基于任何或所有(然后一些)上述条件的影响。通常很容易显示有利于某种方法的极端情况 - 预期的用例通常更重要。

虽然,坦白地说,任何形式的理智串楼,我只想用正常的字符串连接,直到它被确定为一个瓶颈,如果有的话这样的时刻。

我会重新阅读本书中的上述声明,看看作者是否确实有意图调用诸如“对于非常大的字符串”或“疯狂量的字符串操作”或“在JScript中”/IE6“等等...如果不是,那么这样的表述就像”插入排序是O(n * n)“一样有用[[实现成本取决于数据的状态和当然的大小] 。

而且免责声明:代码的速度取决于浏览器,操作系统,底层硬件,月球引力,当然,你的电脑是如何看待你的。

-1

好吧,这在这里关于一个相关的模块:通过使用

var buffer = new String.Buffer(); 
buffer.append("foo", "bar"); 

这是哪门子最快落实的

http://www.openjsan.org/doc/s/sh/shogo4405/String/Buffer/0.0.1/lib/String/Buffer.html

这是创建字符串缓冲区的有效手段,我知道的字符串缓冲区。首先,如果你正在实现字符串缓冲区,不要使用push,因为这是一个内置方法,并且速度很慢,因为一次push迭代遍历整个arguments数组,而不是添加一个元素。

这一切真的取决于加入方法的实现,join方法的一些实施很慢,有些是比较大的。

+0

你是否有链接指出推送方法很慢? – Prestaul 2009-09-03 01:59:21

+0

http:// openjsan。org/doc/j/jh/jhuni/StandardLibrary/1.81/lib/Array.html 您必须处理__proto__以及参数Array的长度,这两件事情不应该是必需的。 http://groups.google.com/group/jquery-dev/browse_thread/thread/5019fa537c8d3595 – jhuni 2009-09-05 06:58:58

2

原则上这本书是正确的。加入一个数组应该是很多快于重复连接到同一个字符串。作为不可变字符串的简单算法,它显然更快。

诀窍是:JavaScript作者,主要是非专业的软件开发人员,他们在野外编写了大量代码,使用连接方式,而使用像array-join这样的方法的代码相对较少。结果是浏览器作者可以通过迎合和优化“不好”,更常见的串联选项,在平均网页上获得更好的速度提升。

这就是发生了什么事。较新的浏览器版本有一些相当多毛茸茸的优化工具,它们可以检测你何时进行连接加载,并且可以对它进行攻击,使得它在内部更像一个数组连接,工作速度几乎相同。

0

正如我们所知,并非所有的浏览器都是平等的。因此,保证不同区域的性能会因浏览器而异。

除此之外,我注意到和你一样的结果;然而,去除不必要的缓冲级,只是直接使用数组和10000字符串后,结果甚至更紧/一致(在FF 3.0.12):http://jsbin.com/ehalu/

除非你正在做的一个很大字符串连接,我会说这种类型的优化是一个微型优化。在限制DOM reflowsqueries(通常使用document.getElementbyById/getElementByTagName),实现AJAX结果的缓存(在适用的情况下)以及利用事件冒泡(某处存在链接,我现在找不到它)时,可能会更好一些。 。

+0

我试过你的脚本,不幸的是它在Firefox 3.5中保持超时。 – Dhana 2009-09-04 15:58:42

+0

更重要的是浏览器与其版本之间的性能差异。 – 2009-09-04 19:35:51