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.



--------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------- Version française ---------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------------------------------------------



Introduction


Dans le dernier article, nous avons vu 3 méthodes pour dédoublonner un tableau en JavaScript. Je compare maintenant les performances de chacune d’entre elles.





performance.now()


La méthode performance.now() retourne une valeur temporelle, mesuré en millisecondes, avec une précision de 5 microsecondes, et représente le temps écoulé depuis l'origine de temps.


Ainsi, en stockant les valeurs retournées par performance.now() avant et après l’exécution d’une fonction, nous obtenons le laps de temps écoulé.


Par exemple : 




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




Méthodologie


Les 3 méthodes seront testées de la même façon : 




  • Tout d’abord, 3 tableaux de différentes longueurs (100, 100000 et 100000000 éléments) sont générés. Ces tableaux contiennent des nombres aléatoires.
  • Chaque tableau est dédoublonné 10 fois, et le temps écoulé est mesuré pour chaque dédoublonnage.
  • Enfin, la moyenne des 10 essais est calculée.


Le code est le suivant :




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

 <button onclick="onClick(uniqueArray1)">Méthode classique</button>
 <button onclick="onClick(uniqueArray2)">Méthode filter()</button>
 <button onclick="onClick(uniqueArray3)">Méthode Set</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)];
}





Résultats


Les résultats sont exprimés en millisecondes.







Conclusion


La méthode Set est de loin la plus performante, quelle que soit la longueur du tableau. Attention cependant, comme précisé dans mon précédent article, elle n’est disponible que depuis la version JavaScript ES2015 et il faudra donc bien vérifier la compatibilité avec les différents navigateurs avant de l’utiliser.


Entre les 2 autres méthodes, il semble préférable de choisir la méthode classique dès que l’on doit traiter des tableaux de longueur supérieure à une centaine d’éléments. La méthode filter(), quant à elle, peut être choisie pour de petits tableaux.

"