Skip to content

Commit

Permalink
assert: improve deepEqual perf for large input
Browse files Browse the repository at this point in the history
Use a Map instead of an array for checking previously found
cyclic references.

This reduces complexity for an array-of-objects case from
O(n²) to O(n·log n).

Fixes: #12842
PR-URL: #12849
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
addaleax committed May 7, 2017
1 parent 3fd890a commit 7e5f500
Showing 1 changed file with 15 additions and 6 deletions.
21 changes: 15 additions & 6 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,24 @@ function _deepEqual(actual, expected, strict, memos) {
// Note: this accounts for both named and indexed properties on Arrays.

// Use memos to handle cycles.
memos = memos || { actual: [], expected: [] };
const actualIndex = memos.actual.indexOf(actual);
if (actualIndex !== -1) {
if (actualIndex === memos.expected.indexOf(expected)) {
if (!memos) {
memos = {
actual: { map: new Map(), position: 0 },
expected: { map: new Map(), position: 0 }
};
}

const actualPosition = memos.actual.map.get(actual);
if (actualPosition !== undefined) {
if (actualPosition === memos.expected.map.get(expected)) {
return true;
}
} else {
memos.actual.map.set(actual, memos.actual.position++);
}
if (!memos.expected.map.has(expected)) {
memos.expected.map.set(expected, memos.expected.position++);
}
memos.actual.push(actual);
memos.expected.push(expected);

return objEquiv(actual, expected, strict, memos);
}
Expand Down

0 comments on commit 7e5f500

Please sign in to comment.