From 51a6b821db395e6e314ea2c551a8c44758e4e150 Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Sat, 9 Mar 2019 21:22:45 -0500 Subject: [PATCH 01/10] benchmark: add byGroup option in benchmark configs --- benchmark/common.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index cad0550986bd18..fdae0bec711de3 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -12,12 +12,27 @@ 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; + + if (byGroup) { + for (var groupKey of Object.keys(configs)) { + const config = configs[groupKey]; + const parsed_args = this._parseArgs(process.argv.slice(2), config); + this.options = parsed_args.cli; + this.extra_options = parsed_args.extra; + // The configuration list as a queue of jobs + this.queue = [ ...this.queue, ...this._queue(this.options) ]; + } + } else { + // 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); + } + // 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 From a6fc43c7e2b3ccdd9eb429700e82297b02a11ca6 Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Sat, 9 Mar 2019 21:23:37 -0500 Subject: [PATCH 02/10] benchmark: adapt byGroup option with buffer-form-by-group.js benchmark --- benchmark/buffers/buffer-from-by-group.js | 110 ++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 benchmark/buffers/buffer-from-by-group.js diff --git a/benchmark/buffers/buffer-from-by-group.js b/benchmark/buffers/buffer-from-by-group.js new file mode 100644 index 00000000000000..8955086c4387c9 --- /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 + + var 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'); + } +} From 272fa0741ec768d67150a2977a64014df5a71ed6 Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Sat, 9 Mar 2019 21:24:17 -0500 Subject: [PATCH 03/10] doc: add byGroup option and example in writing-and-running-benchmarks.md --- doc/guides/writing-and-running-benchmarks.md | 21 ++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) 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 From ccce103a4f254130bdb891c0403d8480b1e23fb0 Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Sat, 9 Mar 2019 21:36:09 -0500 Subject: [PATCH 04/10] refactor: update const variables and comment in benchmark common.js --- benchmark/common.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index fdae0bec711de3..7aeb10ebeb3337 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -16,12 +16,13 @@ function Benchmark(fn, configs, options) { const byGroup = (options && options.byGroup) || false; if (byGroup) { - for (var groupKey of Object.keys(configs)) { + for (const groupKey of Object.keys(configs)) { const config = configs[groupKey]; const parsed_args = this._parseArgs(process.argv.slice(2), config); this.options = parsed_args.cli; this.extra_options = parsed_args.extra; - // The configuration list as a queue of jobs + // 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) ]; } } else { From 883c90a062a8b706d26aae0fda4706b47c710cb5 Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Sat, 9 Mar 2019 21:36:41 -0500 Subject: [PATCH 05/10] refactor: update let variable in benchmark buffer-from-by-group.js --- benchmark/buffers/buffer-from-by-group.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/buffers/buffer-from-by-group.js b/benchmark/buffers/buffer-from-by-group.js index 8955086c4387c9..897004f08e08b6 100644 --- a/benchmark/buffers/buffer-from-by-group.js +++ b/benchmark/buffers/buffer-from-by-group.js @@ -36,7 +36,7 @@ function main({ len, n, source }) { const uint8array = new Uint8Array(len); const obj = { length: null }; // Results in a new, empty Buffer - var i; + let i; switch (source) { case 'array': From 0bfdd66765e9e98e6a7420e29e069fc610bc6731 Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Tue, 19 Mar 2019 00:58:02 -0400 Subject: [PATCH 06/10] benchmark: add process.env.NODEJS_BENCHMARK_BYPASS_GROUP support --- benchmark/common.js | 25 +++++++++++++++++++++++-- test/benchmark/test-benchmark-buffer.js | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index 7aeb10ebeb3337..7f343fd89268b4 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -15,7 +15,16 @@ function Benchmark(fn, configs, options) { this.queue = []; const byGroup = (options && options.byGroup) || false; - if (byGroup) { + const enqueueConfigsInFirstGroup = (configs) => { + const firstConfigKey = Object.keys(configs)[0]; + const firstConfig = configs[firstConfigKey]; + const parsed_args = this._parseArgs(process.argv.slice(2), firstConfig); + this.options = parsed_args.cli; + this.extra_options = parsed_args.extra; + this.queue = this._queue(this.options); + }; + + const enqueueConfigsInGroups = (configs) => { for (const groupKey of Object.keys(configs)) { const config = configs[groupKey]; const parsed_args = this._parseArgs(process.argv.slice(2), config); @@ -25,7 +34,9 @@ function Benchmark(fn, configs, options) { // items with the new items to return a new array this.queue = [ ...this.queue, ...this._queue(this.options) ]; } - } else { + }; + + const enqueuConfigs = (configs) => { // Parse job-specific configuration from the command line arguments const parsed_args = this._parseArgs(process.argv.slice(2), configs); this.options = parsed_args.cli; @@ -34,6 +45,16 @@ function Benchmark(fn, configs, options) { this.queue = this._queue(this.options); } + if (byGroup) { + if (process.env.NODEJS_BENCHMARK_BYPASS_GROUP) { + enqueueConfigsInFirstGroup(configs); + } else { + enqueueConfigsInGroups(configs); + } + } else { + enqueuConfigs(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/test/benchmark/test-benchmark-buffer.js b/test/benchmark/test-benchmark-buffer.js index 171f755647d21f..feff5767d5feb7 100644 --- a/test/benchmark/test-benchmark-buffer.js +++ b/test/benchmark/test-benchmark-buffer.js @@ -26,4 +26,4 @@ runBenchmark('buffers', 'value=0', 'withTotalLength=0' ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); + { NODEJS_BENCHMARK_ZERO_ALLOWED: 1, NODEJS_BENCHMARK_BYPASS_GROUP: 1 }); From 7e802abfc500174f44359b37c3087bab3392797b Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Tue, 19 Mar 2019 01:14:22 -0400 Subject: [PATCH 07/10] benchmark: correct typo of enqueueConfigs function in benchmark common --- benchmark/common.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index 7f343fd89268b4..e644301bb94cd3 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -36,7 +36,7 @@ function Benchmark(fn, configs, options) { } }; - const enqueuConfigs = (configs) => { + const enqueueConfigs = (configs) => { // Parse job-specific configuration from the command line arguments const parsed_args = this._parseArgs(process.argv.slice(2), configs); this.options = parsed_args.cli; @@ -52,7 +52,7 @@ function Benchmark(fn, configs, options) { enqueueConfigsInGroups(configs); } } else { - enqueuConfigs(configs); + enqueueConfigs(configs); } // The configuration of the current job, head of the queue From b961b0240b3f3ed34306bd70a2f7842c5805565c Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Tue, 19 Mar 2019 01:42:15 -0400 Subject: [PATCH 08/10] benchmark: update code format in benchmark/common.js --- benchmark/common.js | 2 +- test/benchmark/test-benchmark-buffer.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index e644301bb94cd3..73f71af5d880e1 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -43,7 +43,7 @@ function Benchmark(fn, configs, options) { this.extra_options = parsed_args.extra; // The configuration list as a queue of jobs this.queue = this._queue(this.options); - } + }; if (byGroup) { if (process.env.NODEJS_BENCHMARK_BYPASS_GROUP) { diff --git a/test/benchmark/test-benchmark-buffer.js b/test/benchmark/test-benchmark-buffer.js index feff5767d5feb7..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_BYPASS_GROUP: 1 }); + { + NODEJS_BENCHMARK_ZERO_ALLOWED: 1, + NODEJS_BENCHMARK_BYPASS_GROUP: 1 + }); From 81ffaec546815ae01ab247f81c9165fce777e9cf Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Tue, 19 Mar 2019 02:02:39 -0400 Subject: [PATCH 09/10] benchmark: rename variables in benchmark/common.js --- benchmark/common.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index 73f71af5d880e1..c21aa93ee9fdf8 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -16,9 +16,10 @@ function Benchmark(fn, configs, options) { const byGroup = (options && options.byGroup) || false; const enqueueConfigsInFirstGroup = (configs) => { - const firstConfigKey = Object.keys(configs)[0]; - const firstConfig = configs[firstConfigKey]; - const parsed_args = this._parseArgs(process.argv.slice(2), firstConfig); + const firstGroupKey = Object.keys(configs)[0]; + const configsInFirstGroup = configs[firstGroupKey]; + const parsed_args = + this._parseArgs(process.argv.slice(2), configsInFirstGroup); this.options = parsed_args.cli; this.extra_options = parsed_args.extra; this.queue = this._queue(this.options); From 6d847e848efe75471ce6f6064fa8f7131f36e27b Mon Sep 17 00:00:00 2001 From: Beni von Cheni Date: Wed, 20 Mar 2019 13:41:11 -0400 Subject: [PATCH 10/10] benchmark: rename parsedArgs variables in benchmark/common.js --- benchmark/common.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/benchmark/common.js b/benchmark/common.js index c21aa93ee9fdf8..5bcf7472e42055 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -18,19 +18,19 @@ function Benchmark(fn, configs, options) { const enqueueConfigsInFirstGroup = (configs) => { const firstGroupKey = Object.keys(configs)[0]; const configsInFirstGroup = configs[firstGroupKey]; - const parsed_args = + const parsedArgs = this._parseArgs(process.argv.slice(2), configsInFirstGroup); - this.options = parsed_args.cli; - this.extra_options = parsed_args.extra; + 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 parsed_args = this._parseArgs(process.argv.slice(2), config); - this.options = parsed_args.cli; - this.extra_options = parsed_args.extra; + 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) ]; @@ -39,9 +39,9 @@ function Benchmark(fn, configs, options) { const enqueueConfigs = (configs) => { // 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; + 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); };