Javascript Firefox中的大型子字符串比Chrome快90000倍:为什么? 基准:

Javascript Firefox中的大型子字符串比Chrome快90000倍:为什么? 基准:,javascript,performance,google-chrome,firefox,jsperf,Javascript,Performance,Google Chrome,Firefox,Jsperf,所以,我开始了我的第一个基于HTML5浏览器的客户端项目。它必须将非常非常大的文本文件解析为一个或多个对象数组。我知道我将如何编码它;我现在最关心的是尽快得到解析器代码,我的主要测试平台是Chrome。然而,在观察子字符串方法之间的差异时(我已经很久很久没有接触JavaScript了),我注意到这个基准在Chrome上比FireFox慢得令人难以置信。为什么? 我的第一个假设是,这与FireFox的JS引擎处理字符串对象的方式有关,对于FireFox来说,这个操作是简单的指针操作,而对于Chro

所以,我开始了我的第一个基于HTML5浏览器的客户端项目。它必须将非常非常大的文本文件解析为一个或多个对象数组。我知道我将如何编码它;我现在最关心的是尽快得到解析器代码,我的主要测试平台是Chrome。然而,在观察子字符串方法之间的差异时(我已经很久很久没有接触JavaScript了),我注意到这个基准在Chrome上比FireFox慢得令人难以置信。为什么?

我的第一个假设是,这与FireFox的JS引擎处理字符串对象的方式有关,对于FireFox来说,这个操作是简单的指针操作,而对于Chrome来说,它实际上是在进行硬拷贝。但是,我不知道为什么Chrome不会做指针操作,或者为什么FireFox会做。有人有什么见解吗

JSPerf似乎在抛出我的FireFox结果,而不是在BrowserScope上显示它们。对我来说,我在FF4中的
.substr()
上获得了9568203±1.44%的运算/秒

编辑:所以我看到一个FF3.5的性能结果在Chrome下面。所以我决定检验我的指针假设。这让我想到了我的子字符串测试,它在FF4中执行
1092718±1.62%
Ops/sec,而在Chrome中执行
1195±3.81%
Ops/sec,速度只快了1000倍,但性能上仍然存在无法解释的差异


附言:不,我一点也不关心Internet Explorer。我关心的是如何提高我的技能,并更深入地了解这门语言。

您是否已从基准测试结果中删除了对
.length
的阅读

我相信V8有一些字符串表示:

1. a sequence of ASCII bytes
2. a sequence of UTF-16 code units.
3. a slice of a string (result of substring)
4. a concatenation of two strings.
数字4使字符串
+=
高效

我只是猜测,但如果他们试图将两个字符串指针和一个长度打包到一个小空间中,他们可能无法使用指针缓存大长度,因此可能最终会遍历连接的链接列表以计算长度。当然,这假设
Array.prototype.join
从数组部分创建形式为(4)的字符串

它确实导致了一个可测试的假设,即使没有缓冲区拷贝,也可以解释这种差异

编辑:


我浏览了V8源代码,然后开始使用它,特别是
runtime.cc

在Spidermonkey(Firefox中的JS引擎)的情况下,
substring()
调用只会创建一个新的“依赖字符串”:一个字符串对象,它存储指向关闭的子字符串以及开始和结束偏移量的指针。这正是为了使
substring()
快速,并且对于不可变字符串来说,这是一个明显的优化

至于为什么V8不这样做。。。一种可能是V8试图节省空间:在依赖字符串设置中,如果您保留子字符串但忘记了原始字符串,则原始字符串无法获得GCD,因为子字符串正在使用其部分字符串数据

在任何情况下,我只是查看了V8源代码,看起来它们根本不做任何类型的依赖字符串;不过,这些评论并没有解释他们为什么不这么做


[更新,2013年12月]:在我给出上述答案几个月后,正如Paul Draper指出的那样,V8增加了对依赖字符串的支持。

链接位于标题的最顶端。或者…?我不知道它是如何实现的,但如果您正在解析,您能用字符串上的迭代替换子字符串吗?AFAIK许多解析算法更面向流。我正在使用索引对字符串进行迭代,但我仍然必须提取子字符串以从文件中提取数据。我在Chrome 11中看到~1.1k/s,在FF3.6中看到~250/s。您可以尝试将其解析为流,而不使用任何子字符串类型函数。。。如果字段开头有标记,只需将每个字符附加到变量中,直到到达字段末尾。此变量将包含整个字段,而不必使用子字符串方法。相比之下,向变量追加字符的速度应该快得离谱。这个答案是不正确的,因为V8没有依赖字符串。甚至有人担心这会导致小字符串占用大量内存。V8在2011年8月左右添加了依赖字符串。看见因此,在给出答案时,答案实际上是正确的。如果您在原始问题的测试用例上尝试当前的Chrome,它的行为与Chrome当时完全不同。