Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
assert.deepEqual() vs require('deep-equal')
> var eq = require('deep-equal'); var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
125
> var assert = require('assert'); function eq (x, y) { try { assert.deepEqual(x,y); return true } catch (e) { return false } } var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
566
@defunctzombie

This comment has been minimized.

Copy link

@defunctzombie defunctzombie commented May 25, 2012

The deep-equal doesn't use the try/catch so that may be causing some penalty with the actual benchmark. What does it look like if you don't have the try/catch?

@substack

This comment has been minimized.

Copy link
Owner Author

@substack substack commented May 26, 2012

The try/catch is the benchmark. The deep-equal package is the assert.deepEqual source except that it returns true or false instead of throwing.

@andrewdeandrade

This comment has been minimized.

Copy link

@andrewdeandrade andrewdeandrade commented Jul 11, 2012

For the sake of contributing another data point, deep-equal is only marginally faster when the objects being compared are very large, such as testing the JSON representation of scraping an entire page. I compared a 5kb json file with itself and the results were 801 and 862, respectively.

FYI, on my machine, I got 41 and 155 for the two tests above. (3x)

@andrewdeandrade

This comment has been minimized.

Copy link

@andrewdeandrade andrewdeandrade commented Jul 11, 2012

FWIW, what would be valuable versus node's assert.deepEqual function would be a deepEqual that performs a diff of the two objects and tells you exactly how they are different. I guess such a function would best be called deepDiff().

@connor4312

This comment has been minimized.

Copy link

@connor4312 connor4312 commented Dec 26, 2014

Also of note (if you're not sure of the types of things your comparing) deep-equal is significantly more efficient on simple data types, such as integers.

> var eq = require('deep-equal'); var obj1 = 1, obj2 = 2; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
1
> var assert = require('assert'); function eq (x, y) { try { assert.deepEqual(x,y); return true } catch (e) { return false } } var obj1 = 1, obj2 = 2; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
116
@nfantone

This comment has been minimized.

Copy link

@nfantone nfantone commented Mar 13, 2017

@substack Given that this was created five years ago, hasn't been revisited since then and it's still featured in the README, it'd be nice to know if this benchmark/comparison still holds true.

@nfantone

This comment has been minimized.

Copy link

@nfantone nfantone commented Mar 13, 2017

Just tried the original gist on node 7.7.2, as a matter of fact, and got this back:

> var eq = require('deep-equal'); var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
39
> var assert = require('assert'); function eq (x, y) { try { assert.deepEqual(x,y); return true } catch (e) { return false } } var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
1229
@nfantone

This comment has been minimized.

Copy link

@nfantone nfantone commented Mar 13, 2017

There's an interesting fact: running the "benchmark" outside the REPL actually hurts deep-equal performance and boosts node's.

→ node test-assert-deep-equal
977

→ node test-deep-equal
57
@antstanley

This comment has been minimized.

Copy link

@antstanley antstanley commented Jan 2, 2019

Just tried this on my machine with Node 11.6.0 ... still faster

> var eq = require('deep-equal'); var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
37
> var assert = require('assert'); function eq (x, y) { try { assert.deepEqual(x,y); return true } catch (e) { return false } } var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
696
@ljharb

This comment has been minimized.

Copy link

@ljharb ljharb commented Dec 3, 2019

Latest updates with the upcoming v2:

> var eq = require('deep-equal'); var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
23
> var assert = require('assert'); function eq (x, y) { try { assert.deepEqual(x,y); return true } catch (e) { return false } } var obj1 = { a : 2, b : 3, c : [ 3, 4 ] }, obj2 = { a : 2, b : 3, c : [ 4, 5 ] }; var t0 = Date.now(); for (var i = 0; i < 10000; i++) eq(obj1, obj2); Date.now() - t0
1061
@BridgeAR

This comment has been minimized.

Copy link

@BridgeAR BridgeAR commented Dec 4, 2019

This benchmark does not actually compare this in any realistic manner. It does not compare the actual comparison performance. Instead, it benchmarks how fast thousands of errors are created. This is quite expensive (plus additional overhead inspecting the value over and over again).

If the objects are identical, assert is significantly faster (~ factor 10 using deep-equal v.1.1.1. ~factor 200 when using v2.0.0). I am absolutely sure that there is no faster implementation out there than the one in Node.js (at this point of time).

The loose equality check is also not recommended in general. Instead, only the strict one should be used. That one is also exposed as utility function (util.isDeepStrictEqual(a, b)) that just simply returns a boolean.

A fair benchmark is therefore:

const de = require('deep-equal') // v1.1.1
const util = require('util')
const assert = require('assert') // Node.js core v13.3.0

let obj1 = { a : 2, b : 3, c : [ 3, 4 ] }
let obj2 = { a : 2, b : 3, c : [ 4, 5 ] }
let obj3 = { a : 2, b : 3, c : [ 3, 4 ] }

function deepEqual(a, b, opts) {
  if (opts && opts.strict)
    return util.isDeepStrictEqual(a, b)
  const limit = Error.stackTraceLimit
  try {
    // Alternative
    Error.stackTraceLimit = 0;
    assert.deepEqual(a, b)
    return true
  } catch {
    return false
  } finally {
    Error.stackTraceLimit = limit
  }
}

function run({ mode = 0, identical = 0 } = {}) {
  console.log('Running %s mode', ['mixed', 'strict', 'loose'][mode])
  console.log('Objects are always', ['changing', 'identical', 'different'][identical])
  console.log()

  const opts = { strict: mode === 1 }

  console.time('assert')
  for (let i = 0; i < 1e5; i++) {
    let rightSide = obj2
    if (mode === 0)
      opts.strict = i % 4 <= 2
    if (identical === 0) {
      if (i % 2 === 0)
        rightSide = obj3
    } else if (identical === 1) {
      rightSide = obj3
    }
    deepEqual(obj1, rightSide, opts)
  }
  console.timeEnd('assert')
  console.time('deep-equal')
  for (let i = 0; i < 1e5; i++) {
    let rightSide = obj2
    if (mode === 0)
      opts.strict = i % 4 <= 2
    if (identical === 0) {
      if (i % 2 === 0)
        rightSide = obj3
    } else if (identical === 1) {
      rightSide = obj3
    }
    de(obj1, rightSide, opts)
  }
  console.timeEnd('deep-equal')
}

run({ mode: 0, identical: 0 })
// Running mixed mode
// Objects are always changing

// assert: 870.567ms
// deep-equal: 2.160s

run({ mode: 1, identical: 0 })
// Running strict mode
// Objects are always changing

// assert: 150.689ms
// deep-equal: 2.096s

run({ mode: 2, identical: 0 })
// Running loose mode
// Objects are always changing

// assert: 1.494s
// deep-equal: 2.184s

run({ mode: 0, identical: 1 })
// Running mixed mode
// Objects are always identical

// assert: 152.072ms
// deep-equal: 1.981s

run({ mode: 1, identical: 1 })
// Running strict mode
// Objects are always identical

// assert: 138.718ms
// deep-equal: 2.066s

run({ mode: 2, identical: 1 })
// Running loose mode
// Objects are always identical

// assert: 120.637ms
// deep-equal: 1.990s

run({ mode: 0, identical: 2 })
// Running mixed mode
// Objects are always different

// assert: 744.344ms
// deep-equal: 2.007s

run({ mode: 1, identical: 2 })
// Running strict mode
// Objects are always different

// assert: 138.866ms
// deep-equal: 1.958s

run({ mode: 2, identical: 2 })
// Running loose mode
// Objects are always different

// assert: 2.585s
// deep-equal: 1.929s
``
@jgehrcke

This comment has been minimized.

Copy link

@jgehrcke jgehrcke commented Jul 15, 2020

@BridgeAR thanks for your comment!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.