Introduction


In the previous post, we reviewed 3 methods to remove duplicate values from an array in JavaScript. I would like to go deeper and show you the performance of each method.


performance.now()


performance.now() returns a time value in milliseconds with a 5 microseconds precision, and represents the time elapsed since the time origin.


Hence, storing the values returned by performance.now() before and after a function execution, we obtain the time elapsed.


For instance:

const before = performance.now();
// exécuter une fonction ici
const after = performance.now();
console.log(after - before); // le temps écoulé en millisecondes s’affiche



Mode of operation


Each of 3 methods will be tested as follow:


  • First, we generate 3 arrays of various length (100, 100000 and 100000000 items). These arrays are filled with random numbers.
  • We process each array 10 times, and elapsed time is measured at each process.
  • Finally, we calculate the average of the 10 tests for each method.


Here is the code:


  • index.html
<!DOCTYPE html>
<html>
<head>
 <title>Performance Tests</title>
</head>
<body>

 <button onclick="onClick(uniqueArray1)">Classic method</button>
 <button onclick="onClick(uniqueArray2)">filter() method</button>
 <button onclick="onClick(uniqueArray3)">Set method</button>
  
 <script src="/js/main.js"></script>
</body>
</html>


  • js/main.js
// Define a method that creates an array of random number
const randomArray = (length, max) => [...new Array(length)].map(() => Math.round(Math.random() * max));

// Create 3 array (small, medium, large)
const numbersArray = [
 randomArray(100, 100),
 randomArray(100000, 100),
 randomArray(100000000, 100)
];

// On button click
function onClick(callback) {
 const trials = 10;
 for (let i = 0; i < numbersArray.length; i++) {
  const numbers = numbersArray[i];
  const times = [];
  for (let j = 0; j < trials; j++) {
   // Before function execution
   const t0 = performance.now();
   callback(numbers);
   // After function execution
   const t1 = performance.now();
   times.push(t1 - t0);
  }
  // Average time for the n trials
  const average = times.reduce((acc, curr) => acc + curr, 0 ) / times.length;
  // Log average and array length
  console.log(`Array of ${numbers.length} elements has been cleaned in ${average} ms`);
 }
}

// Method 1
function uniqueArray1(arr) {
 const uniqueArray = [ ];
 for (let i=0; i < arr.length; i++) {
  const currentValue = arr[i];
  if (uniqueArray.indexOf(currentValue) === -1) {
   uniqueArray.push(currentValue);
  }
 }
    
 return uniqueArray;
}

// Method 2
function uniqueArray2(arr) {
 return arr.filter((currentValue, currentIndex, currentArray) => currentArray.indexOf(currentValue) === currentIndex);
}

// Method 3
function uniqueArray3(arr) {
 return [...new Set(arr)];
}


Results


Results are shown in milliseconds.




Conclusion


Set method is by far the most performant, regardless of the array length. As mentionned in my previous post, be careful while using it, as it was released in ES2015.


Between the two other methods, it seems better to use the classic method if we have arrays > 100 items. filter() method can be used for small arrays, as its performance is not so bad compared to the classic one.