Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 80d9d56

Browse filesBrowse files
BridgeARaduh95
authored andcommitted
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: #57370 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
1 parent d52a71f commit 80d9d56
Copy full SHA for 80d9d56

File tree

Expand file treeCollapse file tree

1 file changed

+83
-46
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

1 file changed

+83
-46
lines changed
Open diff view settings
Collapse file

‎lib/internal/util/comparisons.js‎

Copy file name to clipboardExpand all lines: lib/internal/util/comparisons.js
+83-46Lines changed: 83 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,35 @@ function partialObjectSetEquiv(a, b, mode, set, memo) {
559559
}
560560
}
561561

562+
function setObjectEquiv(a, b, mode, set, memo) {
563+
if (mode === kPartial) {
564+
return partialObjectSetEquiv(a, b, mode, set, memo);
565+
}
566+
// Fast path for objects only
567+
if (mode === kStrict && set.size === a.size) {
568+
for (const val of a) {
569+
if (!setHasEqualElement(set, val, mode, memo)) {
570+
return false;
571+
}
572+
}
573+
return true;
574+
}
575+
576+
for (const val of a) {
577+
// Primitive values have already been handled above.
578+
if (typeof val === 'object') {
579+
if (!b.has(val) && !setHasEqualElement(set, val, mode, memo)) {
580+
return false;
581+
}
582+
} else if (mode === kLoose &&
583+
!b.has(val) &&
584+
!setHasEqualElement(set, val, mode, memo)) {
585+
return false;
586+
}
587+
}
588+
return set.size === 0;
589+
}
590+
562591
function setEquiv(a, b, mode, memo) {
563592
// This is a lazily initiated Set of entries which have to be compared
564593
// pairwise.
@@ -584,22 +613,7 @@ function setEquiv(a, b, mode, memo) {
584613
}
585614

586615
if (set !== null) {
587-
if (mode === kPartial) {
588-
return partialObjectSetEquiv(a, b, mode, set, memo);
589-
}
590-
for (const val of a) {
591-
// Primitive values have already been handled above.
592-
if (typeof val === 'object' && val !== null) {
593-
if (!b.has(val) && !setHasEqualElement(set, val, mode, memo)) {
594-
return false;
595-
}
596-
} else if (mode === kLoose &&
597-
!b.has(val) &&
598-
!setHasEqualElement(set, val, mode, memo)) {
599-
return false;
600-
}
601-
}
602-
return set.size === 0;
616+
return setObjectEquiv(a, b, mode, set, memo);
603617
}
604618

605619
return true;
@@ -640,6 +654,35 @@ function partialObjectMapEquiv(a, b, mode, set, memo) {
640654
}
641655
}
642656

657+
function mapObjectEquivalence(a, b, mode, set, memo) {
658+
if (mode === kPartial) {
659+
return partialObjectMapEquiv(a, b, mode, set, memo);
660+
}
661+
// Fast path for objects only
662+
if (mode === kStrict && set.size === a.size) {
663+
for (const { 0: key1, 1: item1 } of a) {
664+
if (!mapHasEqualEntry(set, b, key1, item1, mode, memo)) {
665+
return false;
666+
}
667+
}
668+
return true;
669+
}
670+
for (const { 0: key1, 1: item1 } of a) {
671+
if (typeof key1 === 'object' && key1 !== null) {
672+
if (!mapHasEqualEntry(set, b, key1, item1, mode, memo))
673+
return false;
674+
} else if (set.size === 0) {
675+
return true;
676+
} else if (mode === kLoose &&
677+
(!b.has(key1) ||
678+
!innerDeepEqual(item1, b.get(key1), mode, memo)) &&
679+
!mapHasEqualEntry(set, b, key1, item1, mode, memo)) {
680+
return false;
681+
}
682+
}
683+
return set.size === 0;
684+
}
685+
643686
function mapEquiv(a, b, mode, memo) {
644687
let set = null;
645688

@@ -675,21 +718,7 @@ function mapEquiv(a, b, mode, memo) {
675718
}
676719

677720
if (set !== null) {
678-
if (mode === kPartial) {
679-
return partialObjectMapEquiv(a, b, mode, set, memo);
680-
}
681-
for (const { 0: key1, 1: item1 } of a) {
682-
if (typeof key1 === 'object' && key1 !== null) {
683-
if (!mapHasEqualEntry(set, b, key1, item1, mode, memo))
684-
return false;
685-
} else if (mode === kLoose &&
686-
(!b.has(key1) ||
687-
!innerDeepEqual(item1, b.get(key1), mode, memo)) &&
688-
!mapHasEqualEntry(set, b, key1, item1, mode, memo)) {
689-
return false;
690-
}
691-
}
692-
return set.size === 0;
721+
return mapObjectEquivalence(a, b, mode, set, memo);
693722
}
694723

695724
return true;
@@ -737,6 +766,24 @@ function partialArrayEquiv(a, b, mode, memos) {
737766
return true;
738767
}
739768

769+
function sparseArrayEquiv(a, b, mode, memos, i) {
770+
// TODO(BridgeAR): Use internal method to only get index properties. The
771+
// same applies to the partial implementation.
772+
const keysA = ObjectKeys(a);
773+
const keysB = ObjectKeys(b);
774+
if (keysA.length !== keysB.length) {
775+
return false;
776+
}
777+
for (; i < keysA.length; i++) {
778+
const key = keysA[i];
779+
if (!ObjectPrototypeHasOwnProperty(b, key) ||
780+
!innerDeepEqual(a[key], b[key], mode, memos)) {
781+
return false;
782+
}
783+
}
784+
return true;
785+
}
786+
740787
function objEquiv(a, b, mode, keys2, memos, iterationType) {
741788
// The pair must have equivalent values for every corresponding key.
742789
if (keys2.length > 0) {
@@ -755,23 +802,13 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) {
755802
if (!innerDeepEqual(a[i], b[i], mode, memos)) {
756803
return false;
757804
}
758-
const isOwnProperty = ObjectPrototypeHasOwnProperty(a, i);
759-
if (isOwnProperty !== ObjectPrototypeHasOwnProperty(b, i)) {
805+
const isSparseA = a[i] === undefined && !ObjectPrototypeHasOwnProperty(a, i);
806+
const isSparseB = b[i] === undefined && !ObjectPrototypeHasOwnProperty(b, i);
807+
if (isSparseA !== isSparseB) {
760808
return false;
761809
}
762-
if (!isOwnProperty) {
763-
// Array is sparse.
764-
// TODO(BridgeAR): Use internal method to only get index properties. The
765-
// same applies to the partial implementation.
766-
const keysA = ObjectKeys(a);
767-
for (; i < keysA.length; i++) {
768-
const key = keysA[i];
769-
if (!ObjectPrototypeHasOwnProperty(b, key) ||
770-
!innerDeepEqual(a[key], b[key], mode, memos)) {
771-
return false;
772-
}
773-
}
774-
return keysA.length === ObjectKeys(b).length;
810+
if (isSparseA) {
811+
return sparseArrayEquiv(a, b, mode, memos, i);
775812
}
776813
}
777814
} else if (iterationType === kIsSet) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.