assert: improve myers diff performance

fix: https://github.com/nodejs/node/issues/57242
PR-URL: https://github.com/nodejs/node/pull/57279
Fixes: https://github.com/nodejs/node/issues/57242
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: LiviaMedeiros <livia@cirno.name>
This commit is contained in:
Giovanni Bucci 2025-03-06 12:59:53 +01:00 committed by GitHub
parent 2a6f90813f
commit 395439be8b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 13 deletions

View file

@ -0,0 +1,38 @@
'use strict';
const common = require('../common.js');
const assert = require('assert');
const bench = common.createBenchmark(main, {
n: [10, 50, 200, 500],
size: [10, 100],
datasetName: ['objects'],
});
const baseObject = {
a: 1,
b: {
c: 2,
d: [3, 4, 5],
e: 'fghi',
j: {
k: 6,
},
},
};
function createObjects(size) {
return Array.from({ length: size }, () => baseObject);
}
function main({ n, size }) {
bench.start();
for (let i = 0; i < n; ++i) {
new assert.AssertionError({
actual: {},
expected: createObjects(size),
operator: 'partialDeepStrictEqual',
stackStartFunction: () => {},
});
}
bench.end(n);
}

View file

@ -2,7 +2,6 @@
const {
ArrayPrototypePush,
ArrayPrototypeSlice,
Int32Array,
StringPrototypeEndsWith,
} = primordials;
@ -16,7 +15,7 @@ function areLinesEqual(actual, expected, checkCommaDisparity) {
return true;
}
if (checkCommaDisparity) {
return `${actual},` === expected || actual === `${expected},`;
return (actual + ',') === expected || actual === (expected + ',');
}
return false;
}
@ -26,12 +25,10 @@ function myersDiff(actual, expected, checkCommaDisparity = false) {
const expectedLength = expected.length;
const max = actualLength + expectedLength;
const v = new Int32Array(2 * max + 1);
const trace = [];
for (let diffLevel = 0; diffLevel <= max; diffLevel++) {
const newTrace = ArrayPrototypeSlice(v);
ArrayPrototypePush(trace, newTrace);
ArrayPrototypePush(trace, new Int32Array(v)); // Clone the current state of `v`
for (let diagonalIndex = -diffLevel; diagonalIndex <= diffLevel; diagonalIndex += 2) {
const offset = diagonalIndex + max;
@ -89,10 +86,7 @@ function backtrack(trace, actual, expected, checkCommaDisparity) {
while (x > prevX && y > prevY) {
const actualItem = actual[x - 1];
const value =
!checkCommaDisparity || StringPrototypeEndsWith(actualItem, ',') ?
actualItem :
expected[y - 1];
const value = checkCommaDisparity && !StringPrototypeEndsWith(actualItem, ',') ? expected[y - 1] : actualItem;
ArrayPrototypePush(result, { __proto__: null, type: 'nop', value });
x--;
y--;
@ -100,11 +94,9 @@ function backtrack(trace, actual, expected, checkCommaDisparity) {
if (diffLevel > 0) {
if (x > prevX) {
ArrayPrototypePush(result, { __proto__: null, type: 'insert', value: actual[x - 1] });
x--;
ArrayPrototypePush(result, { __proto__: null, type: 'insert', value: actual[--x] });
} else {
ArrayPrototypePush(result, { __proto__: null, type: 'delete', value: expected[y - 1] });
y--;
ArrayPrototypePush(result, { __proto__: null, type: 'delete', value: expected[--y] });
}
}
}