isaacs | aa2edd4 | 2013-02-12 07:28:48 | [diff] [blame^] | 1 | var usage = 'node benchmark/compare.js <node-binary1> <node-binary2>'; |
| 2 | |
| 3 | var show = 'both'; |
| 4 | var nodes = []; |
| 5 | for (var i = 2; i < process.argv.length; i++) { |
| 6 | var arg = process.argv[i]; |
| 7 | switch (arg) { |
| 8 | case '--red': case '-r': |
| 9 | show = show === 'green' ? 'both' : 'red'; |
| 10 | break; |
| 11 | case '--green': case '-g': |
| 12 | show = show === 'red' ? 'both' : 'green'; |
| 13 | break; |
| 14 | default: |
| 15 | nodes.push(arg); |
| 16 | break; |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | var runBench = process.env.NODE_BENCH || 'bench'; |
| 21 | |
| 22 | if (nodes.length !== 2) |
| 23 | return console.error('usage:\n %s', usage); |
| 24 | |
| 25 | var spawn = require('child_process').spawn; |
| 26 | var results = {}; |
| 27 | var n = 2; |
| 28 | |
| 29 | run(); |
| 30 | |
| 31 | function run() { |
| 32 | if (n === 0) |
| 33 | return compare(); |
| 34 | |
| 35 | n--; |
| 36 | |
| 37 | var node = nodes[n]; |
| 38 | console.error('running %s', node); |
| 39 | var env = {}; |
| 40 | for (var i in process.env) |
| 41 | env[i] = process.env[i]; |
| 42 | env.NODE = node; |
| 43 | var child = spawn('make', [ runBench ], { env: env }); |
| 44 | |
| 45 | var out = ''; |
| 46 | child.stdout.setEncoding('utf8'); |
| 47 | child.stdout.on('data', function(c) { |
| 48 | out += c; |
| 49 | }); |
| 50 | |
| 51 | child.stderr.pipe(process.stderr); |
| 52 | |
| 53 | child.on('close', function(code) { |
| 54 | if (code) { |
| 55 | console.error('%s exited with code=%d', node, code); |
| 56 | process.exit(code); |
| 57 | } else { |
| 58 | out.trim().split(/\r?\n/).forEach(function(line) { |
| 59 | line = line.trim(); |
| 60 | if (!line) |
| 61 | return; |
| 62 | |
| 63 | var s = line.split(':'); |
| 64 | var num = +s.pop(); |
| 65 | if (!num && num !== 0) |
| 66 | return |
| 67 | |
| 68 | line = s.join(':'); |
| 69 | var res = results[line] = results[line] || {}; |
| 70 | res[node] = num; |
| 71 | }); |
| 72 | |
| 73 | run(); |
| 74 | } |
| 75 | }); |
| 76 | } |
| 77 | |
| 78 | function compare() { |
| 79 | // each result is an object with {"foo.js arg=bar":12345,...} |
| 80 | // compare each thing, and show which node did the best. |
| 81 | // node[0] is shown in green, node[1] shown in red. |
| 82 | var green = '\033[1;32m'; |
| 83 | var red = '\033[1;31m'; |
| 84 | var reset = '\033[m'; |
| 85 | var maxLen = -Infinity; |
| 86 | var util = require('util'); |
| 87 | Object.keys(results).map(function(bench) { |
| 88 | var res = results[bench]; |
| 89 | var n0 = res[nodes[0]]; |
| 90 | var n1 = res[nodes[1]]; |
| 91 | |
| 92 | var pct = ((n0 - n1) / ((n0 + n1) / 2) * 100).toFixed(2); |
| 93 | |
| 94 | var g = n0 > n1 ? green : ''; |
| 95 | var r = n0 > n1 ? '' : red; |
| 96 | var c = r || g; |
| 97 | |
| 98 | if (show === 'green' && !g || show === 'red' && !r) |
| 99 | return; |
| 100 | |
| 101 | var r0 = util.format('%s%s: %d%s', g, nodes[0], n0, reset); |
| 102 | var r1 = util.format('%s%s: %d%s', r, nodes[1], n1, reset); |
| 103 | var pct = c + pct + '%' + reset; |
| 104 | var l = util.format('%s: %s %s', bench, r0, r1); |
| 105 | maxLen = Math.max(l.length + pct.length, maxLen); |
| 106 | return [l, pct]; |
| 107 | }).filter(function(l) { |
| 108 | return l; |
| 109 | }).forEach(function(line) { |
| 110 | var l = line[0]; |
| 111 | var pct = line[1]; |
| 112 | var dotLen = maxLen - l.length - pct.length + 2; |
| 113 | var dots = ' ' + new Array(Math.max(0, dotLen)).join('.') + ' '; |
| 114 | console.log(l + dots + pct); |
| 115 | }); |
| 116 | } |