Skip to content

Commit

Permalink
assert,util: improve deep equal comparison performance
Browse files Browse the repository at this point in the history
This is mainly a performance improvement for a lot of simple cases.
Diverging elements are detected earlier and equal entries are
partially also detected faster.

A small correctness patch is also included where recursions now
stop as soon as either side has a circular structure. Before, both
sides had to have a circular structure at the specific comparison
which could have caused more checks that likely fail at a later
point.

Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de>
PR-URL: #46593
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
BridgeAR authored and targos committed Mar 13, 2023
1 parent abba45e commit 7f85a2c
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 132 deletions.
3 changes: 2 additions & 1 deletion benchmark/assert/deepequal-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const bench = common.createBenchmark(main, {
combinationFilter: (p) => {
return p.size === 1e4 && p.n === 25 ||
p.size === 1e3 && p.n === 2e2 ||
p.size === 1e2 && p.n === 2e3;
p.size === 1e2 && p.n === 2e3 ||
p.size === 1;
},
});

Expand Down
12 changes: 10 additions & 2 deletions doc/api/assert.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,10 @@ An alias of [`assert.ok()`][].
<!-- YAML
added: v0.1.21
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/46593
description: Recursion now stops when either side encounters a circular
reference.
- version: v18.0.0
pr-url: https://github.com/nodejs/node/pull/41020
description: Regular expressions lastIndex property is now compared as well.
Expand Down Expand Up @@ -617,7 +621,7 @@ are also recursively evaluated by the following rules.
* [Object wrappers][] are compared both as objects and unwrapped values.
* `Object` properties are compared unordered.
* [`Map`][] keys and [`Set`][] items are compared unordered.
* Recursion stops when both sides differ or both sides encounter a circular
* Recursion stops when both sides differ or either side encounters a circular
reference.
* Implementation does not test the [`[[Prototype]]`][prototype-spec] of
objects.
Expand Down Expand Up @@ -727,6 +731,10 @@ parameter is an instance of an [`Error`][] then it will be thrown instead of the
<!-- YAML
added: v1.2.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/46593
description: Recursion now stops when either side encounters a circular
reference.
- version: v18.0.0
pr-url: https://github.com/nodejs/node/pull/41020
description: Regular expressions lastIndex property is now compared as well.
Expand Down Expand Up @@ -780,7 +788,7 @@ are recursively evaluated also by the following rules.
* [Object wrappers][] are compared both as objects and unwrapped values.
* `Object` properties are compared unordered.
* [`Map`][] keys and [`Set`][] items are compared unordered.
* Recursion stops when both sides differ or both sides encounter a circular
* Recursion stops when both sides differ or either side encounters a circular
reference.
* [`WeakMap`][] and [`WeakSet`][] comparison does not rely on their values. See
below for further details.
Expand Down
Loading

0 comments on commit 7f85a2c

Please sign in to comment.