Benchmark.js 与 jsPerf 试玩

今天群里有同学提问“你们知道那种循环效率比较高吗?”,然后我想起之前在benchmark 怎么写看过、但还没试过的Benchmark,遂决定使用一下

使用Benchmark主要有两种方式,一种是本地跑,一种是使用jsPerf线上分享,具体使用方法可以看使用Benchmark.js和jsPerf分析代码性能

我对比了下for map reduce forEach4种循环方式,其中num1~1000的数组,empty是1000个undefined数组,结果如下图:

发现forundefined数组比有数字的数组慢好多,而map跑有数字的比undefined的快

我还在本地测试了一下varletfor循环中是否有差异

const Benchmark = require('benchmark')
const suite = new Benchmark.Suite;

const arr = [0,1,2,3,4,5,6,7,8,9]

// add tests
suite.add('let', function() {
  for(let i = 0, len = arr.length; i < len; i++) {
    arr[i]
  }
})
.add('var', function() {
  for(var i = 0, len = arr.length; i < len; i++) {
    arr[i]
  }
})
// add listeners
.on('cycle', function(event) {
  console.log(String(event.target));
})
.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run()

结果如下,发现letvar慢很多

let x 24,180,382 ops/sec ±0.85% (88 runs sampled)
var x 49,310,969 ops/sec ±0.96% (90 runs sampled)
Fastest is var

这些不测一测是不会知道有这么明显的差异的,接下来就是分析为什么了,这我就先不写了,最近在看了《You-Dont-Know-JS》系列的时候找到了答案(这个开源书真不错,会从编译器角度来讲解JS的一些行为,真应该早点看看)

用于for循环头部的let声明被定义了一种特殊行为。这种行为说,这个变量将不是只为循环声明一次,而是为每次迭代声明一次。并且,它将在每次后续的迭代中被上一次迭代末尾的值初始化。 —— 你不懂JS:作用域与闭包 第五章:作用域闭包

有兴趣的朋友还可以到这http://jsperf.com/browse看看,里面有250个最新的网友们的测试,昨天我随意点进去两个看了下,其中之一在测试有console.log跟没有之间的差别,还有一个测试了各种DOM选择方式的差异

还有很多更好的用法,可以参考这些github项目fast-jsfast.js

我也是刚接触这个,有啥更好的认知了回头再补充

其它参考

推荐阅读更多精彩内容