mirror of
https://github.com/nodejs/node.git
synced 2025-05-02 22:31:35 +00:00
lib: improve performance of validateStringArray and validateBooleanArray
PR-URL: https://github.com/nodejs/node/pull/49756 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
parent
d370ed0cd8
commit
a58ffad656
61
benchmark/validators/parse-file-mode.js
Normal file
61
benchmark/validators/parse-file-mode.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e7],
|
||||||
|
value: [
|
||||||
|
"'777'",
|
||||||
|
'0o777',
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function getParseFactory() {
|
||||||
|
const {
|
||||||
|
parseFileMode,
|
||||||
|
} = require('internal/validators');
|
||||||
|
|
||||||
|
return (n) => parseFileMode(n, 'n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function main({ n, value }) {
|
||||||
|
const parse = getParseFactory();
|
||||||
|
|
||||||
|
value = value === "'777'" ? '777' : 0o777;
|
||||||
|
|
||||||
|
// Warm up.
|
||||||
|
const length = 1024;
|
||||||
|
const array = [];
|
||||||
|
let errCase = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
try {
|
||||||
|
array.push(parse(value));
|
||||||
|
} catch (e) {
|
||||||
|
errCase = true;
|
||||||
|
array.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const index = i % length;
|
||||||
|
try {
|
||||||
|
array[index] = parse(value);
|
||||||
|
} catch (e) {
|
||||||
|
array[index] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
// Verify the entries to prevent dead code elimination from making
|
||||||
|
// the benchmark invalid.
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
assert.strictEqual(typeof array[i], errCase ? 'object' : 'number');
|
||||||
|
}
|
||||||
|
}
|
68
benchmark/validators/validate-array.js
Normal file
68
benchmark/validators/validate-array.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e7],
|
||||||
|
value: [
|
||||||
|
'[]',
|
||||||
|
'[1,2,3]',
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function getValidateFactory() {
|
||||||
|
const {
|
||||||
|
validateArray,
|
||||||
|
} = require('internal/validators');
|
||||||
|
|
||||||
|
return (n) => validateArray(n, 'n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function main({ n, value }) {
|
||||||
|
const validate = getValidateFactory();
|
||||||
|
|
||||||
|
switch (value) {
|
||||||
|
case '[]':
|
||||||
|
value = [];
|
||||||
|
break;
|
||||||
|
case '[1,2,3]':
|
||||||
|
value = [1, 2, 3];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warm up.
|
||||||
|
const length = 1024;
|
||||||
|
const array = [];
|
||||||
|
let errCase = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
try {
|
||||||
|
array.push(validate(value));
|
||||||
|
} catch (e) {
|
||||||
|
errCase = true;
|
||||||
|
array.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const index = i % length;
|
||||||
|
try {
|
||||||
|
array[index] = validate(value);
|
||||||
|
} catch (e) {
|
||||||
|
array[index] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
// Verify the entries to prevent dead code elimination from making
|
||||||
|
// the benchmark invalid.
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
assert.strictEqual(typeof array[i], errCase ? 'object' : 'undefined');
|
||||||
|
}
|
||||||
|
}
|
55
benchmark/validators/validate-boolean.js
Normal file
55
benchmark/validators/validate-boolean.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e8],
|
||||||
|
code: [
|
||||||
|
'validateBoolean',
|
||||||
|
],
|
||||||
|
value: [
|
||||||
|
'true',
|
||||||
|
'false',
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function getValidateFactory(code) {
|
||||||
|
const {
|
||||||
|
validateBoolean,
|
||||||
|
} = require('internal/validators');
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case 'validateBoolean':
|
||||||
|
return (n) => validateBoolean(n, 'n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main({ n, code, value }) {
|
||||||
|
const validate = getValidateFactory(code);
|
||||||
|
const v = value === 'true';
|
||||||
|
|
||||||
|
// Warm up.
|
||||||
|
const length = 1024;
|
||||||
|
const array = [];
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
array.push(validate(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const index = i % length;
|
||||||
|
array[index] = validate(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
// Verify the entries to prevent dead code elimination from making
|
||||||
|
// the benchmark invalid.
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
assert.strictEqual(typeof array[i], 'undefined');
|
||||||
|
}
|
||||||
|
}
|
59
benchmark/validators/validate-encoding.js
Normal file
59
benchmark/validators/validate-encoding.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e8],
|
||||||
|
encoding: [
|
||||||
|
'ascii',
|
||||||
|
'utf8',
|
||||||
|
'utf-8',
|
||||||
|
'utf16le',
|
||||||
|
'ucs2',
|
||||||
|
'ucs-2',
|
||||||
|
'base64',
|
||||||
|
'latin1',
|
||||||
|
'binary',
|
||||||
|
'hex',
|
||||||
|
],
|
||||||
|
value: [
|
||||||
|
'test',
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function getValidateFactory(encoding) {
|
||||||
|
const {
|
||||||
|
validateEncoding,
|
||||||
|
} = require('internal/validators');
|
||||||
|
|
||||||
|
return (n) => validateEncoding(n, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
function main({ n, encoding, value }) {
|
||||||
|
const validate = getValidateFactory(encoding);
|
||||||
|
|
||||||
|
// Warm up.
|
||||||
|
const length = 1024;
|
||||||
|
const array = [];
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
array.push(validate(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const index = i % length;
|
||||||
|
array[index] = validate(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
// Verify the entries to prevent dead code elimination from making
|
||||||
|
// the benchmark invalid.
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
assert.strictEqual(typeof array[i], 'undefined');
|
||||||
|
}
|
||||||
|
}
|
69
benchmark/validators/validate-one-of.js
Normal file
69
benchmark/validators/validate-one-of.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e7],
|
||||||
|
code: [
|
||||||
|
'validateOneOf',
|
||||||
|
],
|
||||||
|
value: [
|
||||||
|
'fifo',
|
||||||
|
'lifo',
|
||||||
|
'lilo',
|
||||||
|
],
|
||||||
|
validLength: [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const validValues = [
|
||||||
|
'fifo',
|
||||||
|
'lifo',
|
||||||
|
'lilo',
|
||||||
|
'filo',
|
||||||
|
];
|
||||||
|
|
||||||
|
function getValidateFactory(code, validLength) {
|
||||||
|
const {
|
||||||
|
validateOneOf,
|
||||||
|
} = require('internal/validators');
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case 'validateOneOf':
|
||||||
|
return (n) => validateOneOf(n, 'n', validValues.slice(0, validLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main({ n, code, validLength }) {
|
||||||
|
const validate = getValidateFactory(code, validLength);
|
||||||
|
|
||||||
|
// Warm up.
|
||||||
|
const length = 1024;
|
||||||
|
const array = [];
|
||||||
|
|
||||||
|
const value = validValues[validLength - 1];
|
||||||
|
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
array.push(validate(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const index = i % length;
|
||||||
|
array[index] = validate(value);
|
||||||
|
}
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
|
||||||
|
// Verify the entries to prevent dead code elimination from making
|
||||||
|
// the benchmark invalid.
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
assert.strictEqual(typeof array[i], 'undefined');
|
||||||
|
}
|
||||||
|
}
|
66
benchmark/validators/validate-x-array.js
Normal file
66
benchmark/validators/validate-x-array.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e8],
|
||||||
|
type: [
|
||||||
|
'validateStringArray',
|
||||||
|
'validateBooleanArray',
|
||||||
|
],
|
||||||
|
arrayLength: [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
10,
|
||||||
|
100,
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function getValidateFactory(type, arrayLength) {
|
||||||
|
const {
|
||||||
|
validateBooleanArray,
|
||||||
|
validateStringArray,
|
||||||
|
} = require('internal/validators');
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'validateBooleanArray':
|
||||||
|
return [
|
||||||
|
(n) => validateBooleanArray(n, 'n'),
|
||||||
|
Array.from({ length: arrayLength }, (v, i) => ((i & 1) === 0)),
|
||||||
|
];
|
||||||
|
case 'validateStringArray':
|
||||||
|
return [
|
||||||
|
(n) => validateStringArray(n, 'n'),
|
||||||
|
Array.from({ length: arrayLength }, (v, i) => `foo${i}`),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main({ n, type, arrayLength }) {
|
||||||
|
const [validate, value] = getValidateFactory(type, arrayLength);
|
||||||
|
|
||||||
|
// Warm up.
|
||||||
|
const length = 1024;
|
||||||
|
const array = [];
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
array.push(validate(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const index = i % length;
|
||||||
|
array[index] = validate(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
// Verify the entries to prevent dead code elimination from making
|
||||||
|
// the benchmark invalid.
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
assert.strictEqual(typeof array[i], 'undefined');
|
||||||
|
}
|
||||||
|
}
|
@ -311,8 +311,12 @@ const validateArray = hideStackFrames((value, name, minLength = 0) => {
|
|||||||
/** @type {validateStringArray} */
|
/** @type {validateStringArray} */
|
||||||
function validateStringArray(value, name) {
|
function validateStringArray(value, name) {
|
||||||
validateArray(value, name);
|
validateArray(value, name);
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; ++i) {
|
||||||
validateString(value[i], `${name}[${i}]`);
|
// Don't use validateString here for performance reasons, as
|
||||||
|
// we would generate intermediate strings for the name.
|
||||||
|
if (typeof value[i] !== 'string') {
|
||||||
|
throw new ERR_INVALID_ARG_TYPE(`${name}[${i}]`, 'string', value[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,8 +330,12 @@ function validateStringArray(value, name) {
|
|||||||
/** @type {validateBooleanArray} */
|
/** @type {validateBooleanArray} */
|
||||||
function validateBooleanArray(value, name) {
|
function validateBooleanArray(value, name) {
|
||||||
validateArray(value, name);
|
validateArray(value, name);
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; ++i) {
|
||||||
validateBoolean(value[i], `${name}[${i}]`);
|
// Don't use validateBoolean here for performance reasons, as
|
||||||
|
// we would generate intermediate strings for the name.
|
||||||
|
if (value[i] !== true && value[i] !== false) {
|
||||||
|
throw new ERR_INVALID_ARG_TYPE(`${name}[${i}]`, 'boolean', value[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ require('../common');
|
|||||||
|
|
||||||
// Minimal test for assert benchmarks. This makes sure the benchmarks aren't
|
// Minimal test for assert benchmarks. This makes sure the benchmarks aren't
|
||||||
// completely broken but nothing more than that.
|
// completely broken but nothing more than that.
|
||||||
|
|
||||||
const runBenchmark = require('../common/benchmark');
|
const runBenchmark = require('../common/benchmark');
|
||||||
|
|
||||||
runBenchmark('validators');
|
runBenchmark('validators');
|
||||||
|
Loading…
Reference in New Issue
Block a user