diff --git a/benchmark/buffers/buffer-copy.js b/benchmark/buffers/buffer-copy.js index 164f31420766d5..054f72ef41cf7f 100644 --- a/benchmark/buffers/buffer-copy.js +++ b/benchmark/buffers/buffer-copy.js @@ -5,6 +5,12 @@ const bench = common.createBenchmark(main, { bytes: [0, 8, 128, 32 * 1024], partial: ['true', 'false'], n: [6e6] +}, { + combinationFilter: (p) => { + return (p.partial === 'false' && p.bytes === 0) || + (p.partial !== 'false' && p.bytes !== 0); + }, + test: { partial: 'false', bytes: 0 }, }); function main({ n, bytes, partial }) { diff --git a/benchmark/buffers/buffer-indexof.js b/benchmark/buffers/buffer-indexof.js index 4c0993a1ef0ef9..1b02a8bb7d9d38 100644 --- a/benchmark/buffers/buffer-indexof.js +++ b/benchmark/buffers/buffer-indexof.js @@ -19,9 +19,14 @@ const searchStrings = [ const bench = common.createBenchmark(main, { search: searchStrings, - encoding: ['utf8', 'ucs2'], + encoding: ['undefined', 'utf8', 'ucs2'], type: ['buffer', 'string'], n: [5e4] +}, { + combinationFilter: (p) => { + return (p.type === 'buffer' && p.encoding === 'undefined') || + (p.type !== 'buffer' && p.encoding !== 'undefined'); + }, }); function main({ n, search, encoding, type }) { diff --git a/benchmark/buffers/buffer-tostring.js b/benchmark/buffers/buffer-tostring.js index 98d6ab3fa08311..ac4e7f6c86e010 100644 --- a/benchmark/buffers/buffer-tostring.js +++ b/benchmark/buffers/buffer-tostring.js @@ -3,10 +3,15 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { - encoding: ['utf8', 'ascii', 'latin1', 'hex', 'UCS-2'], + encoding: ['', 'utf8', 'ascii', 'latin1', 'hex', 'UCS-2'], args: [0, 1, 3], len: [1, 64, 1024], n: [1e6] +}, { + combinationFilter: (p) => { + return (p.args === 0 && p.encoding === '') || + (p.args !== 0 && p.encoding !== ''); + }, }); function main({ encoding, args, len, n }) { diff --git a/benchmark/common.js b/benchmark/common.js index 6ed230ffde4231..9a58823f9888a4 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -3,6 +3,10 @@ const child_process = require('child_process'); const http_benchmarkers = require('./_http-benchmarkers.js'); +function allow() { + return true; +} + class Benchmark { constructor(fn, configs, options = {}) { // Used to make sure a benchmark only start a timer once @@ -31,9 +35,17 @@ class Benchmark { this.flags = this.flags.concat(options.flags); } + if (typeof options.combinationFilter === 'function') + this.combinationFilter = options.combinationFilter; + else + this.combinationFilter = allow; + // The configuration list as a queue of jobs this.queue = this._queue(this.options); + if (this.queue.length === 0) + return; + // The configuration of the current job, head of the queue this.config = this.queue[0]; @@ -108,6 +120,7 @@ class Benchmark { _queue(options) { const queue = []; const keys = Object.keys(options); + const { combinationFilter } = this; // Perform a depth-first walk through all options to generate a // configuration list that contains all combinations. @@ -131,7 +144,15 @@ class Benchmark { if (keyIndex + 1 < keys.length) { recursive(keyIndex + 1, currConfig); } else { - queue.push(currConfig); + // Check if we should allow the current combination + const allowed = combinationFilter({ ...currConfig }); + if (typeof allowed !== 'boolean') { + throw new TypeError( + 'Combination filter must always return a boolean' + ); + } + if (allowed) + queue.push(currConfig); } } } diff --git a/doc/contributing/writing-and-running-benchmarks.md b/doc/contributing/writing-and-running-benchmarks.md index 9422d42519453c..ffc622abeecb91 100644 --- a/doc/contributing/writing-and-running-benchmarks.md +++ b/doc/contributing/writing-and-running-benchmarks.md @@ -450,8 +450,12 @@ The arguments of `createBenchmark` are: possible combinations of these parameters, unless specified otherwise. Each configuration is a property with an array of possible values. The configuration values can only be strings or numbers. -* `options` {Object} The benchmark options. At the moment only the `flags` - option for specifying command line flags is supported. +* `options` {Object} The benchmark options. Supported options: + * `flags` {Array} Contains node-specific command line flags to pass to + the child process. + * `combinationFilter` {Function} Has a single parameter which is an object + containing a combination of benchmark parameters. It should return `true` + or `false` to indicate whether the combination should be included or not. `createBenchmark` returns a `bench` object, which is used for timing the runtime of the benchmark. Run `bench.start()` after the initialization