mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
assert,util: improve performance
This improves the performance for array comparison by making the sparse array detection simpler. On top of that it adds a fast path for sets and maps that only contain objects as key. PR-URL: https://github.com/nodejs/node/pull/57370 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
This commit is contained in:
committed by
Node.js GitHub Bot
parent
77607d5306
commit
64f56e4156
@@ -559,6 +559,35 @@ function partialObjectSetEquiv(a, b, mode, set, memo) {
|
||||
}
|
||||
}
|
||||
|
||||
function setObjectEquiv(a, b, mode, set, memo) {
|
||||
if (mode === kPartial) {
|
||||
return partialObjectSetEquiv(a, b, mode, set, memo);
|
||||
}
|
||||
// Fast path for objects only
|
||||
if (mode === kStrict && set.size === a.size) {
|
||||
for (const val of a) {
|
||||
if (!setHasEqualElement(set, val, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const val of a) {
|
||||
// Primitive values have already been handled above.
|
||||
if (typeof val === 'object') {
|
||||
if (!b.has(val) && !setHasEqualElement(set, val, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
} else if (mode === kLoose &&
|
||||
!b.has(val) &&
|
||||
!setHasEqualElement(set, val, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return set.size === 0;
|
||||
}
|
||||
|
||||
function setEquiv(a, b, mode, memo) {
|
||||
// This is a lazily initiated Set of entries which have to be compared
|
||||
// pairwise.
|
||||
@@ -584,22 +613,7 @@ function setEquiv(a, b, mode, memo) {
|
||||
}
|
||||
|
||||
if (set !== null) {
|
||||
if (mode === kPartial) {
|
||||
return partialObjectSetEquiv(a, b, mode, set, memo);
|
||||
}
|
||||
for (const val of a) {
|
||||
// Primitive values have already been handled above.
|
||||
if (typeof val === 'object' && val !== null) {
|
||||
if (!b.has(val) && !setHasEqualElement(set, val, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
} else if (mode === kLoose &&
|
||||
!b.has(val) &&
|
||||
!setHasEqualElement(set, val, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return set.size === 0;
|
||||
return setObjectEquiv(a, b, mode, set, memo);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -640,6 +654,35 @@ function partialObjectMapEquiv(a, b, mode, set, memo) {
|
||||
}
|
||||
}
|
||||
|
||||
function mapObjectEquivalence(a, b, mode, set, memo) {
|
||||
if (mode === kPartial) {
|
||||
return partialObjectMapEquiv(a, b, mode, set, memo);
|
||||
}
|
||||
// Fast path for objects only
|
||||
if (mode === kStrict && set.size === a.size) {
|
||||
for (const { 0: key1, 1: item1 } of a) {
|
||||
if (!mapHasEqualEntry(set, b, key1, item1, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (const { 0: key1, 1: item1 } of a) {
|
||||
if (typeof key1 === 'object' && key1 !== null) {
|
||||
if (!mapHasEqualEntry(set, b, key1, item1, mode, memo))
|
||||
return false;
|
||||
} else if (set.size === 0) {
|
||||
return true;
|
||||
} else if (mode === kLoose &&
|
||||
(!b.has(key1) ||
|
||||
!innerDeepEqual(item1, b.get(key1), mode, memo)) &&
|
||||
!mapHasEqualEntry(set, b, key1, item1, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return set.size === 0;
|
||||
}
|
||||
|
||||
function mapEquiv(a, b, mode, memo) {
|
||||
let set = null;
|
||||
|
||||
@@ -675,21 +718,7 @@ function mapEquiv(a, b, mode, memo) {
|
||||
}
|
||||
|
||||
if (set !== null) {
|
||||
if (mode === kPartial) {
|
||||
return partialObjectMapEquiv(a, b, mode, set, memo);
|
||||
}
|
||||
for (const { 0: key1, 1: item1 } of a) {
|
||||
if (typeof key1 === 'object' && key1 !== null) {
|
||||
if (!mapHasEqualEntry(set, b, key1, item1, mode, memo))
|
||||
return false;
|
||||
} else if (mode === kLoose &&
|
||||
(!b.has(key1) ||
|
||||
!innerDeepEqual(item1, b.get(key1), mode, memo)) &&
|
||||
!mapHasEqualEntry(set, b, key1, item1, mode, memo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return set.size === 0;
|
||||
return mapObjectEquivalence(a, b, mode, set, memo);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -737,6 +766,24 @@ function partialArrayEquiv(a, b, mode, memos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function sparseArrayEquiv(a, b, mode, memos, i) {
|
||||
// TODO(BridgeAR): Use internal method to only get index properties. The
|
||||
// same applies to the partial implementation.
|
||||
const keysA = ObjectKeys(a);
|
||||
const keysB = ObjectKeys(b);
|
||||
if (keysA.length !== keysB.length) {
|
||||
return false;
|
||||
}
|
||||
for (; i < keysA.length; i++) {
|
||||
const key = keysA[i];
|
||||
if (!ObjectPrototypeHasOwnProperty(b, key) ||
|
||||
!innerDeepEqual(a[key], b[key], mode, memos)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function objEquiv(a, b, mode, keys2, memos, iterationType) {
|
||||
// The pair must have equivalent values for every corresponding key.
|
||||
if (keys2.length > 0) {
|
||||
@@ -755,23 +802,13 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) {
|
||||
if (!innerDeepEqual(a[i], b[i], mode, memos)) {
|
||||
return false;
|
||||
}
|
||||
const isOwnProperty = ObjectPrototypeHasOwnProperty(a, i);
|
||||
if (isOwnProperty !== ObjectPrototypeHasOwnProperty(b, i)) {
|
||||
const isSparseA = a[i] === undefined && !ObjectPrototypeHasOwnProperty(a, i);
|
||||
const isSparseB = b[i] === undefined && !ObjectPrototypeHasOwnProperty(b, i);
|
||||
if (isSparseA !== isSparseB) {
|
||||
return false;
|
||||
}
|
||||
if (!isOwnProperty) {
|
||||
// Array is sparse.
|
||||
// TODO(BridgeAR): Use internal method to only get index properties. The
|
||||
// same applies to the partial implementation.
|
||||
const keysA = ObjectKeys(a);
|
||||
for (; i < keysA.length; i++) {
|
||||
const key = keysA[i];
|
||||
if (!ObjectPrototypeHasOwnProperty(b, key) ||
|
||||
!innerDeepEqual(a[key], b[key], mode, memos)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return keysA.length === ObjectKeys(b).length;
|
||||
if (isSparseA) {
|
||||
return sparseArrayEquiv(a, b, mode, memos, i);
|
||||
}
|
||||
}
|
||||
} else if (iterationType === kIsSet) {
|
||||
|
||||
Reference in New Issue
Block a user