benchmarkify
Advanced tools
Comparing version 3.0.0 to 4.0.0
@@ -13,3 +13,4 @@ module.exports = { | ||
"parserOptions": { | ||
"sourceType": "module" | ||
"sourceType": "module", | ||
"ecmaVersion": "2020" | ||
}, | ||
@@ -16,0 +17,0 @@ "rules": { |
665
index.js
@@ -1,664 +0,3 @@ | ||
const _ = require("lodash"); | ||
const kleur = require("kleur"); | ||
const humanize = require("tiny-human-time"); | ||
"use strict"; | ||
const ora = require("ora"); | ||
/** | ||
* Formatting number | ||
* | ||
* @param {any} value Number value | ||
* @param {number} [decimals=0] Count of decimals | ||
* @param {boolean} [sign=false] Put '+' sign if the number is positive | ||
* @returns | ||
*/ | ||
function formatNumber(value, decimals = 0, sign = false) { | ||
let res = Number(value.toFixed(decimals)).toLocaleString(); | ||
if (sign && value > 0.0) res = "+" + res; | ||
return res; | ||
} | ||
function delay(ms) { | ||
return new Promise(resolve => setTimeout(resolve, ms)); | ||
} | ||
/** | ||
* Test case class | ||
* | ||
* @class TestCase | ||
*/ | ||
class TestCase { | ||
/** | ||
* Creates an instance of TestCase. | ||
* | ||
* @param {Suite} suite | ||
* @param {String} name | ||
* @param {Function} fn | ||
* @param {Object} opts | ||
* | ||
* @memberOf TestCase | ||
*/ | ||
constructor(suite, name, fn, opts) { | ||
this.suite = suite; | ||
this.name = name; | ||
this.fn = fn; | ||
this.async = fn.length > 0; | ||
this.opts = opts || {}; | ||
this.skip = false; | ||
this.done = false; | ||
this.running = false; | ||
this.time = this.opts.time || this.suite.time || 5000; | ||
this.cycles = this.opts.cycles || this.suite.cycles || 1000; | ||
this.minSamples = this.opts.minSamples || this.suite.minSamples || 5; | ||
this.timer = null; | ||
this.startTime = null; | ||
this.startHrTime = null; | ||
this.stat = { | ||
duration: null, | ||
cycle: 0, | ||
count: 0, | ||
avg: null, | ||
rps: null | ||
}; | ||
} | ||
/** | ||
* | ||
* | ||
* @returns | ||
* | ||
* @memberOf TestCase | ||
*/ | ||
run() { | ||
const self = this; | ||
return new Promise((resolve, reject) => { | ||
// Start test | ||
self.start(); | ||
// Run | ||
if (self.async) { | ||
self.cyclingAsyncCb(resolve, reject); | ||
} else { | ||
self.cycling(resolve); | ||
} | ||
}); | ||
} | ||
/** | ||
* | ||
* | ||
* | ||
* @memberOf TestCase | ||
*/ | ||
start() { | ||
this.running = true; | ||
this.stat.count = 0; | ||
this.startTime = Date.now(); | ||
this.startHrTime = process.hrtime(); | ||
} | ||
/** | ||
* | ||
* | ||
* | ||
* @memberOf TestCase | ||
*/ | ||
finish() { | ||
const diff = process.hrtime(this.startHrTime); | ||
const count = this.stat.count; | ||
const duration = diff[0] + diff[1] / 1e9; | ||
_.assign(this.stat, { | ||
duration, | ||
avg: duration / count, | ||
rps: count / duration | ||
}); | ||
this.done = true; | ||
this.running = false; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} resolve | ||
* | ||
* @memberOf TestCase | ||
*/ | ||
cycling(resolve) { | ||
if (Date.now() - this.startTime < this.time || this.stat.count < this.minSamples) { | ||
for (let i = 0; i < this.cycles; i++) { | ||
this.fn(); | ||
this.stat.count++; | ||
} | ||
this.stat.cycle++; | ||
setImmediate(() => this.cycling(resolve)); | ||
} else { | ||
this.finish(); | ||
resolve(this); | ||
} | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} resolve | ||
* | ||
* @memberOf TestCase | ||
* | ||
cyclingAsync(resolve, reject) { | ||
const self = this; | ||
const fn = self.fn; | ||
let c = 0; | ||
function cycle() { | ||
return fn().then(() => { | ||
self.stat.count++; | ||
c++; | ||
if (c >= self.cycles) { | ||
if (Date.now() - self.startTime < self.time || self.stat.count < self.minSamples) { | ||
c = 0; | ||
return new Promise(resolve => { | ||
setImmediate(() => resolve(cycle())); | ||
}); | ||
} | ||
} else { | ||
return cycle(); | ||
} | ||
}); | ||
} | ||
return cycle() | ||
.then(() => { | ||
self.finish(); | ||
resolve(self); | ||
}).catch(reject); | ||
}*/ | ||
/** | ||
* | ||
* | ||
* @param {any} resolve | ||
* | ||
* @memberOf TestCase | ||
*/ | ||
cyclingAsyncCb(resolve) { | ||
const self = this; | ||
const fn = self.fn; | ||
let c = 0; | ||
function cycle() { | ||
fn(function () { | ||
self.stat.count++; | ||
c++; | ||
if (c >= self.cycles) { | ||
if ( | ||
Date.now() - self.startTime < self.time || | ||
self.stat.count < self.minSamples | ||
) { | ||
// Wait for new cycle | ||
c = 0; | ||
setImmediate(() => cycle()); | ||
} else { | ||
// Finished | ||
self.finish(); | ||
resolve(self); | ||
} | ||
} else { | ||
// Next call | ||
cycle(); | ||
} | ||
}); | ||
} | ||
// Start | ||
cycle(); | ||
} | ||
} | ||
/** | ||
* | ||
* | ||
* @class Suite | ||
*/ | ||
class Suite { | ||
/** | ||
* Creates an instance of Suite. | ||
* @param {Benchmarkify} parent | ||
* @param {String} name | ||
* @param {Object} opts | ||
* | ||
* @memberOf Suite | ||
*/ | ||
constructor(parent, name, opts = {}) { | ||
this.parent = parent; | ||
this.name = name; | ||
this.description = opts.description; | ||
this.meta = opts.meta || {}; | ||
this.logger = this.parent.logger; | ||
this.onlyTest = null; | ||
this.done = false; | ||
this.running = false; | ||
this.locals = {}; | ||
this.tests = []; | ||
_.assign( | ||
this, | ||
{ | ||
time: 5000, | ||
minSamples: 0 | ||
}, | ||
opts | ||
); | ||
if (!this.cycles) this.cycles = this.minSamples > 0 ? this.minSamples : 1000; | ||
} | ||
/** | ||
* Add a "setup" function to be run before test. | ||
* | ||
* @param {Function} fn | ||
*/ | ||
setup(fn) { | ||
this.setupFn = fn; | ||
return this; | ||
} | ||
/** | ||
* Add a "tearDown" function to be run after test. | ||
* | ||
* @param {Function} fn | ||
*/ | ||
tearDown(fn) { | ||
this.tearDownFn = fn; | ||
return this; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} name | ||
* @param {any} fn | ||
* @param {any} opts | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
appendTest(name, fn, opts) { | ||
const test = new TestCase(this, name, fn, opts); | ||
this.tests.push(test); | ||
return test; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} name | ||
* @param {any} fn | ||
* @param {any} [opts={}] | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
add(name, fn, opts = {}) { | ||
this.appendTest(name, fn, opts); | ||
return this; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} name | ||
* @param {any} fn | ||
* @param {any} [opts={}] | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
only(name, fn, opts = {}) { | ||
this.onlyTest = this.appendTest(name, fn, opts); | ||
return this; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} name | ||
* @param {any} fn | ||
* @param {any} [opts={}] | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
skip(name, fn, opts = {}) { | ||
const test = this.appendTest(name, fn, opts); | ||
test.skip = true; | ||
return this; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} name | ||
* @param {any} fn | ||
* @param {any} [opts={}] | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
ref(name, fn, opts = {}) { | ||
const test = this.appendTest(name, fn, opts); | ||
test.reference = true; | ||
return this; | ||
} | ||
/** | ||
* | ||
* | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
run() { | ||
let self = this; | ||
self.maxTitleLength = | ||
this.tests.reduce((max, test) => Math.max(max, test.name.length), 0) + 2; | ||
if (this.onlyTest) { | ||
this.tests.forEach(test => (test.skip = test !== this.onlyTest)); | ||
} | ||
return Promise.resolve() | ||
.then(() => { | ||
if (_.isFunction(self.setupFn)) return self.setupFn.call(self); | ||
else if (Array.isArray(self.setupFn)) | ||
return Promise.all(self.setupFn.map(fn => fn.call(self))); | ||
}) | ||
.then(() => { | ||
return new Promise(resolve => { | ||
self.running = true; | ||
self.logger.log(kleur.magenta().bold(`Suite: ${self.name}`)); | ||
this.runTest(Array.from(this.tests), resolve); | ||
}); | ||
}) | ||
.then(() => { | ||
if (_.isFunction(self.tearDownFn)) return self.tearDownFn.call(self); | ||
else if (Array.isArray(self.tearDownFn)) | ||
return Promise.all(self.tearDownFn.map(fn => fn.call(self))); | ||
}) | ||
.then(() => { | ||
if (self.parent.spinner) self.parent.spinner.stop(); | ||
self.logger.log(""); | ||
// Generate results | ||
return self.calculateResult(); | ||
}); | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} list | ||
* @param {any} resolve | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
runTest(list, resolve) { | ||
const self = this; | ||
const test = list.shift(); | ||
function printAndRun(type, msg, err) { | ||
if (self.parent.spinner) self.parent.spinner[type](msg); | ||
else self.logger.log("››", msg); | ||
if (err) self.logger.error(err); | ||
return list.length > 0 ? self.runTest(list, resolve) : resolve(); | ||
} | ||
if (test.skip) { | ||
// Skip test | ||
return printAndRun("warn", kleur.yellow(`[SKIP] ${test.name}`)); | ||
} | ||
if (this.parent.spinner) { | ||
// Refresh spinner | ||
self.parent.spinner.text = `Running '${test.name}'...`; | ||
self.parent.spinner.start(); | ||
} | ||
// Run test | ||
return test | ||
.run() | ||
.then(() => delay(200)) | ||
.then(() => { | ||
const flag = test.async ? "*" : ""; | ||
let msg = | ||
_.padEnd(test.name + flag, self.maxTitleLength) + | ||
_.padStart(formatNumber(test.stat.rps) + " rps", 20); | ||
return printAndRun("succeed", msg); | ||
}) | ||
.catch(err => { | ||
test.error = err; | ||
return printAndRun("fail", kleur.red("[ERR] " + test.name), err); | ||
}); | ||
} | ||
/** | ||
* | ||
* | ||
* @returns | ||
* | ||
* @memberOf Suite | ||
*/ | ||
calculateResult() { | ||
let maxRps = 0; | ||
let maxTitleLength = 0; | ||
let fastest = null; | ||
let reference = null; | ||
this.tests.forEach(test => { | ||
if (test.skip) return; | ||
if (test.reference) reference = test; | ||
if (test.stat.rps > maxRps) { | ||
maxRps = test.stat.rps; | ||
fastest = test; | ||
} | ||
if (test.name.length > maxTitleLength) maxTitleLength = test.name.length; | ||
}); | ||
//this.tests.sort((a, b) => b.stat.rps - a.stat.rps); | ||
let pe = _.padEnd; | ||
let ps = _.padStart; | ||
this.tests.forEach(test => { | ||
if (test.skip) { | ||
this.logger.log(kleur.yellow(` ${test.name} (skipped)`)); | ||
return; | ||
} | ||
if (test.error) { | ||
this.logger.log(kleur.red(` ${test.name} (error: ${test.error.message})`)); | ||
return; | ||
} | ||
const baseRps = reference ? reference.stat.rps : fastest.stat.rps; | ||
const c = test == fastest ? kleur.green() : kleur.cyan(); | ||
test.stat.percent = (test.stat.rps / baseRps) * 100 - 100; | ||
let flag = test.async ? "*" : ""; | ||
if (test == reference) flag += " (#)"; | ||
let line = [ | ||
" ", | ||
pe(test.name + flag, maxTitleLength + 5), | ||
ps(formatNumber(test.stat.percent, 2, true) + "%", 8), | ||
ps(" (" + formatNumber(test.stat.rps) + " rps)", 20), | ||
" (avg: " + humanize.short(test.stat.avg * 1000) + ")" | ||
]; | ||
this.logger.log(c.bold(line.join(" "))); | ||
}); | ||
this.logger.log( | ||
"-----------------------------------------------------------------------\n" | ||
); | ||
// Generate result to return | ||
const result = this.tests.map(test => { | ||
let item = { | ||
name: test.name, | ||
meta: test.meta || {} | ||
}; | ||
if (test === fastest) item.fastest = true; | ||
if (test.reference) item.reference = true; | ||
if (test.error) item.error = test.error.toString(); | ||
if (!test.skip) item.stat = test.stat; | ||
else item.skipped = true; | ||
return item; | ||
}); | ||
return result; | ||
} | ||
} | ||
/** | ||
* | ||
* | ||
* @class Benchmarkify | ||
*/ | ||
class Benchmarkify { | ||
/** | ||
* Creates an instance of Benchmarkify. | ||
* @param {any} name | ||
* @param {any} logger | ||
* | ||
* @memberOf Benchmarkify | ||
*/ | ||
constructor(name, opts = {}) { | ||
this.name = name; | ||
this.description = opts.description; | ||
this.meta = opts.meta || {}; | ||
this.logger = opts.logger || console; | ||
if (opts.spinner !== false) { | ||
this.spinner = ora({ | ||
text: "Running benchmark...", | ||
spinner: { | ||
interval: 400, | ||
frames: [". ", ".. ", "...", " ..", " .", " "] | ||
} | ||
}); | ||
} | ||
this.Promise = Promise; | ||
this.suites = []; | ||
} | ||
/** | ||
* | ||
* | ||
* | ||
* @memberOf Benchmarkify | ||
*/ | ||
printPlatformInfo() { | ||
require("./platform")(this.logger); | ||
this.logger.log(""); | ||
} | ||
/** | ||
* | ||
* | ||
* @param {boolean} [platformInfo=true] | ||
* | ||
* @memberOf Benchmarkify | ||
*/ | ||
printHeader(platformInfo = true) { | ||
let title = " " + this.name + " "; | ||
let lines = "=".repeat(title.length); | ||
this.logger.log(kleur.yellow().bold(lines)); | ||
this.logger.log(kleur.yellow().bold(title)); | ||
this.logger.log(kleur.yellow().bold(lines)); | ||
this.logger.log(""); | ||
if (platformInfo) this.printPlatformInfo(); | ||
return this; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {String} name | ||
* @param {any} opts | ||
* @returns | ||
* | ||
* @memberOf Benchmarkify | ||
*/ | ||
createSuite(name, opts) { | ||
const suite = new Suite(this, name, opts); | ||
this.suites.push(suite); | ||
return suite; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {any} suites | ||
* @returns | ||
* | ||
* @memberOf Benchmarkify | ||
*/ | ||
run(suites) { | ||
const self = this; | ||
let list = Array.from(suites || this.suites); | ||
let results = []; | ||
let start = Date.now(); | ||
/** | ||
* | ||
* | ||
* @param {any} suite | ||
* @returns | ||
*/ | ||
function run(suite) { | ||
return suite.run().then(res => { | ||
results.push({ | ||
name: suite.name, | ||
description: suite.description, | ||
meta: suite.meta, | ||
tests: res | ||
}); | ||
if (list.length > 0) return run(list.shift()); | ||
return { | ||
name: self.name, | ||
description: self.description, | ||
meta: self.meta, | ||
suites: results, | ||
timestamp: Date.now(), | ||
generated: new Date().toString(), | ||
elapsedMs: Date.now() - start | ||
}; | ||
}); | ||
} | ||
return run(list.shift()); | ||
} | ||
} | ||
module.exports = Benchmarkify; | ||
module.exports = require("./src/benchmarkify"); |
{ | ||
"name": "benchmarkify", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"description": "Benchmark runner for NodeJS", | ||
@@ -22,5 +22,6 @@ "main": "index.js", | ||
"dependencies": { | ||
"kleur": "^4.1.4", | ||
"kleur": "^4.1.5", | ||
"lodash": "^4.17.21", | ||
"ora": "^5.4.1", | ||
"qs": "^6.11.2", | ||
"tiny-human-time": "^1.2.0" | ||
@@ -33,4 +34,4 @@ }, | ||
"engines": { | ||
"node": ">=10.0.0" | ||
"node": ">=12.0.0" | ||
} | ||
} |
154
README.md
# :zap: benchmarkify | ||
Benchmark framework for NodeJS for measure the execution time of JS codes. | ||
Benchmark framework for Node.js for measure the execution time of JS codes. It can generate JSON result, chart image or draw a simple bar chart to the console. | ||
# Installation | ||
``` | ||
$ npm install benchmarkify --save-dev | ||
$ npm i benchmarkify | ||
``` | ||
@@ -18,20 +18,22 @@ | ||
// information from the OS/PC to the console. | ||
const benchmark = new Benchmarkify("Simple example").printHeader(); | ||
const benchmark = new Benchmarkify("Simple example", { description: "This is a common benchmark", chartImage: true }).printHeader(); | ||
let i = 0; | ||
// Create a test suite | ||
const bench1 = benchmark.createSuite("Increment integer"); | ||
benchmark.createSuite("String concatenate", { time: 1000, description: "Concatenate string in different ways" }) | ||
// Add first func | ||
bench1.add("Increment with ++", () => { | ||
i++; | ||
}); | ||
.add("Concat with '+'", () => { | ||
let s = ""; | ||
for (let i = 0; i < 1000; i++) | ||
s += "test" + i; | ||
return s; | ||
}) | ||
// Add second func. This result will be the reference | ||
bench1.ref("Increment with i + 1", () => { | ||
i = i + 1; | ||
}); | ||
.ref("Concat with array & join", () => { | ||
let s = []; | ||
for (let i = 0; i < 1000; i++) | ||
s.push("test" + i); | ||
return s.join(); | ||
}); | ||
bench1.run(); | ||
benchmark.run(); | ||
``` | ||
@@ -47,51 +49,86 @@ | ||
============== | ||
Windows_NT 6.1.7601 x64 | ||
Node.JS: 6.10.0 | ||
V8: 5.1.281.93 | ||
Intel(R) Core(TM) i7-4770K CPU @ 3.50GHz × 8 | ||
Windows_NT 10.0.19045 x64 | ||
Node.JS: 18.16.0 | ||
V8: 10.2.154.26-node.26 | ||
CPU: 13th Gen Intel(R) Core(TM) i5-13500 × 20 | ||
Memory: 32 GB | ||
Suite: Increment integer | ||
√ Increment with ++ 98,878,885 rps | ||
√ Increment with i + 1 89,930,539 rps | ||
Suite: String concatenate | ||
========================= | ||
Increment with ++ +9.95% (98,878,885 rps) (avg: 10ns) | ||
Increment with i + 1 (#) 0% (89,930,539 rps) (avg: 11ns) | ||
√ Concat with '+' 105 533 ops/sec | ||
√ Concat with array & join 57 987 ops/sec | ||
Concat with '+' +81,99% (105 533 ops/sec) (avg: 9μs) | ||
Concat with array & join (#) 0% (57 987 ops/sec) (avg: 17μs) | ||
┌──────────────────────────┬────────────────────────────────────────────────────┐ | ||
│ Concat with '+' │ ██████████████████████████████████████████████████ │ | ||
├──────────────────────────┼────────────────────────────────────────────────────┤ | ||
│ Concat with array & join │ ███████████████████████████ │ | ||
└──────────────────────────┴────────────────────────────────────────────────────┘ | ||
Chart: https://image-charts.com/chart.js/2.8.0?bkg=white&c=%7B%22type%22%3A%22bar%22%2C%22data%22%3A%7B%22labels%22%3A%5B%22Concat%20with%20%27%2B%27%22%2C%22Concat%20with%20array%20%26%20join%22%5D%2C%22datasets%22%3A%5B%7B%22label%22%3A%22Dataset%201%22%2C%22backgroundColor%22%3A%22rgba%2854%2C%20162%2C%20235%2C%200.5%29%22%2C%22borderColor%22%3A%22rgb%2854%2C%20162%2C%20235%29%22%2C%22borderWidth%22%3A1%2C%22data%22%3A%5B105532.65917212216%2C57986.883366982394%5D%7D%5D%7D%2C%22options%22%3A%7B%22responsive%22%3Afalse%2C%22legend%22%3A%7B%22display%22%3Afalse%2C%22position%22%3A%22top%22%7D%2C%22title%22%3A%7B%22display%22%3Atrue%2C%22text%22%3A%22String%20concatenate%7C%28ops%2Fsec%29%22%7D%2C%22layout%22%3A%7B%22padding%22%3A20%7D%7D%7D | ||
----------------------------------------------------------------------- | ||
``` | ||
**Example chart image** | ||
![Example chart image](https://image-charts.com/chart.js/2.8.0?bkg=white&c=%7B%22type%22%3A%22bar%22%2C%22data%22%3A%7B%22labels%22%3A%5B%22Concat%20with%20%27%2B%27%22%2C%22Concat%20with%20array%20%26%20join%22%5D%2C%22datasets%22%3A%5B%7B%22label%22%3A%22Dataset%201%22%2C%22backgroundColor%22%3A%22rgba%2854%2C%20162%2C%20235%2C%200.5%29%22%2C%22borderColor%22%3A%22rgb%2854%2C%20162%2C%20235%29%22%2C%22borderWidth%22%3A1%2C%22data%22%3A%5B105320.73392654078%2C57369.423976363796%5D%7D%5D%7D%2C%22options%22%3A%7B%22responsive%22%3Afalse%2C%22legend%22%3A%7B%22display%22%3Afalse%2C%22position%22%3A%22top%22%7D%2C%22title%22%3A%7B%22display%22%3Atrue%2C%22text%22%3A%22String%20concatenate%7C%28ops%2Fsec%29%22%7D%2C%22layout%22%3A%7B%22padding%22%3A20%7D%7D%7D) | ||
**JSON result** | ||
If you need the results in JSON use `.then` after `run()` | ||
```js | ||
bench1.run().then(res => console.log(res)); | ||
benchmark.run().then(res => console.log(res)); | ||
``` | ||
Result on console: | ||
**Result on the console:** | ||
```js | ||
[ | ||
{ | ||
name: 'Increment with ++', | ||
fastest: true, | ||
stat: { | ||
duration: 4.999651845, | ||
cycle: 492086, | ||
count: 492086000, | ||
avg: 1.0160118038310376e-8, | ||
rps: 98424053.36525989, | ||
percent: 9.95071720945748 | ||
} | ||
}, | ||
{ | ||
name: 'Increment with i + 1', | ||
reference: true, | ||
stat: { | ||
duration: 4.999535403, | ||
cycle: 447541, | ||
count: 447541000, | ||
avg: 1.117112265244972e-8, | ||
rps: 89516517.82112603, | ||
percent: 0 | ||
} | ||
} | ||
] | ||
{ | ||
name: 'Simple example', | ||
description: 'This is a common benchmark', | ||
meta: {}, | ||
suites: [ | ||
{ | ||
name: 'String concatenate', | ||
description: 'Concatenate string in different ways', | ||
meta: {}, | ||
unit: 'ops/sec', | ||
tests: [ | ||
{ | ||
name: "Concat with '+'", | ||
meta: {}, | ||
unit: 'ops/sec', | ||
fastest: true, | ||
stat: { | ||
duration: 1.0064495, | ||
cycle: 106, | ||
count: 106000, | ||
avg: 0.000009494806603773585, | ||
rps: 105320.73392654078, | ||
percent: 83.58339098878338 | ||
} | ||
}, | ||
{ | ||
name: 'Concat with array & join', | ||
meta: {}, | ||
unit: 'ops/sec', | ||
reference: true, | ||
stat: { | ||
duration: 1.0109915, | ||
cycle: 58, | ||
count: 58000, | ||
avg: 0.000017430887931034482, | ||
rps: 57369.423976363796, | ||
percent: 0 | ||
} | ||
} | ||
] | ||
} | ||
], | ||
timestamp: 1693594301782, | ||
generated: 'Fri Sep 01 2023 20:51:41 GMT+0200 (közép-európai nyári idő)', | ||
elapsedMs: 2466 | ||
} | ||
``` | ||
@@ -113,2 +150,4 @@ | ||
* `meta` - To store any meta information. Result JSON contains it. | ||
* `chartImage` - Generate chart image url and print to the console after every suite. | ||
* `drawChart` - Draw a bar chart to the console after every suite. Default: `true` | ||
@@ -130,2 +169,3 @@ ### Methods | ||
* `description` - Custom description field. | ||
* `unit` - Measurement unit. Default: `"ops/sec"`. | ||
* `meta` - To store any meta information. Result JSON contains it. | ||
@@ -147,3 +187,3 @@ | ||
bench.add("Async call test", done => { | ||
asyncFunction(data).then(() => done()); | ||
asyncFunction(data).then(() => done()); | ||
}); | ||
@@ -156,4 +196,4 @@ ``` | ||
bench.add("Async call test", async done => { | ||
await asyncFunction(data) | ||
done(); | ||
await asyncFunction(data) | ||
done(); | ||
}); | ||
@@ -167,4 +207,4 @@ ``` | ||
Copyright (C) 2021 Icebob | ||
Copyright (C) 2023 Icebob | ||
[![@icebob](https://img.shields.io/badge/github-icebob-green.svg)](https://github.com/icebob) [![@icebob](https://img.shields.io/badge/twitter-Icebobcsi-blue.svg)](https://twitter.com/Icebobcsi) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27834
11
749
204
5
1
+ Addedqs@^6.11.2
+ Addedcall-bind-apply-helpers@1.0.1(transitive)
+ Addedcall-bound@1.0.3(transitive)
+ Addeddunder-proto@1.0.1(transitive)
+ Addedes-define-property@1.0.1(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-object-atoms@1.0.0(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedget-intrinsic@1.2.6(transitive)
+ Addedgopd@1.2.0(transitive)
+ Addedhas-symbols@1.1.0(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedmath-intrinsics@1.1.0(transitive)
+ Addedobject-inspect@1.13.3(transitive)
+ Addedqs@6.13.1(transitive)
+ Addedside-channel@1.1.0(transitive)
+ Addedside-channel-list@1.0.0(transitive)
+ Addedside-channel-map@1.0.1(transitive)
+ Addedside-channel-weakmap@1.0.2(transitive)
Updatedkleur@^4.1.5