123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- var Class = require('./Class');
- var defaults = require('./defaults');
- var Promise = require('./Promise');
- var perfNow = require('./perfNow');
- var delay = require('./delay');
- var average = require('./average');
- var reduce = require('./reduce');
- var each = require('./each');
- var map = require('./map');
- var table = require('./table');
- var toStr = require('./toStr');
- exports = Class(
- {
- initialize: function Benchmark(fn) {
- var options =
- arguments.length > 1 && arguments[1] !== undefined
- ? arguments[1]
- : {};
- defaults(options, defOpts);
- this._fn = fn;
- this._isRunning = false;
- this._options = options;
- },
- run: function() {
- var _this = this;
- if (this._isRunning) {
- return this._pendingPromise;
- }
- this._reset();
- this._isRunning = true;
- var options = this._options;
- var pendingPromise = new Promise(function(resolve, reject) {
- var runSample = function() {
- var initCount =
- arguments.length > 0 && arguments[0] !== undefined
- ? arguments[0]
- : 1;
- delay(function() {
- _this
- ._runSample(initCount)
- .then(function(_ref) {
- var period = _ref.period,
- count = _ref.count;
- var sample = _this._sample;
- sample.push(period);
- if (
- perfNow() - _this._timeStamp <
- options.maxTime ||
- sample.length < options.minSamples
- ) {
- runSample(count);
- } else {
- resolve(_this._calcResult());
- }
- })
- .catch(function(err) {
- reject(err);
- });
- }, options.delay);
- };
- runSample();
- });
- function complete() {
- this._isRunning = false;
- delete this._pendingPromise;
- }
- pendingPromise.then(complete).catch(complete);
- this._pendingPromise = pendingPromise;
- return pendingPromise;
- },
- _reset: function() {
- this._timeStamp = perfNow();
- this._sample = [];
- },
- _calcResult: function() {
- var sample = this._sample;
- var result = {
- sample: sample,
- toString: function() {
- var hz = this.hz,
- rme = this.rme,
- name = this.name;
- var size = this.sample.length;
- return ''
- .concat(name, ' x ')
- .concat(
- formatNumber(hz.toFixed(hz < 100 ? 2 : 0)),
- ' ops/sec \xB1'
- )
- .concat(rme.toFixed(2), '% (')
- .concat(size, ' run')
- .concat(size === 1 ? '' : 's', ' sampled)');
- }
- };
- var size = sample.length;
- result.name = this._options.name || this._fn.name || 'anonymous';
- result.mean = average.apply(null, sample);
- function varOf(sum, x) {
- return sum + Math.pow(x - result.mean, 2);
- }
- result.variance = reduce(sample, varOf, 0) / (size - 1) || 0;
- result.deviation = Math.sqrt(result.variance);
- result.sem = result.deviation / Math.sqrt(size);
- var critical = tTable[Math.round(size - 1) || 1] || tTable.infinity;
- result.moe = result.sem * critical;
- result.rme = (result.moe / result.mean) * 100 || 0;
- result.hz = 1000 / result.mean;
- return result;
- },
- _runSample: function(count) {
- var _this2 = this;
- var options = this._options;
- var minTime = options.minTime;
- return new Promise(function(resolve, reject) {
- var runCycle = function(count) {
- delay(function() {
- var elapsed = 0;
- try {
- elapsed = _this2._runCycle(count);
- } catch (e) {
- return reject(e);
- }
- var period = elapsed / count;
- if (elapsed < minTime) {
- if (elapsed === 0) {
- count *= 100;
- } else {
- count += Math.ceil(
- (minTime - elapsed) / period
- );
- }
- runCycle(count);
- } else {
- resolve({
- count: count,
- period: period
- });
- }
- }, options.delay);
- };
- runCycle(count);
- });
- },
- _runCycle: function(count) {
- var fn = this._fn;
- var now = perfNow();
- while (count--) {
- fn();
- }
- return perfNow() - now;
- }
- },
- {
- all: function(benches, options) {
- var promises = [];
- each(benches, function(bench) {
- if (!(bench instanceof exports)) {
- bench = new exports(bench, options);
- }
- promises.push(bench.run());
- });
- return Promise.all(promises).then(function(results) {
- results.toString = function() {
- var data = map(results, function(_ref2, idx) {
- var name = _ref2.name,
- sample = _ref2.sample,
- hz = _ref2.hz,
- rme = _ref2.rme;
- var columns = [];
- var size = sample.length;
- columns.push(
- toStr(idx + 1),
- name || 'anonymous',
- formatNumber(hz.toFixed(hz < 100 ? 2 : 0)),
- '\xB1'.concat(rme.toFixed(2), '%'),
- ''
- .concat(size, ' run')
- .concat(size === 1 ? '' : 's')
- );
- return columns;
- });
- data.unshift([
- 'index',
- 'name',
- 'ops/sec',
- 'rme',
- 'sampled'
- ]);
- return table(data);
- };
- return results;
- });
- }
- }
- );
- var defOpts = {
- minTime: 50,
- maxTime: 5000,
- minSamples: 5,
- delay: 5,
- name: ''
- };
- var tTable = {
- '1': 12.706,
- '2': 4.303,
- '3': 3.182,
- '4': 2.776,
- '5': 2.571,
- '6': 2.447,
- '7': 2.365,
- '8': 2.306,
- '9': 2.262,
- '10': 2.228,
- '11': 2.201,
- '12': 2.179,
- '13': 2.16,
- '14': 2.145,
- '15': 2.131,
- '16': 2.12,
- '17': 2.11,
- '18': 2.101,
- '19': 2.093,
- '20': 2.086,
- '21': 2.08,
- '22': 2.074,
- '23': 2.069,
- '24': 2.064,
- '25': 2.06,
- '26': 2.056,
- '27': 2.052,
- '28': 2.048,
- '29': 2.045,
- '30': 2.042,
- infinity: 1.96
- };
- function formatNumber(number) {
- number = String(number).split('.');
- return (
- number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') +
- (number[1] ? '.' + number[1] : '')
- );
- }
- module.exports = exports;
|