Javascript中嵌套for循环与数组函数的性能
昨天我写了一小段代码,它使用两个for循环来比较两个数组中的对象(尽管数组是相同的) 我的路线感觉它的响应有点慢,但是,正在迭代的数据是一个数据库查询的结果,该查询可能包含成千上万个项目,我想确保我不会无缘无故地影响服务器的性能。因此,我将这些函数插入到jsperf中,这让我很难过。for循环的运行速度约为2600次/秒,而第二个块的运行速度约为500次/秒:( 问题是,我的第二个代码块是否写得很差,是否可以改进并提高速度?如果不是,这是否正常?我看到越来越多的人在推广函数式javascript 我是否以风格的名义损害了性能?我是否应该享受学习函数式语言的乐趣,而将其从javascript中删除 约翰·雷斯格似乎是个粉丝-> 我意识到这篇文章很快从非常具体到非常一般,如果有人建议,我会编辑范围并发表一篇新文章 编辑:在组中添加了lodash和下划线测试。lodash以大约870 ops/sec的速度排在第二位,下划线测试仅为475 ops/secJavascript中嵌套for循环与数组函数的性能,javascript,node.js,performance,functional-programming,Javascript,Node.js,Performance,Functional Programming,昨天我写了一小段代码,它使用两个for循环来比较两个数组中的对象(尽管数组是相同的) 我的路线感觉它的响应有点慢,但是,正在迭代的数据是一个数据库查询的结果,该查询可能包含成千上万个项目,我想确保我不会无缘无故地影响服务器的性能。因此,我将这些函数插入到jsperf中,这让我很难过。for循环的运行速度约为2600次/秒,而第二个块的运行速度约为500次/秒:( 问题是,我的第二个代码块是否写得很差,是否可以改进并提高速度?如果不是,这是否正常?我看到越来越多的人在推广函数式javascript
我找到了fast.js与for循环和js本机函数的基准,它同样被一个简单的for循环吹走了。数组方法天生比for循环慢,因为1)它们必须在每次迭代时重新构建函数范围,2)其中一些(
.map
,.reduce
)必须重建阵列的副本(因此需要更多内存、更多垃圾收集,通常需要更多操作)。所以,如果你担心速度,就尽量保持低速度
但是,特别是对于您的算法,您可以做一些事情来改进运行时。您最昂贵的操作是LevenshteinDistance
,因此优化该操作将大大提高速度
您可以做的最简单的事情是检查字符串的长度并提前返回:您知道如果两个字符串的长度相差超过选项。距离它们的Levenshtein距离将至少超过该值,因此您可以轻松地提前返回:
for (var j = 0; j < compareArr.length; j++) {
// This check was added
if (Math.abs(res[i].name.length - compareArr[j].name.length) > options.distance) {
continue;
}
if(natural.LevenshteinDistance(res[i].name, compareArr[j].name) === options.distance) {
tempObj.matches.push(compareArr[j])
}
}
for(var j=0;joptions.distance){
继续;
}
if(natural.levenshteindication(res[i].name,comparararr[j].name)==options.distance){
tempObj.matches.push(comparearl[j])
}
}
该方法本身还有一些改进,在另一篇stackoverflow文章中有更好的解释:内置函数做得太多,因此速度较慢。通常在实践中,这并不是什么大问题,但你仍然可以保留抽象,但可以用它们来代替类似的东西。埃尔克兰斯:啊,我应该为FastJS和LoDash添加测试,我完全忘记了这些选项。:)嗯,我在长度上加了cach'ing,这样就不会每次重复都命中,实际上这比不使用cache要慢,所以对我来说,这些结果是不可靠的。为什么缓存不能比缓存快?顺便说一句-对我来说,“firefox”-本机浏览器func比库快得多。@jamesemanon:链接到缓存测试?我刚刚在firefox上运行了我自己的测试,虽然for循环仍然是最快的,但是原生函数紧随其后,libs失败得很惨,lodash的速度只有119次/秒。当然,这些结果很有趣,但也完全没有意义,因为node在v8引擎上运行。请参阅:,我刚从您的初始版本创建了一个新版本。
var result = res.
map(function(baseItem) {
baseItem.matches = compareArr.
reduce(function(acc, compItem) {
if(natural.LevenshteinDistance(baseItem.name, compItem.name) === options.distance) {
acc.push(compItem)
}
return acc
}, [])
return baseItem
}).
filter(function(item) {
return item.matches.length > 0
})
for (var j = 0; j < compareArr.length; j++) {
// This check was added
if (Math.abs(res[i].name.length - compareArr[j].name.length) > options.distance) {
continue;
}
if(natural.LevenshteinDistance(res[i].name, compareArr[j].name) === options.distance) {
tempObj.matches.push(compareArr[j])
}
}