mirror of https://github.com/lukechilds/node.git
Browse Source
This removes the need for parsing stdout from the benchmarks. If the process wasn't executed by fork, it will just print like it used to. This also fixes the parsing of CLI arguments, by inferring the type from the options object instead of the value content. Only two benchmarks had to be changed: * http/http_server_for_chunky_client.js this previously used a spawn now it uses a fork and relays the messages using common.sendResult. * misc/v8-bench.js this utilized that v8/benchmark/run.js called global.print and reformatted the input. It now interfaces directly with the benchmark runner global.BenchmarkSuite. PR-URL: https://github.com/nodejs/node/pull/7094 Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Brian White <mscdex@mscdex.net> Reviewed-By: Anna Henningsen <anna@addaleax.net>v7.x
Andreas Madsen
9 years ago
5 changed files with 358 additions and 232 deletions
@ -0,0 +1,99 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const fs = require('fs'); |
||||
|
const path = require('path'); |
||||
|
|
||||
|
// Create an object of all benchmark scripts
|
||||
|
const benchmarks = {}; |
||||
|
fs.readdirSync(__dirname) |
||||
|
.filter(function(name) { |
||||
|
return fs.statSync(path.resolve(__dirname, name)).isDirectory(); |
||||
|
}) |
||||
|
.forEach(function(category) { |
||||
|
benchmarks[category] = fs.readdirSync(path.resolve(__dirname, category)) |
||||
|
.filter((filename) => filename[0] !== '.' && filename[0] !== '_'); |
||||
|
}); |
||||
|
|
||||
|
function CLI(usage, settings) { |
||||
|
if (!(this instanceof CLI)) return new CLI(usage, settings); |
||||
|
|
||||
|
if (process.argv.length < 3) { |
||||
|
this.abort(usage); // abort will exit the process
|
||||
|
} |
||||
|
|
||||
|
this.usage = usage; |
||||
|
this.optional = {}; |
||||
|
this.items = []; |
||||
|
|
||||
|
for (const argName of settings.arrayArgs) { |
||||
|
this.optional[argName] = []; |
||||
|
} |
||||
|
|
||||
|
let currentOptional = null; |
||||
|
let mode = 'both'; // possible states are: [both, option, item]
|
||||
|
|
||||
|
for (const arg of process.argv.slice(2)) { |
||||
|
if (arg === '--') { |
||||
|
// Only items can follow --
|
||||
|
mode = 'item'; |
||||
|
} else if (['both', 'option'].includes(mode) && arg[0] === '-') { |
||||
|
// Optional arguments declaration
|
||||
|
|
||||
|
if (arg[1] === '-') { |
||||
|
currentOptional = arg.slice(2); |
||||
|
} else { |
||||
|
currentOptional = arg.slice(1); |
||||
|
} |
||||
|
|
||||
|
// Default the value to true
|
||||
|
if (!settings.arrayArgs.includes(currentOptional)) { |
||||
|
this.optional[currentOptional] = true; |
||||
|
} |
||||
|
|
||||
|
// expect the next value to be option related (either -- or the value)
|
||||
|
mode = 'option'; |
||||
|
} else if (mode === 'option') { |
||||
|
// Optional arguments value
|
||||
|
|
||||
|
if (settings.arrayArgs.includes(currentOptional)) { |
||||
|
this.optional[currentOptional].push(arg); |
||||
|
} else { |
||||
|
this.optional[currentOptional] = arg; |
||||
|
} |
||||
|
|
||||
|
// the next value can be either an option or an item
|
||||
|
mode = 'both'; |
||||
|
} else if (['both', 'item'].includes(mode)) { |
||||
|
// item arguments
|
||||
|
this.items.push(arg); |
||||
|
|
||||
|
// the next value must be an item
|
||||
|
mode = 'item'; |
||||
|
} else { |
||||
|
// Bad case, abort
|
||||
|
this.abort(usage); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
module.exports = CLI; |
||||
|
|
||||
|
CLI.prototype.abort = function(msg) { |
||||
|
console.error(msg); |
||||
|
process.exit(1); |
||||
|
}; |
||||
|
|
||||
|
CLI.prototype.benchmarks = function() { |
||||
|
const paths = []; |
||||
|
const filter = this.optional.filter || false; |
||||
|
|
||||
|
for (const category of this.items) { |
||||
|
for (const scripts of benchmarks[category]) { |
||||
|
if (filter && scripts.lastIndexOf(filter) === -1) continue; |
||||
|
|
||||
|
paths.push(path.join(category, scripts)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return paths; |
||||
|
}; |
@ -1,63 +1,51 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
const fs = require('fs'); |
|
||||
const path = require('path'); |
const path = require('path'); |
||||
const child_process = require('child_process'); |
const fork = require('child_process').fork; |
||||
|
const CLI = require('./_cli.js'); |
||||
var outputFormat = process.env.OUTPUT_FORMAT || |
|
||||
(+process.env.NODE_BENCH_SILENT ? 'silent' : false) || |
|
||||
'default'; |
|
||||
|
|
||||
// If this is the main module, then run the benchmarks
|
|
||||
if (module === require.main) { |
|
||||
var type = process.argv[2]; |
|
||||
var testFilter = process.argv[3]; |
|
||||
if (!type) { |
|
||||
console.error('usage:\n ./node benchmark/run.js <type> [testFilter]'); |
|
||||
process.exit(1); |
|
||||
} |
|
||||
|
|
||||
var dir = path.join(__dirname, type); |
const cli = CLI(`usage: ./node run.js [options] [--] <category> ...
|
||||
var tests = fs.readdirSync(dir); |
Run each benchmark in the <category> directory a single time, more than one |
||||
|
<categoty> directory can be specified. |
||||
|
|
||||
if (testFilter) { |
--filter pattern string to filter benchmark scripts |
||||
var filteredTests = tests.filter(function(item) { |
--set variable=value set benchmark variable (can be repeated) |
||||
if (item.lastIndexOf(testFilter) >= 0) { |
`, {
|
||||
return item; |
arrayArgs: ['set'] |
||||
} |
|
||||
}); |
}); |
||||
|
const benchmarks = cli.benchmarks(); |
||||
|
|
||||
if (filteredTests.length === 0) { |
if (benchmarks.length === 0) { |
||||
console.error('%s is not found in \n %j', testFilter, tests); |
console.error('no benchmarks found'); |
||||
return; |
process.exit(1); |
||||
} |
|
||||
tests = filteredTests; |
|
||||
} |
} |
||||
|
|
||||
runBenchmarks(); |
(function recursive(i) { |
||||
} |
const filename = benchmarks[i]; |
||||
|
const child = fork(path.resolve(__dirname, filename), cli.optional.set); |
||||
|
|
||||
function runBenchmarks() { |
console.log(); |
||||
var test = tests.shift(); |
console.log(filename); |
||||
if (!test) |
|
||||
return; |
|
||||
|
|
||||
if (test.match(/^[\._]/)) |
child.on('message', function(data) { |
||||
return process.nextTick(runBenchmarks); |
// Construct configuration string, " A=a, B=b, ..."
|
||||
|
let conf = ''; |
||||
if (outputFormat == 'default') |
for (const key of Object.keys(data.conf)) { |
||||
console.error(type + '/' + test); |
conf += ' ' + key + '=' + JSON.stringify(data.conf[key]); |
||||
|
} |
||||
|
|
||||
test = path.resolve(dir, test); |
console.log(`${data.name}${conf}: ${data.rate}`); |
||||
|
}); |
||||
|
|
||||
var a = (process.execArgv || []).concat(test); |
child.once('close', function(code) { |
||||
var child = child_process.spawn(process.execPath, a, { stdio: 'inherit' }); |
|
||||
child.on('close', function(code) { |
|
||||
if (code) { |
if (code) { |
||||
process.exit(code); |
process.exit(code); |
||||
} else { |
return; |
||||
console.log(''); |
|
||||
runBenchmarks(); |
|
||||
} |
} |
||||
}); |
|
||||
|
// If there are more benchmarks execute the next
|
||||
|
if (i + 1 < benchmarks.length) { |
||||
|
recursive(i + 1); |
||||
} |
} |
||||
|
}); |
||||
|
})(0); |
||||
|
Loading…
Reference in new issue