├── package.json ├── .gitignore ├── test.js ├── README.md └── index.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "beautify-benchmark", 3 | "version": "0.2.4", 4 | "description": "Beautify Benchmark.js's output into readable form.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git@github.com:Fishrock123/beautify-benchmark.git" 12 | }, 13 | "keywords": [ 14 | "benchmark", 15 | "beautify" 16 | ], 17 | "author": { 18 | "name": "Jeremiah Senkpiel", 19 | "email": "fishrock123@rocketmail.com" 20 | }, 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/Fishrock123/beautify-benchmark/issues", 24 | "email": "fishrock123@rocketmail.com" 25 | }, 26 | "homepage": "https://github.com/Fishrock123/beautify-benchmark", 27 | "devDependencies": { 28 | "benchmark": "*" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store* 32 | # Icon? 33 | ehthumbs.db 34 | Thumbs.db 35 | 36 | # Node.js # 37 | ########### 38 | lib-cov 39 | *.seed 40 | *.log 41 | *.csv 42 | *.dat 43 | *.out 44 | *.pid 45 | *.gz 46 | 47 | pids 48 | logs 49 | results 50 | 51 | node_modules 52 | npm-debug.log 53 | 54 | # Components # 55 | ############## 56 | 57 | /build 58 | /components 59 | 60 | # Sublime Text # 61 | ############## 62 | *.sublime-project 63 | *.sublime-workspace 64 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | , Benchmark = require('benchmark') 3 | , suite = new Benchmark.Suite 4 | , benchmarks = require('./index') 5 | 6 | function getRandom() { 7 | return Math.floor(Math.random() * 381) 8 | } 9 | 10 | function getSlow() { 11 | var out = Math.floor(Math.random() * 381) 12 | return out > 67 && out < 193 ? blaaaah(out) : out 13 | } 14 | 15 | function getSlowRandom() { 16 | var out = Math.floor(Math.random() * 381) 17 | return out > 354 && out < 355 ? blaaaah(out) : out 18 | } 19 | 20 | function blaaaah(num) { 21 | // consume excess time for absolutely no reason at all 22 | for (var i = 0; i < num + num; i++) { 23 | "catslol".split(num) 24 | } 25 | return num 26 | } 27 | 28 | suite.add('current', function() { 29 | return getRandom() < 0 ? true : false 30 | }) 31 | .add('legacy', function() { 32 | return ~getRandom() ? false: true 33 | }) 34 | .add('very blaaaah', function() { 35 | return ~getSlow() ? false: true 36 | }) 37 | .add('random blaaaah', function() { 38 | return ~getSlowRandom() ? false: true 39 | }) 40 | .on('cycle', function(event) { 41 | benchmarks.add(event.target) 42 | }) 43 | .on('start', function(event) { 44 | console.log('\n Starting...') 45 | }) 46 | .on('complete', function done() { 47 | var current = benchmarks.getPercent('current') 48 | benchmarks.log() 49 | if (current < 95) 50 | assert.fail('' + current + '%', '95%', null, '>=', done) 51 | }) 52 | .run({ 'async': false }) 53 | 54 | suite = new Benchmark.Suite 55 | 56 | suite.add('cats', function() { 57 | return Math.abs(getRandom()) 58 | }) 59 | .add('whaaaaale', function() { 60 | return Math.atan2(getRandom(), getRandom()) 61 | }) 62 | .on('cycle', function(event) { 63 | benchmarks.add(event.target) 64 | }) 65 | .on('start', function(event) { 66 | console.log('\n Starting...') 67 | }) 68 | .on('complete', function() { 69 | benchmarks.log() 70 | }) 71 | .run({ 'async': false }) 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Beautify-Benchmark [![NPM version](https://badge.fury.io/js/beautify-benchmark.svg)](http://badge.fury.io/js/beautify-benchmark) 2 | 3 | Beautify Benchmark.js's output into readable form. 4 | 5 | ## API 6 | 7 | ```js 8 | var Benchmark = require('benchmark') 9 | , suite = new Benchmark.Suite 10 | , benchmarks = require('beautify-benchmark') 11 | ``` 12 | 13 | ### benchmarks.add(event.target) 14 | 15 | ```js 16 | suit.on('cycle', function(event) { 17 | benchmarks.add(event.target) 18 | }) 19 | ``` 20 | 21 | ### benchmarks.getPercent(name) 22 | Returns the percentage of the given benchmark's ops/sec compared to the highest ops/sec. 23 | 24 | ### benchmarks.reset() 25 | 26 | Manually clear the stored benchmarks. 27 | 28 | ### benchmarks.log(options) 29 | 30 | ```js 31 | suit.on('complete', function() { 32 | benchmarks.log() 33 | }) 34 | ``` 35 | 36 | ##### default options 37 | ```js 38 | options: { 39 | reset: true 40 | , tolerances: { pass: .95, mid: .80 } 41 | } 42 | ``` 43 | 44 | ## Result 45 | 46 | ![beautify-benchmark output](http://imgur.com/AME4QSr.png) 47 | 48 | ## License 49 | 50 | The MIT License (MIT) 51 | 52 | Copyright (c) 2013-2014 Jeremiah Senkpiel 53 | 54 | Permission is hereby granted, free of charge, to any person obtaining a copy 55 | of this software and associated documentation files (the "Software"), to deal 56 | in the Software without restriction, including without limitation the rights 57 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58 | copies of the Software, and to permit persons to whom the Software is 59 | furnished to do so, subject to the following conditions: 60 | 61 | The above copyright notice and this permission notice shall be included in 62 | all copies or substantial portions of the Software. 63 | 64 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 66 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 67 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 68 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 69 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 70 | THE SOFTWARE. 71 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | exports.add = add 2 | exports.log = log 3 | exports.reset = reset 4 | exports.getPercent = getPercent 5 | exports.store = [] 6 | exports.numCompleted = 0 7 | 8 | var name_maxlen = 0 9 | , ops_maxlen = 0 10 | , ops_arr = [] 11 | , ops_top 12 | // Using Mocha's coloring 13 | // https://github.com/visionmedia/mocha/blob/master/lib/reporters/base.js#L100 14 | , colors = { 15 | 'pass': 90 16 | , 'fail': 31 17 | , 'pending': 36 18 | , 'suite': 0 19 | , 'fast': 90 20 | , 'medium': 33 21 | , 'slow': 31 22 | , 'green': 32 23 | } 24 | 25 | console.log('') 26 | 27 | function add(bench) { 28 | exports.store.push(bench) 29 | 30 | var len = (bench.name || (Number.isNaN(id) ? id : '')).length 31 | name_maxlen = len > name_maxlen ? len : name_maxlen 32 | var ops = bench.hz.toFixed(bench.hz < 100 ? 2 : 0) 33 | ops_maxlen = formatNumber(ops).length > ops_maxlen ? formatNumber(ops).length : ops_maxlen 34 | ops_arr.push(ops) 35 | ops_top = Math.max.apply(Math, ops_arr); 36 | 37 | process.stdout.write(' ' 38 | + color('pending', (++exports.numCompleted)) 39 | + ' test' 40 | + (exports.numCompleted > 1 ? 's' : '') 41 | + ' completed.\u000D') 42 | } 43 | 44 | function getPercent(name) { 45 | var bench; 46 | for (var i = exports.store.length - 1; i >= 0; i--) { 47 | var element = exports.store[i] 48 | if (element.name && element.name == name) { 49 | bench = element 50 | break 51 | } 52 | } 53 | return bench ? (bench.hz.toFixed(bench.hz < 100 ? 2 : 0) / ops_top) * 100 : 0 54 | } 55 | 56 | function log(options) { 57 | options = options || {} 58 | var reset = options.reset || true 59 | , tolerances = options.tolerances || { pass: .95, mid: .80 } 60 | 61 | console.log('\n') 62 | 63 | for (var i = 0; i < exports.store.length; i++) { 64 | logBench(exports.store[i], tolerances) 65 | } 66 | 67 | if (options.reset === undefined || options.reset === true) exports.reset() 68 | 69 | console.log('') 70 | } 71 | 72 | function reset() { 73 | exports.numCompleted = 0 74 | exports.store = [] 75 | ops_arr = [] 76 | name_maxlen = 0 77 | ops_maxlen = 0 78 | } 79 | 80 | function logBench(bench, tolerances) { 81 | var error = bench.error 82 | , hz = bench.hz 83 | , id = bench.id 84 | , stats = bench.stats 85 | , size = stats.sample.length 86 | , result = bench.name || (Number.isNaN(id) ? id : '') 87 | , name_len = result.length 88 | , ops = hz.toFixed(hz < 100 ? 2 : 0) 89 | , deviation = stats.rme.toFixed(2) 90 | , percent = ops / ops_top 91 | 92 | if (ops == ops_top) result = color('green', result) 93 | 94 | if (error) { 95 | result += ': ' + color('fail', join(error)) 96 | } else { 97 | result += makeSpace(name_maxlen - name_len) 98 | + color('pass', ' x ') 99 | + makeSpace(ops_maxlen - formatNumber(ops).length) 100 | + color( 101 | percent > (tolerances.pass || .95) ? 'green' 102 | : percent > (tolerances.mid || .80) ? 'medium' 103 | : 'slow', formatNumber(ops)) 104 | + ' ops/sec ' 105 | + color('pass', '\xb1') 106 | + color( 107 | deviation > 5 ? 'slow' 108 | : deviation > 2 ? 'medium' 109 | : 'green', deviation) 110 | + color('pending', '% ') 111 | + '\u001b[' + colors['pass'] + 'm(' 112 | + size 113 | + ' run' + (size == 1 ? '' : 's') 114 | + ' sampled)' 115 | + '\u001b[0m' 116 | } 117 | console.log(' ' + result) 118 | } 119 | 120 | function makeSpace(len) { 121 | var out = '' 122 | for (var i = len - 1; i >= 0; i--) out += ' ' 123 | return out 124 | } 125 | 126 | function color(type, str) { 127 | return '\u001b[' + colors[type] + 'm' + str + '\u001b[0m' 128 | } 129 | 130 | function formatNumber(number) { 131 | number = String(number).split('.') 132 | return number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') 133 | + (number[1] ? '.' + number[1] : '') 134 | } 135 | 136 | function join(object) { 137 | var result = [] 138 | , length = (object = Object(object)).length 139 | , arrayLike = length === length >>> 0 140 | 141 | for (key in object) { 142 | var value = object[key] 143 | result.push(arrayLike ? value : key + ': ' + value) 144 | } 145 | return result.join(',') 146 | } 147 | --------------------------------------------------------------------------------