为什么str.charAt(i)比Node.js中的str [i]快1.6倍

时间:2014-11-26 09:00:05

标签: javascript string node.js

var s = '', ok = ' h dfb  ds84 78sgf  ydf hjb////**', lc = 0, cc = 0

for (var i = 0; i < 300000; i++) {
    s += ok[Math.floor(Math.random() * ok.length)]
}

console.time('[]')
for (var i = 0; i < s.length; i++) {
    if (s[i] == '/' && s[i+1] == '/') lc++, i++
    if (s[i] == '/' && s[i+1] == '*') cc++, i++
}
console.timeEnd('[]')
/*
console.time('charAt')
for (var i = 0; i < s.length; i++) {
    if (s.charAt(i) == '/' && s.charAt(i+1) == '/') lc++, i++
    if (s.charAt(i) == '/' && s.charAt(i+1) == '*') cc++, i++
}
console.timeEnd('charAt')
*/
console.time('regex')
var rlc = (s.match(/\/\//g) || []).length;
var rcc = (s.match(/\/\*/g) || []).length;
console.timeEnd('regex')

console.log(lc, cc, rlc==lc, rcc==cc)

为什么str.charAt()始终显示比str []提高1.6的性能?他们不应该以同样的方式做同样的事情吗? []会做一些影响速度的额外检查或转换吗?或者它是关于我的代码?

此外,为什么str.charCodeAt(i) == 42str.charAt(i) == '/'快10%?从C / C ++的角度来看,它完全没有意义。

更新:我把完整的测试代码放在这里。

UPDATE2:我必须说这是使用Node.js ver 0.11.4

观察到的

http://jsperf.com/brackets-vs-charat3 此测试用例显示较小的差异。 charAt()在Chrome 37中慢了6%,在Firefox 33中慢了1%。所有Ubuntu 64。

更新3,因为这似乎是Node.js问题,我添加了node.js标记

2 个答案:

答案 0 :(得分:2)

  

他们不应该以同样的方式做同样的事情吗?

没有。除了明显不同的方式,他们不会做同样的事情。查看spec for charAtfor [] on strings

  

[]是否会进行一些影响速度的额外检查或转换?

显然。不同之处在于charAt需要将其操作数强制转换为字符串,[]不需要这样做。此外,charAt将返回空字符串以进行越界访问,而[]将返回undefined。而且大多数情况下,[]需要检查给定的属性名称是否真的是一个整数,以及字符串对象上是否存在具有该名称的实际属性

  

还是我的代码呢?

您的代码看起来很好。

  

此外为什么str.charCodeAt(i)== 42比str.charAt(i)=='/'快10%?从C / C ++的角度来看,它完全没有意义。

请注意,JavaScript没有char数据类型。 '/'是一个长度为1的字符串。看起来它没有很好地优化(或者很容易),并且整数 1 比较比字符串快比较。

1:大多数数字,虽然“每个规范”是64位浮点数,但在V8中表示为31位整数。

答案 1 :(得分:-2)

引用Crockford的“JavaScript:the Good Parts”,打开Chap 6,Arrays的段落:

  

...数组可以是非常快速的数据结构。不幸的是,JavaScript没有像这种数组那样的东西。   相反,JavaScript提供了一个具有类似数组特征的对象。它将数组下标转换为用于创建属性的字符串。它比真正的阵列慢得多......

因此,在C或Java中,arr [2]是指向内存位置的直接指针,因此应具有非常快的性能,在JS中,arr [2]实际上意味着“将数字2转换为字符串'2' ,然后将其哈希以用作对象中的查找。“

散列查找仍然非常快,但不如真正的数组快。添加它需要将数字转换为字符串然后进行散列,并且您会看到性能损失。

另一方面,我认为str.charAt(2)是一个本机函数,可能正在进行真正的数组查找。