diff --git a/benchmark/buffers/buffer-from-by-group.js b/benchmark/buffers/buffer-from-by-group.js new file mode 100644 index 00000000000000..897004f08e08b6 --- /dev/null +++ b/benchmark/buffers/buffer-from-by-group.js @@ -0,0 +1,110 @@ +'use strict'; + +const common = require('../common.js'); +const assert = require('assert'); +const bench = common.createBenchmark(main, { + groupA: { + source: [ + 'array', + 'arraybuffer', + 'arraybuffer-middle', + 'buffer', + 'uint8array', + 'string', + 'string-utf8', + 'string-base64', + 'object', + ], + len: [10, 2048], + n: [2048] + }, + groupB: { + source: [ + 'buffer', + 'string', + ], + len: [2048], + n: [2048] + } +}, { byGroup: true }); + +function main({ len, n, source }) { + const array = new Array(len).fill(42); + const arrayBuf = new ArrayBuffer(len); + const str = 'a'.repeat(len); + const buffer = Buffer.allocUnsafe(len); + const uint8array = new Uint8Array(len); + const obj = { length: null }; // Results in a new, empty Buffer + + let i; + + switch (source) { + case 'array': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(array); + } + bench.end(n); + break; + case 'arraybuffer': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(arrayBuf); + } + bench.end(n); + break; + case 'arraybuffer-middle': + const offset = ~~(len / 4); + const length = ~~(len / 2); + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(arrayBuf, offset, length); + } + bench.end(n); + break; + case 'buffer': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(buffer); + } + bench.end(n); + break; + case 'uint8array': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(uint8array); + } + bench.end(n); + break; + case 'string': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(str); + } + bench.end(n); + break; + case 'string-utf8': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(str, 'utf8'); + } + bench.end(n); + break; + case 'string-base64': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(str, 'base64'); + } + bench.end(n); + break; + case 'object': + bench.start(); + for (i = 0; i < n * 1024; i++) { + Buffer.from(obj); + } + bench.end(n); + break; + default: + assert.fail(null, null, 'Should not get here'); + } +} diff --git a/benchmark/common.js b/benchmark/common.js index cad0550986bd18..5bcf7472e42055 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -12,12 +12,50 @@ exports.createBenchmark = function(fn, configs, options) { function Benchmark(fn, configs, options) { // Use the file name as the name of the benchmark this.name = require.main.filename.slice(__dirname.length + 1); - // Parse job-specific configuration from the command line arguments - const parsed_args = this._parseArgs(process.argv.slice(2), configs); - this.options = parsed_args.cli; - this.extra_options = parsed_args.extra; - // The configuration list as a queue of jobs - this.queue = this._queue(this.options); + this.queue = []; + const byGroup = (options && options.byGroup) || false; + + const enqueueConfigsInFirstGroup = (configs) => { + const firstGroupKey = Object.keys(configs)[0]; + const configsInFirstGroup = configs[firstGroupKey]; + const parsedArgs = + this._parseArgs(process.argv.slice(2), configsInFirstGroup); + this.options = parsedArgs.cli; + this.extra_options = parsedArgs.extra; + this.queue = this._queue(this.options); + }; + + const enqueueConfigsInGroups = (configs) => { + for (const groupKey of Object.keys(configs)) { + const config = configs[groupKey]; + const parsedArgs = this._parseArgs(process.argv.slice(2), config); + this.options = parsedArgs.cli; + this.extra_options = parsedArgs.extra; + // The configuration list as a queue of jobs by merging the existing + // items with the new items to return a new array + this.queue = [ ...this.queue, ...this._queue(this.options) ]; + } + }; + + const enqueueConfigs = (configs) => { + // Parse job-specific configuration from the command line arguments + const parsedArgs = this._parseArgs(process.argv.slice(2), configs); + this.options = parsedArgs.cli; + this.extra_options = parsedArgs.extra; + // The configuration list as a queue of jobs + this.queue = this._queue(this.options); + }; + + if (byGroup) { + if (process.env.NODEJS_BENCHMARK_BYPASS_GROUP) { + enqueueConfigsInFirstGroup(configs); + } else { + enqueueConfigsInGroups(configs); + } + } else { + enqueueConfigs(configs); + } + // The configuration of the current job, head of the queue this.config = this.queue[0]; // Execution arguments i.e. flags used to run the jobs diff --git a/doc/guides/writing-and-running-benchmarks.md b/doc/guides/writing-and-running-benchmarks.md index 5838449612b541..eb7da8d004d8cd 100644 --- a/doc/guides/writing-and-running-benchmarks.md +++ b/doc/guides/writing-and-running-benchmarks.md @@ -353,8 +353,25 @@ The arguments of `createBenchmark` are: possible combinations of these parameters, unless specified otherwise. Each configuration is a property with an array of possible values. Note that 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 are: + + * `flags` option for specifying command line flags is supported + * `byGroup` option for processing `configs` by groups with this syntax: + +```js +const bench = common.createBenchmark(main, { + groupA: { + source: ['array'], + len: [10, 2048], + n: [50] + }, + groupB: { + source: ['buffer', 'string'], + len: [2048], + n: [50, 2048] + } +}, { byGroup: true }); +``` `createBenchmark` returns a `bench` object, which is used for timing the runtime of the benchmark. Run `bench.start()` after the initialization diff --git a/test/benchmark/test-benchmark-buffer.js b/test/benchmark/test-benchmark-buffer.js index 171f755647d21f..b5eb7841bc2f6d 100644 --- a/test/benchmark/test-benchmark-buffer.js +++ b/test/benchmark/test-benchmark-buffer.js @@ -26,4 +26,7 @@ runBenchmark('buffers', 'value=0', 'withTotalLength=0' ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); + { + NODEJS_BENCHMARK_ZERO_ALLOWED: 1, + NODEJS_BENCHMARK_BYPASS_GROUP: 1 + });