Lodash isEqual vs vanilla deepEqual (v295)

Revision 295 of this benchmark created on


Preparation HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Setup

function deepEqual(obj1, obj2) {
  if (obj1 === obj2) {
    return true
  }

  if (obj1 == null || obj2 == null || typeof obj1 !== 'object' || typeof obj2 !== 'object') {
    return false
  }

  const keys1 = Object.keys(obj1)
  const keys2 = Object.keys(obj2)

  if (keys1.length !== keys2.length) {
    return false
  }

  for (const key of keys1) {
    if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
      return false
    }
  }

  return true
}
    
function generateRandomObject(objectSize, maxDepth) {
  const KB = 1024;
  const targetSize = objectSize * KB;
  let currentSize = 0;

  function getRandomKey() {
    return Math.random().toString(36).substring(2, 15);
  }

  function getRandomPrimitive() {
    const primitives = [
      Math.random().toString(36).substring(2, 15), // string
      Math.floor(Math.random() * 100), // number
      Math.random() < 0.5, // boolean
      null // null
    ];
    return primitives[Math.floor(Math.random() * primitives.length)];
  }

  function getRandomValue(depth) {
    if (depth >= maxDepth) {
      return getRandomPrimitive();
    }

    const types = ['object', 'array', 'primitive'];
    const type = types[Math.floor(Math.random() * types.length)];

    switch (type) {
      case 'object':
        return generateRandomObjectHelper(depth + 1);
      case 'array':
        return Array.from({ length: Math.floor(Math.random() * 5) + 1 }, () => getRandomValue(depth + 1));
      case 'primitive':
        return getRandomPrimitive();
    }
  }

  function generateRandomObjectHelper(depth) {
    const obj = {};
    while (currentSize < targetSize) {
      for (let i = 0; i < 10; i++) { // Increase the number of keys per level
        const key = getRandomKey();
        const value = getRandomValue(depth);
        obj[key] = value;
        currentSize += key.length + JSON.stringify(value).length;
        if (currentSize >= targetSize) break;
      }
    }
    return obj;
  }

  return generateRandomObjectHelper(0);
}

var smallObj = generateRandomObject(1, 3);
var smallObjCpy = _.cloneDeep(smallObj)
var smallObj2 = generateRandomObject(1, 3);
var medObj = generateRandomObject(3, 6);
var medObjCpy = _.cloneDeep(medObj)
var medObj2 = generateRandomObject(3, 6);
var largeObj = generateRandomObject(5, 8);
var largeObjCpy = _.cloneDeep(largeObj)
var largeObj2 = generateRandomObject(5, 8);

Test runner

Ready to run.

Testing in
TestOps/sec
Lodash isEqual - Small (Equal)
_.isEqual(smallObj, smallObjCpy)
ready
Vanilla deepEqual - Small (Equal)
deepEqual(smallObj, smallObjCpy)
ready
Lodash isEqual - Medium (Equal)
_.isEqual(medObj, medObjCpy)
ready
Vanilla deepEqual - Medium (Equal)
deepEqual(medObj, medObjCpy)
ready
Lodash isEqual - Large (Equal)
_.isEqual(largeObj, largeObjCpy)
ready
Vanilla deepEqual - Large (Equal)
deepEqual(largeObj, largeObjCpy)
ready
Lodash isEqual - Small (Not equal)
_.isEqual(smallObj, smallObj2)
ready
Vanilla deepEqual - Small (Not equal)
deepEqual(smallObj, smallObj2)
ready
Lodash isEqual - Medium (Not equal)
_.isEqual(medObj, medObj2)
ready
Vanilla deepEqual - Medium (Not equal)
deepEqual(medObj, medObj2)
ready
Lodash isEqual - Large (Not equal)
_.isEqual(largeObj, largeObj2)
ready
Vanilla deepEqual - Large (Not equal)
deepEqual(largeObj, largeObj2)
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.