mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
benchmark: rework assert benchmarks for correctness
This reworks most assert benchmarks to provide more reliable test cases that also test more cases than before while keeping the runtime low. Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de> PR-URL: https://github.com/nodejs/node/pull/46593 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
committed by
Antoine du Hamel
parent
1d5058d4bb
commit
841279d79c
@@ -6,27 +6,47 @@ const bench = common.createBenchmark(main, {
|
||||
n: [2e4],
|
||||
len: [1e2, 1e3],
|
||||
strict: [0, 1],
|
||||
method: ['deepEqual', 'notDeepEqual'],
|
||||
arrayBuffer: [0, 1],
|
||||
method: ['deepEqual', 'notDeepEqual', 'unequal_length'],
|
||||
}, {
|
||||
combinationFilter: (p) => {
|
||||
return p.strict === 1 || p.method === 'deepEqual';
|
||||
},
|
||||
});
|
||||
|
||||
function main({ len, n, method, strict }) {
|
||||
const data = Buffer.allocUnsafe(len + 1);
|
||||
const actual = Buffer.alloc(len);
|
||||
const expected = Buffer.alloc(len);
|
||||
const expectedWrong = Buffer.alloc(len + 1);
|
||||
data.copy(actual);
|
||||
data.copy(expected);
|
||||
data.copy(expectedWrong);
|
||||
function main({ len, n, method, strict, arrayBuffer }) {
|
||||
let actual = Buffer.alloc(len);
|
||||
let expected = Buffer.alloc(len + Number(method === 'unequal_length'));
|
||||
|
||||
|
||||
if (method === 'unequal_length') {
|
||||
method = 'notDeepEqual';
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
actual.writeInt8(i % 128, i);
|
||||
expected.writeInt8(i % 128, i);
|
||||
}
|
||||
|
||||
if (method.includes('not')) {
|
||||
const position = Math.floor(len / 2);
|
||||
expected[position] = expected[position] + 1;
|
||||
}
|
||||
|
||||
if (strict) {
|
||||
method = method.replace('eep', 'eepStrict');
|
||||
}
|
||||
|
||||
const fn = assert[method];
|
||||
const value2 = method.includes('not') ? expectedWrong : expected;
|
||||
|
||||
if (arrayBuffer) {
|
||||
actual = actual.buffer;
|
||||
expected = expected.buffer;
|
||||
}
|
||||
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
fn(actual, value2);
|
||||
fn(actual, expected);
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
||||
|
||||
@@ -4,14 +4,20 @@ const common = require('../common.js');
|
||||
const assert = require('assert');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
n: [5e3],
|
||||
size: [1e2, 1e3, 5e4],
|
||||
strict: [0, 1],
|
||||
n: [25, 2e2, 2e3],
|
||||
size: [1e2, 1e3, 1e4],
|
||||
strict: [1],
|
||||
method: ['deepEqual', 'notDeepEqual'],
|
||||
}, {
|
||||
combinationFilter: (p) => {
|
||||
return p.size === 1e4 && p.n === 25 ||
|
||||
p.size === 1e3 && p.n === 2e2 ||
|
||||
p.size === 1e2 && p.n === 2e3;
|
||||
},
|
||||
});
|
||||
|
||||
function createObj(source, add = '') {
|
||||
return source.map((n) => ({
|
||||
function createObj(size, add = '') {
|
||||
return Array.from({ length: size }, (n) => ({
|
||||
foo: 'yarp',
|
||||
nope: {
|
||||
bar: `123${add}`,
|
||||
@@ -24,22 +30,17 @@ function createObj(source, add = '') {
|
||||
}
|
||||
|
||||
function main({ size, n, method, strict }) {
|
||||
const len = Math.min(Math.ceil(n / size), 20);
|
||||
|
||||
const source = Array.apply(null, Array(size));
|
||||
const actual = createObj(source);
|
||||
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;
|
||||
|
||||
const actual = createObj(size);
|
||||
const expected = method.includes('not') ? createObj(size, '4') : createObj(size);
|
||||
|
||||
bench.start();
|
||||
for (let i = 0; i < len; ++i) {
|
||||
fn(actual, value2);
|
||||
for (let i = 0; i < n; ++i) {
|
||||
fn(actual, expected);
|
||||
}
|
||||
bench.end(len);
|
||||
bench.end(n);
|
||||
}
|
||||
|
||||
@@ -2,35 +2,77 @@
|
||||
const common = require('../common.js');
|
||||
const assert = require('assert');
|
||||
|
||||
const circular = {};
|
||||
circular.circular = circular;
|
||||
const circular2 = {};
|
||||
circular2.circular = circular2;
|
||||
const notCircular = {};
|
||||
notCircular.circular = {};
|
||||
|
||||
const primValues = {
|
||||
'string': 'a',
|
||||
'number': 1,
|
||||
'object': { 0: 'a' },
|
||||
'string': 'abcdef',
|
||||
'number': 1_000,
|
||||
'boolean': true,
|
||||
'object': { property: 'abcdef' },
|
||||
'object_other_property': { property: 'abcdef' },
|
||||
'array': [1, 2, 3],
|
||||
'set_object': new Set([[1]]),
|
||||
'set_simple': new Set([1, 2, 3]),
|
||||
'circular': circular,
|
||||
'empty_object': {},
|
||||
'regexp': /abc/i,
|
||||
'date': new Date(),
|
||||
};
|
||||
|
||||
const primValues2 = {
|
||||
'object': { property: 'abcdef' },
|
||||
'array': [1, 2, 3],
|
||||
'set_object': new Set([[1]]),
|
||||
'set_simple': new Set([1, 3, 2]),
|
||||
'circular': circular2,
|
||||
'empty_object': {},
|
||||
'regexp': /abc/i,
|
||||
'date': new Date(primValues.date),
|
||||
};
|
||||
|
||||
const primValuesUnequal = {
|
||||
'string': 'abcdez',
|
||||
'number': 1_001,
|
||||
'boolean': false,
|
||||
'object': { property2: 'abcdef' },
|
||||
'array': [1, 3, 2],
|
||||
'set_object': new Set([[2]]),
|
||||
'set_simple': new Set([1, 4, 2]),
|
||||
'circular': notCircular,
|
||||
'empty_object': [],
|
||||
'regexp': /abc/g,
|
||||
'date': new Date(primValues.date.getTime() + 1),
|
||||
};
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
primitive: Object.keys(primValues),
|
||||
n: [2e4],
|
||||
n: [1e5],
|
||||
strict: [0, 1],
|
||||
method: ['deepEqual', 'notDeepEqual'],
|
||||
}, {
|
||||
combinationFilter: (p) => {
|
||||
return p.strict === 1 || p.method === 'deepEqual';
|
||||
},
|
||||
});
|
||||
|
||||
function main({ n, primitive, method, strict }) {
|
||||
const prim = primValues[primitive];
|
||||
const actual = prim;
|
||||
const expected = prim;
|
||||
const expectedWrong = 'b';
|
||||
const actual = primValues2[primitive] ?? prim;
|
||||
const expected = method.includes('not') ? primValuesUnequal[primitive] : prim;
|
||||
|
||||
if (strict) {
|
||||
method = method.replace('eep', 'eepStrict');
|
||||
}
|
||||
const fn = assert[method];
|
||||
const value2 = method.includes('not') ? expectedWrong : expected;
|
||||
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
fn([actual], [value2]);
|
||||
fn(actual, expected);
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
||||
|
||||
@@ -4,18 +4,10 @@ const common = require('../common.js');
|
||||
const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } =
|
||||
require('assert');
|
||||
|
||||
const primValues = {
|
||||
'string': 'a',
|
||||
'number': 1,
|
||||
'object': { 0: 'a' },
|
||||
'array': [1, 2, 3],
|
||||
};
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
primitive: Object.keys(primValues),
|
||||
n: [25],
|
||||
len: [2e4],
|
||||
strict: [0, 1],
|
||||
n: [5e2],
|
||||
len: [1e4],
|
||||
strict: [1],
|
||||
method: [
|
||||
'deepEqual_Array',
|
||||
'notDeepEqual_Array',
|
||||
@@ -32,38 +24,32 @@ function run(fn, n, actual, expected) {
|
||||
bench.end(n);
|
||||
}
|
||||
|
||||
function main({ n, len, primitive, method, strict }) {
|
||||
const prim = primValues[primitive];
|
||||
function main({ n, len, method, strict }) {
|
||||
const actual = [];
|
||||
const expected = [];
|
||||
const expectedWrong = [];
|
||||
|
||||
for (let x = 0; x < len; x++) {
|
||||
actual.push(prim);
|
||||
expected.push(prim);
|
||||
expectedWrong.push(prim);
|
||||
for (let i = 0; i < len; i++) {
|
||||
actual.push(i);
|
||||
expected.push(i);
|
||||
}
|
||||
if (method.includes('not')) {
|
||||
expected[len - 1] += 1;
|
||||
}
|
||||
expectedWrong.pop();
|
||||
expectedWrong.push('b');
|
||||
|
||||
// Note: primitives are only added once to a set
|
||||
const actualSet = new Set(actual);
|
||||
const expectedSet = new Set(expected);
|
||||
const expectedWrongSet = new Set(expectedWrong);
|
||||
|
||||
switch (method) {
|
||||
case 'deepEqual_Array':
|
||||
run(strict ? deepStrictEqual : deepEqual, n, actual, expected);
|
||||
break;
|
||||
case 'notDeepEqual_Array':
|
||||
run(strict ? notDeepStrictEqual : notDeepEqual, n, actual, expectedWrong);
|
||||
run(strict ? notDeepStrictEqual : notDeepEqual, n, actual, expected);
|
||||
break;
|
||||
case 'deepEqual_Set':
|
||||
run(strict ? deepStrictEqual : deepEqual, n, actualSet, expectedSet);
|
||||
run(strict ? deepStrictEqual : deepEqual,
|
||||
n, new Set(actual), new Set(expected));
|
||||
break;
|
||||
case 'notDeepEqual_Set':
|
||||
run(strict ? notDeepStrictEqual : notDeepEqual,
|
||||
n, actualSet, expectedWrongSet);
|
||||
n, new Set(actual), new Set(expected));
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported method "${method}"`);
|
||||
@@ -7,8 +7,7 @@ const bench = common.createBenchmark(main, {
|
||||
'Int8Array',
|
||||
'Uint8Array',
|
||||
'Float32Array',
|
||||
'Float64Array',
|
||||
'Uint8ClampedArray',
|
||||
'Uint32Array',
|
||||
],
|
||||
n: [5e2],
|
||||
strict: [0, 1],
|
||||
@@ -23,21 +22,24 @@ function main({ type, n, len, method, strict }) {
|
||||
const clazz = global[type];
|
||||
const actual = new clazz(len);
|
||||
const expected = new clazz(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;
|
||||
|
||||
if (method.includes('not')) {
|
||||
expected[Math.floor(len / 2)] = 123;
|
||||
}
|
||||
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
actual[0] = i;
|
||||
value2[0] = i;
|
||||
fn(actual, value2);
|
||||
expected[0] = i;
|
||||
const pos = Math.ceil(len / 2) + 1;
|
||||
actual[pos] = i;
|
||||
expected[pos] = i;
|
||||
fn(actual, expected);
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
const assert = require('assert');
|
||||
|
||||
const bench = common.createBenchmark(main, { n: [1e5] });
|
||||
|
||||
function main({ n }) {
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
if (i % 2 === 0)
|
||||
assert(true);
|
||||
else
|
||||
assert(true, 'foo bar baz');
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
const { throws, doesNotThrow } = require('assert');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
n: [1e4],
|
||||
method: [ 'doesNotThrow', 'throws_TypeError', 'throws_RegExp' ],
|
||||
});
|
||||
|
||||
function main({ n, method }) {
|
||||
const throwError = () => { throw new TypeError('foobar'); };
|
||||
const doNotThrowError = () => { return 'foobar'; };
|
||||
const regExp = /foobar/;
|
||||
const message = 'failure';
|
||||
|
||||
switch (method) {
|
||||
case 'doesNotThrow':
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
doesNotThrow(doNotThrowError);
|
||||
}
|
||||
bench.end(n);
|
||||
break;
|
||||
case 'throws_TypeError':
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
throws(throwError, TypeError, message);
|
||||
}
|
||||
bench.end(n);
|
||||
break;
|
||||
case 'throws_RegExp':
|
||||
bench.start();
|
||||
for (let i = 0; i < n; ++i) {
|
||||
throws(throwError, regExp, message);
|
||||
}
|
||||
bench.end(n);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported method ${method}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user