写作背景:
我们在开发过程中经常会遇到这样一个问题,同样的功能有很多中实现的方案,但是选择那种方案,那种方案最优,耗时最短呢?除了从书上写的,别人嘴里说的,我们最好是用数据来说话,眼见为实~
基准测试:
使用Benchmark.js:
1. 安装所需要的依赖:
{
"benchmark": "^2.1.4",
"chalk": "^4.1.0",
"console-table-printer": "^2.10.0",
"microtime": "^3.0.0",
"ora": "^5.1.0"
}
2. 编写benchmark主结构:
- 添加测试用例
- 设置监听
const Benchmark = require("benchmark"); const suite = new Benchmark.Suite(); const ora = require("ora"); const chalk = require("chalk"); const { getRows, p, addRow } = require("./utils"); const { description } = Benchmark.platform; const spinner = ora();
console.log(chalk.green(description)); spinner.start(chalk.grey("Testing ..."));
const cases = function (cases) { // TODO 添加case // TODO 设置监听 return suite; };
module.exports = { cases, };
注意:后续可以直接编写测试用例,不再关注主结构编写
#### 3. 使用benchmark的add函数添加测试用例:
```javascript
cases.forEach((c) => {
const key = Object.keys(c)[0];
suite.add(key, c[key]);
});
4. 设置监听来输出测试结果:
suite
.on("cycle", function (event) {
spinner.succeed(chalk.green(String(event.target)));
spinner.start(chalk.grey("Testing next case ..."));
})
.on("complete", function () {
spinner.succeed(chalk.green("Test completed"));
getRows(this.filter("successful")).forEach((row) => {
addRow(row, row.case === this.filter("fastest").map("name")[0]);
});
p.printTable();
});
5. 终端输出表格:
const p = new Table({
columns: [
{ name: "case", title: "测试用例" },
{ name: "hz", title: "执行次数/秒" },
{ name: "rme", title: "相对误差" },
{ name: "sampled", title: "总执行次数" },
{ name: "conclusion", title: "结论" },
],
sort: (r1, r2) => Number(r1.hzs) - Number(r2.hzs),
disabledColumns: ["hzs"],
});
6. 表格行数据整合:
- 第一列:测试用例名称
- 第二列:每秒执行用例次数,越高越好
- 第三列:相对误差值
- 第四列:用例被执行的实际次数
- 第五列:结论,被标记fastest的为最优用例
getRows: function (events) { const result = []; Object.keys(events).forEach((key) => { if (/^\d{0,}$/g.test(key)) { const { name, hz, stats: { sample, rme }, } = events[key]; const size = sample.length; result.push({ case: name, hz: Benchmark.formatNumber(hz.toFixed(hz < 100 ? 2 : 0)), hzs: hz, rme: `\xb1${rme.toFixed(2)}%`, sampled: `${size} run${size == 1 ? "" : "s"} sampled`, }); } }); return result; },
7. 测试用例编写:
require("../src")
.cases([
{
"RegExp#test": function () {
/o/.test("Hello World!");
},
},
{
"String#indexOf": function () {
"Hello World!".indexOf("o") > -1;
},
},
{
"String#match": function () {
!!"Hello World!".match(/o/);
},
},
])
.run({ async: true });
8. 测试结果预览
文章源码:
- benchmark-javascript
其他方案:
- jsbench:Web版基准测试,网站显示Inspired by Benchmark.js, Jsperf.com and Jsfiddle.com.
- jsperf:应该是个老牌基准测试网站,目前是服务器500了,我是没能打开过,看Github可以自己搭建使用。