From 1c577016b84dc075682737791343ab1b5aeaf7bd Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Fri, 3 Aug 2018 15:30:22 +0200 Subject: [PATCH] benchmark: improve assert benchmarks This reduces the runtime and makes sure the strict and loose options can be tested individually. Besides that a couple of redundant cases were removed. PR-URL: https://github.com/nodejs/node/pull/22211 Reviewed-By: Anatoli Papirovski Reviewed-By: Benjamin Gruenbaum Reviewed-By: Matteo Collina Reviewed-By: Trivikram Kamat Reviewed-By: James M Snell --- benchmark/assert/deepequal-buffer.js | 14 ++-- benchmark/assert/deepequal-map.js | 66 +++-------------- benchmark/assert/deepequal-object.js | 20 +++--- .../deepequal-prims-and-objs-big-array-set.js | 38 +++------- .../deepequal-prims-and-objs-big-loop.js | 16 ++--- benchmark/assert/deepequal-set.js | 70 +++---------------- benchmark/assert/deepequal-typedarrays.js | 20 +++--- benchmark/assert/ok.js | 2 +- benchmark/assert/throws.js | 10 +-- test/parallel/test-benchmark-assert.js | 1 + 10 files changed, 68 insertions(+), 189 deletions(-) diff --git a/benchmark/assert/deepequal-buffer.js b/benchmark/assert/deepequal-buffer.js index fe3f6f9754c3a0..baf3e1766c15f5 100644 --- a/benchmark/assert/deepequal-buffer.js +++ b/benchmark/assert/deepequal-buffer.js @@ -3,17 +3,16 @@ const common = require('../common.js'); const assert = require('assert'); const bench = common.createBenchmark(main, { - n: [1e5], - len: [1e2, 1e4], + n: [2e4], + len: [1e2, 1e3], + strict: [0, 1], method: [ 'deepEqual', - 'deepStrictEqual', - 'notDeepEqual', - 'notDeepStrictEqual' + 'notDeepEqual' ] }); -function main({ len, n, method }) { +function main({ len, n, method, strict }) { if (!method) method = 'deepEqual'; const data = Buffer.allocUnsafe(len + 1); @@ -24,6 +23,9 @@ function main({ len, n, method }) { data.copy(expected); data.copy(expectedWrong); + if (strict) { + method = method.replace('eep', 'eepStrict'); + } const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; diff --git a/benchmark/assert/deepequal-map.js b/benchmark/assert/deepequal-map.js index c6c7173fe8ed6d..c15e1c9a360c3b 100644 --- a/benchmark/assert/deepequal-map.js +++ b/benchmark/assert/deepequal-map.js @@ -7,21 +7,14 @@ const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } = const bench = common.createBenchmark(main, { n: [5e2], len: [5e2], + strict: [0, 1], method: [ 'deepEqual_primitiveOnly', - 'deepStrictEqual_primitiveOnly', 'deepEqual_objectOnly', - 'deepStrictEqual_objectOnly', 'deepEqual_mixed', - 'deepStrictEqual_mixed', - 'deepEqual_looseMatches', 'notDeepEqual_primitiveOnly', - 'notDeepStrictEqual_primitiveOnly', 'notDeepEqual_objectOnly', - 'notDeepStrictEqual_objectOnly', - 'notDeepEqual_mixed', - 'notDeepStrictEqual_mixed', - 'notDeepEqual_looseMatches', + 'notDeepEqual_mixed' ] }); @@ -37,7 +30,7 @@ function benchmark(method, n, values, values2) { bench.end(n); } -function main({ n, len, method }) { +function main({ n, len, method, strict }) { const array = Array(len).fill(1); var values, values2; @@ -46,74 +39,33 @@ function main({ n, len, method }) { // Empty string falls through to next line as default, mostly for tests. case 'deepEqual_primitiveOnly': values = array.map((_, i) => [`str_${i}`, 123]); - benchmark(deepEqual, n, values); - break; - case 'deepStrictEqual_primitiveOnly': - values = array.map((_, i) => [`str_${i}`, 123]); - benchmark(deepStrictEqual, n, values); + benchmark(strict ? deepStrictEqual : deepEqual, n, values); break; case 'deepEqual_objectOnly': values = array.map((_, i) => [[`str_${i}`, 1], 123]); - benchmark(deepEqual, n, values); - break; - case 'deepStrictEqual_objectOnly': - values = array.map((_, i) => [[`str_${i}`, 1], 123]); - benchmark(deepStrictEqual, n, values); + benchmark(strict ? deepStrictEqual : deepEqual, n, values); break; case 'deepEqual_mixed': values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); - benchmark(deepEqual, n, values); - break; - case 'deepStrictEqual_mixed': - values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); - benchmark(deepStrictEqual, n, values); - break; - case 'deepEqual_looseMatches': - values = array.map((_, i) => [i, i]); - values2 = values.slice().map((v) => [String(v[0]), String(v[1])]); - benchmark(deepEqual, n, values, values2); + benchmark(strict ? deepStrictEqual : deepEqual, n, values); break; case 'notDeepEqual_primitiveOnly': values = array.map((_, i) => [`str_${i}`, 123]); values2 = values.slice(0); values2[Math.floor(len / 2)] = ['w00t', 123]; - benchmark(notDeepEqual, n, values, values2); - break; - case 'notDeepStrictEqual_primitiveOnly': - values = array.map((_, i) => [`str_${i}`, 123]); - values2 = values.slice(0); - values2[Math.floor(len / 2)] = ['w00t', 123]; - benchmark(notDeepStrictEqual, n, values, values2); + benchmark(strict ? notDeepStrictEqual : notDeepEqual, n, values, values2); break; case 'notDeepEqual_objectOnly': values = array.map((_, i) => [[`str_${i}`, 1], 123]); values2 = values.slice(0); values2[Math.floor(len / 2)] = [['w00t'], 123]; - benchmark(notDeepEqual, n, values, values2); - break; - case 'notDeepStrictEqual_objectOnly': - values = array.map((_, i) => [[`str_${i}`, 1], 123]); - values2 = values.slice(0); - values2[Math.floor(len / 2)] = [['w00t'], 123]; - benchmark(notDeepStrictEqual, n, values, values2); + benchmark(strict ? notDeepStrictEqual : notDeepEqual, n, values, values2); break; case 'notDeepEqual_mixed': values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); values2 = values.slice(0); values2[0] = ['w00t', 123]; - benchmark(notDeepEqual, n, values, values2); - break; - case 'notDeepStrictEqual_mixed': - values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); - values2 = values.slice(0); - values2[0] = ['w00t', 123]; - benchmark(notDeepStrictEqual, n, values, values2); - break; - case 'notDeepEqual_looseMatches': - values = array.map((_, i) => [i, i]); - values2 = values.slice().map((v) => [String(v[0]), String(v[1])]); - values2[len - 1] = [String(len + 1), String(len + 1)]; - benchmark(notDeepEqual, n, values, values2); + benchmark(strict ? notDeepStrictEqual : notDeepEqual, n, values, values2); break; default: throw new Error(`Unsupported method ${method}`); diff --git a/benchmark/assert/deepequal-object.js b/benchmark/assert/deepequal-object.js index 124943b19ec761..1a9c826a00d4c1 100644 --- a/benchmark/assert/deepequal-object.js +++ b/benchmark/assert/deepequal-object.js @@ -4,13 +4,12 @@ const common = require('../common.js'); const assert = require('assert'); const bench = common.createBenchmark(main, { - n: [1e6], - size: [1e2, 1e3, 1e4], + n: [5e3], + size: [1e2, 1e3, 5e4], + strict: [0, 1], method: [ 'deepEqual', - 'deepStrictEqual', - 'notDeepEqual', - 'notDeepStrictEqual' + 'notDeepEqual' ] }); @@ -20,14 +19,16 @@ function createObj(source, add = '') { nope: { bar: `123${add}`, a: [1, 2, 3], - baz: n + baz: n, + c: {}, + b: [] } })); } -function main({ size, n, method }) { +function main({ size, n, method, strict }) { // TODO: Fix this "hack". `n` should not be manipulated. - n = n / size; + n = Math.min(Math.ceil(n / size), 20); if (!method) method = 'deepEqual'; @@ -37,6 +38,9 @@ function main({ size, n, method }) { const expected = createObj(source); const expectedWrong = createObj(source, '4'); + if (strict) { + method = method.replace('eep', 'eepStrict'); + } const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; diff --git a/benchmark/assert/deepequal-prims-and-objs-big-array-set.js b/benchmark/assert/deepequal-prims-and-objs-big-array-set.js index 4578e5a250f392..71637c28cea999 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-array-set.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-array-set.js @@ -5,29 +5,22 @@ const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } = require('assert'); const primValues = { - 'null': null, - 'undefined': undefined, 'string': 'a', 'number': 1, - 'boolean': true, 'object': { 0: 'a' }, - 'array': [1, 2, 3], - 'new-array': new Array([1, 2, 3]) + 'array': [1, 2, 3] }; const bench = common.createBenchmark(main, { primitive: Object.keys(primValues), n: [25], - len: [1e5], + len: [2e4], + strict: [0, 1], method: [ 'deepEqual_Array', - 'deepStrictEqual_Array', 'notDeepEqual_Array', - 'notDeepStrictEqual_Array', 'deepEqual_Set', - 'deepStrictEqual_Set', - 'notDeepEqual_Set', - 'notDeepStrictEqual_Set' + 'notDeepEqual_Set' ] }); @@ -39,7 +32,7 @@ function run(fn, n, actual, expected) { bench.end(n); } -function main({ n, len, primitive, method }) { +function main({ n, len, primitive, method, strict }) { const prim = primValues[primitive]; const actual = []; const expected = []; @@ -62,28 +55,17 @@ function main({ n, len, primitive, method }) { // Empty string falls through to next line as default, mostly for tests. case '': case 'deepEqual_Array': - run(deepEqual, n, actual, expected); - break; - case 'deepStrictEqual_Array': - run(deepStrictEqual, n, actual, expected); + run(strict ? deepStrictEqual : deepEqual, n, actual, expected); break; case 'notDeepEqual_Array': - run(notDeepEqual, n, actual, expectedWrong); - break; - case 'notDeepStrictEqual_Array': - run(notDeepStrictEqual, n, actual, expectedWrong); + run(strict ? notDeepStrictEqual : notDeepEqual, n, actual, expectedWrong); break; case 'deepEqual_Set': - run(deepEqual, n, actualSet, expectedSet); - break; - case 'deepStrictEqual_Set': - run(deepStrictEqual, n, actualSet, expectedSet); + run(strict ? deepStrictEqual : deepEqual, n, actualSet, expectedSet); break; case 'notDeepEqual_Set': - run(notDeepEqual, n, actualSet, expectedWrongSet); - break; - case 'notDeepStrictEqual_Set': - run(notDeepStrictEqual, n, actualSet, expectedWrongSet); + run(strict ? notDeepStrictEqual : notDeepEqual, + n, actualSet, expectedWrongSet); break; default: throw new Error(`Unsupported method "${method}"`); diff --git a/benchmark/assert/deepequal-prims-and-objs-big-loop.js b/benchmark/assert/deepequal-prims-and-objs-big-loop.js index f1183dab32a3fb..13abaf107fdfb9 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-loop.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-loop.js @@ -3,28 +3,23 @@ const common = require('../common.js'); const assert = require('assert'); const primValues = { - 'null': null, - 'undefined': undefined, 'string': 'a', 'number': 1, - 'boolean': true, 'object': { 0: 'a' }, - 'array': [1, 2, 3], - 'new-array': new Array([1, 2, 3]) + 'array': [1, 2, 3] }; const bench = common.createBenchmark(main, { primitive: Object.keys(primValues), - n: [1e6], + n: [2e4], + strict: [0, 1], method: [ 'deepEqual', - 'deepStrictEqual', 'notDeepEqual', - 'notDeepStrictEqual' ] }); -function main({ n, primitive, method }) { +function main({ n, primitive, method, strict }) { if (!method) method = 'deepEqual'; const prim = primValues[primitive]; @@ -32,6 +27,9 @@ function main({ n, primitive, method }) { const expected = prim; const expectedWrong = 'b'; + if (strict) { + method = method.replace('eep', 'eepStrict'); + } const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; diff --git a/benchmark/assert/deepequal-set.js b/benchmark/assert/deepequal-set.js index 6769e5e37fafb7..1f4061afb2a300 100644 --- a/benchmark/assert/deepequal-set.js +++ b/benchmark/assert/deepequal-set.js @@ -7,21 +7,14 @@ const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } = const bench = common.createBenchmark(main, { n: [5e2], len: [5e2], + strict: [0, 1], method: [ 'deepEqual_primitiveOnly', - 'deepStrictEqual_primitiveOnly', 'deepEqual_objectOnly', - 'deepStrictEqual_objectOnly', 'deepEqual_mixed', - 'deepStrictEqual_mixed', - 'deepEqual_looseMatches', 'notDeepEqual_primitiveOnly', - 'notDeepStrictEqual_primitiveOnly', 'notDeepEqual_objectOnly', - 'notDeepStrictEqual_objectOnly', - 'notDeepEqual_mixed', - 'notDeepStrictEqual_mixed', - 'notDeepEqual_looseMatches', + 'notDeepEqual_mixed' ] }); @@ -37,7 +30,7 @@ function benchmark(method, n, values, values2) { bench.end(n); } -function main({ n, len, method }) { +function main({ n, len, method, strict }) { const array = Array(len).fill(1); var values, values2; @@ -47,60 +40,29 @@ function main({ n, len, method }) { // Empty string falls through to next line as default, mostly for tests. case 'deepEqual_primitiveOnly': values = array.map((_, i) => `str_${i}`); - benchmark(deepEqual, n, values); - break; - case 'deepStrictEqual_primitiveOnly': - values = array.map((_, i) => `str_${i}`); - benchmark(deepStrictEqual, n, values); + benchmark(strict ? deepStrictEqual : deepEqual, n, values); break; case 'deepEqual_objectOnly': values = array.map((_, i) => [`str_${i}`, null]); - benchmark(deepEqual, n, values); - break; - case 'deepStrictEqual_objectOnly': - values = array.map((_, i) => [`str_${i}`, null]); - benchmark(deepStrictEqual, n, values); + benchmark(strict ? deepStrictEqual : deepEqual, n, values); break; case 'deepEqual_mixed': values = array.map((_, i) => { return i % 2 ? [`str_${i}`, null] : `str_${i}`; }); - benchmark(deepEqual, n, values); - break; - case 'deepStrictEqual_mixed': - values = array.map((_, i) => { - return i % 2 ? [`str_${i}`, null] : `str_${i}`; - }); - benchmark(deepStrictEqual, n, values); - break; - case 'deepEqual_looseMatches': - values = array.map((_, i) => i); - values2 = values.slice().map((v) => String(v)); - benchmark(deepEqual, n, values, values2); + benchmark(strict ? deepStrictEqual : deepEqual, n, values); break; case 'notDeepEqual_primitiveOnly': values = array.map((_, i) => `str_${i}`); values2 = values.slice(0); values2[Math.floor(len / 2)] = 'w00t'; - benchmark(notDeepEqual, n, values, values2); - break; - case 'notDeepStrictEqual_primitiveOnly': - values = array.map((_, i) => `str_${i}`); - values2 = values.slice(0); - values2[Math.floor(len / 2)] = 'w00t'; - benchmark(notDeepStrictEqual, n, values, values2); + benchmark(strict ? notDeepStrictEqual : notDeepEqual, n, values, values2); break; case 'notDeepEqual_objectOnly': values = array.map((_, i) => [`str_${i}`, null]); values2 = values.slice(0); values2[Math.floor(len / 2)] = ['w00t']; - benchmark(notDeepEqual, n, values, values2); - break; - case 'notDeepStrictEqual_objectOnly': - values = array.map((_, i) => [`str_${i}`, null]); - values2 = values.slice(0); - values2[Math.floor(len / 2)] = ['w00t']; - benchmark(notDeepStrictEqual, n, values, values2); + benchmark(strict ? notDeepStrictEqual : notDeepEqual, n, values, values2); break; case 'notDeepEqual_mixed': values = array.map((_, i) => { @@ -108,21 +70,7 @@ function main({ n, len, method }) { }); values2 = values.slice(); values2[0] = 'w00t'; - benchmark(notDeepEqual, n, values, values2); - break; - case 'notDeepStrictEqual_mixed': - values = array.map((_, i) => { - return i % 2 ? [`str_${i}`, null] : `str_${i}`; - }); - values2 = values.slice(); - values2[0] = 'w00t'; - benchmark(notDeepStrictEqual, n, values, values2); - break; - case 'notDeepEqual_looseMatches': - values = array.map((_, i) => i); - values2 = values.slice().map((v) => String(v)); - values2[len - 1] = String(len + 1); - benchmark(notDeepEqual, n, values, values2); + benchmark(strict ? notDeepStrictEqual : notDeepEqual, n, values, values2); break; default: throw new Error(`Unsupported method "${method}"`); diff --git a/benchmark/assert/deepequal-typedarrays.js b/benchmark/assert/deepequal-typedarrays.js index c4d8f434bf4e8a..9f9c68a6731254 100644 --- a/benchmark/assert/deepequal-typedarrays.js +++ b/benchmark/assert/deepequal-typedarrays.js @@ -6,39 +6,39 @@ const bench = common.createBenchmark(main, { type: [ 'Int8Array', 'Uint8Array', - 'Int16Array', - 'Uint16Array', - 'Int32Array', - 'Uint32Array', 'Float32Array', 'Float64Array', 'Uint8ClampedArray', ], - n: [1], + n: [5e2], + strict: [0, 1], method: [ 'deepEqual', - 'deepStrictEqual', 'notDeepEqual', - 'notDeepStrictEqual' ], - len: [1e6] + len: [1e2, 5e3] }); -function main({ type, n, len, method }) { +function main({ type, n, len, method, strict }) { if (!method) method = 'deepEqual'; const clazz = global[type]; const actual = new clazz(len); const expected = new clazz(len); - const expectedWrong = Buffer.alloc(len); + const expectedWrong = new clazz(len); const wrongIndex = Math.floor(len / 2); expectedWrong[wrongIndex] = 123; + if (strict) { + method = method.replace('eep', 'eepStrict'); + } const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; bench.start(); for (var i = 0; i < n; ++i) { + actual[0] = i; + value2[0] = i; fn(actual, value2); } bench.end(n); diff --git a/benchmark/assert/ok.js b/benchmark/assert/ok.js index 849be65539aef7..4869a9de69c319 100644 --- a/benchmark/assert/ok.js +++ b/benchmark/assert/ok.js @@ -4,7 +4,7 @@ const common = require('../common.js'); const assert = require('assert'); const bench = common.createBenchmark(main, { - n: [1e9] + n: [1e5] }); function main({ n }) { diff --git a/benchmark/assert/throws.js b/benchmark/assert/throws.js index a8a7bd4509e1ca..1788630cb2f992 100644 --- a/benchmark/assert/throws.js +++ b/benchmark/assert/throws.js @@ -4,10 +4,9 @@ const common = require('../common.js'); const { throws, doesNotThrow } = require('assert'); const bench = common.createBenchmark(main, { - n: [1e6], + n: [1e4], method: [ 'doesNotThrow', - 'throws', 'throws_TypeError', 'throws_RegExp' ] @@ -30,13 +29,6 @@ function main({ n, method }) { } bench.end(n); break; - case 'throws': - bench.start(); - for (i = 0; i < n; ++i) { - throws(throwError); - } - bench.end(n); - break; case 'throws_TypeError': bench.start(); for (i = 0; i < n; ++i) { diff --git a/test/parallel/test-benchmark-assert.js b/test/parallel/test-benchmark-assert.js index 3ca72df718cd64..8a8ba0244489e5 100644 --- a/test/parallel/test-benchmark-assert.js +++ b/test/parallel/test-benchmark-assert.js @@ -10,6 +10,7 @@ const runBenchmark = require('../common/benchmark'); runBenchmark( 'assert', [ + 'strict=1', 'len=1', 'method=', 'n=1',