Skip to content

new Set(arr) seems faster #9

@jimmywarting

Description

@jimmywarting
  • There where no benchmarks to be found.
  • installing and executing the function didn't show any numbers (benchmark results #7)
  • updating benchmarked and executing the test was alarming too me cuz i wasn't sure if the mutable function would change the fixture (cuz i didn't get an array in my test function)
  • so i conducted my own test to se how this compared to using native new Set(iterable)
Vanilla source code (benchmark)
/**
 * Source: http://jsperf.com/array-unique2/15
 */

function randomize(n) {
  var values = [];
  var rand;
  while (n--) {
    rand = Math.random() * n * 2 | 0;
    if (rand < values.length) {
      values.push(values[rand]);
    }
    else {
      switch (Math.random() * 3 | 0) {
      case 0:
        values.push(Math.random() * 1e10 | 0);
        break;
      case 1:
        values.push((Math.random() * 1e32).toString(36));
        break;
      case 2:
        values.push({});
        break;
      }
    }
  }

  return values;
};

function unique(arr) {
  var len = arr.length;
  var i = -1;

  while (i++ < len) {
    var j = i + 1;

    for (; j < arr.length; ++j) {
      if (arr[i] === arr[j]) {
        arr.splice(j--, 1);
      }
    }
  }
  return arr;
};

function uniqueImmutable(arr) {
  var arrLen = arr.length;
  var newArr = new Array(arrLen);

  for (var i = 0; i < arrLen; i++) {
    newArr[i] = arr[i];
  }

  return unique(newArr);
};

function set(arr) {
  return [...new Set(arr)];
}

function setWithoutCasting(arr) {
  return new Set(arr);
}

for (let arr of [randomize(10000), randomize(500), randomize(10)]) {
  console.group(`Array(${arr.length})`)
  for (let fn of [unique, uniqueImmutable, set, setWithoutCasting]) {  
    let runs = 0
    let startCountingAt = performance.now() + 3000 // 3 sec later
    let stopAt = performance.now() + 5000 // 5 sec later
    let now = performance.now()
    while (now < stopAt) {
      // Pre run it a few times
      if (now > startCountingAt) {
        runs++;
      }
      fn([...arr]) // copy the array for each test and fn (unique mutates)
      now = performance.now();
    }
    console.log(`executed "${fn.name}(arr)" ${runs} times`)
  }
  console.groupEnd(`Array(${arr.length})`)
}
it's ashamed that ppl expect to be working with arrays all the times. `Set` is perfect for when you need uniqueness and it dose not have to be an Array all the time...

you can loop over Set the exact same way as with an Array, both Set and Array's have forEach and for..of loop support.

According to my benchmarks Set seems to be the way to go, it runs faster than your unique function in FF, Blink, Safari and NodeJS.

Need some numbers?

(higher number = faster)

Chrome v84

Skärmavbild 2020-08-07 kl  02 04 43

Safari v14
Skärmavbild 2020-08-07 kl  02 11 08

node v14.2.0
Skärmavbild 2020-08-07 kl  02 11 43

new Set(iterable) is so small, don't need any 3th party modules, it's built in and dose not offer readability for performance that i think this should be the recommended way for all who seeks for a solution

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions