144 votes

Javascript pour Définir vs les performances de la baie

Peut-être parce que les Jeux sont relativement nouvelles pour Javascript, mais je n'ai pas été en mesure de trouver un article, sur StackO ou n'importe où ailleurs, qui parle de la différence de performances entre les deux en Javascript. Alors, quelle est la différence, en termes de performance, entre les deux? Plus précisément, lorsqu'il s'agit de suppression, d'ajout et d'itération.

158voto

neoflash Points 1183

Ok, j'ai testé l'ajout, l'itération et la suppression d'éléments d'un tableau et d'un ensemble. J'ai couru un "petit" test, à l'aide de 10 000 éléments et une "grande" de test, l'utilisation de 100 000 éléments. Voici les résultats.

Ajout d'éléments à une collection

Il semblerait que l' .push méthode de tableau est environ 4 fois plus rapide que l' .add méthode de jeu, peu importe le nombre d'éléments ajoutés.

Parcourir et modifier des éléments dans une collection

Pour cette partie du test, j'ai utilisé un for boucle pour parcourir le tableau et un for of boucle pour parcourir l'ensemble. De nouveau, parcourir le tableau a été plus rapide. Cette fois, il semble que c'est de façon exponentielle, de sorte qu'il a fallu deux fois plus longtemps pendant les "petites" les tests et près de quatre fois plus de temps pendant les "grands" des tests.

La suppression d'éléments d'une collection

Maintenant, c'est là que ça devient intéressant. J'ai utilisé une combinaison d'un for boucle et .splice de supprimer certains éléments de la matrice et j'ai utilisé for of et .delete de supprimer certains éléments de l'ensemble. Pour les "petits" tests, il a été environ trois fois plus rapide pour supprimer des éléments de l'ensemble (2,6 ms vs 7.1 ms), mais les choses ont changé de façon drastique pour les "grands" test où il a pris 1955.1 ms pour supprimer des éléments de la matrice tout cela a seulement pris de 83,6 ms pour les supprimer, 23 fois plus rapide.

Conclusions

À 10k éléments, les deux tests ont couru des périodes comparables (tableau: 16.6 ms, set: 20.7 ms), mais lorsque l'on traite avec 100k éléments, le set a été le gagnant clair (tableau: 1974.8 ms, set: 83.6 ms), mais seulement en raison de la suppression de l'opération. Sinon, le tableau a été plus rapide. Je ne pourrais pas dire exactement pourquoi.

J'ai joué un peu avec quelques hybrides scénarios où un tableau est créé et rempli, puis converti en un ensemble où certains éléments serait supprimé, l'ensemble serait alors de se reconvertir dans un tableau. Bien que cela va donner beaucoup de meilleures performances que la suppression d'éléments dans le tableau, le supplément de temps de traitement requis pour le transfert vers et à partir d'un ensemble emportent sur les gains de remplir un tableau au lieu d'un jeu. En fin de compte, il est plus rapide de ne faire affaire qu'avec un ensemble. Pourtant, c'est une idée intéressante, que si l'on choisit d'utiliser un tableau de la collecte de données pour certains gros des données qui n'ont pas de doublons, il pourrait être avantageux de performance sage, si il n'y a jamais un besoin de supprimer de nombreux éléments en une seule opération, pour convertir le tableau d'ensemble, effectuer l'opération de suppression, et de convertir le retour à un tableau.

Tableau code:

var timer = function(name) {
  var start = new Date();
  return {
    stop: function() {
      var end = new Date();
      var time = end.getTime() - start.getTime();
      console.log('Timer:', name, 'finished in', time, 'ms');
    }
  }
};

var getRandom = function(min, max) {
  return Math.random() * (max - min) + min;
};

var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];

var genLastName = function() {
  var index = Math.round(getRandom(0, lastNames.length - 1));
  return lastNames[index];
};

var sex = ["Male", "Female"];

var genSex = function() {
  var index = Math.round(getRandom(0, sex.length - 1));
  return sex[index];
};

var Person = function() {
  this.name = genLastName();
  this.age = Math.round(getRandom(0, 100))
  this.sex = "Male"
};

var genPersons = function() {
  for (var i = 0; i < 100000; i++)
    personArray.push(new Person());
};

var changeSex = function() {
  for (var i = 0; i < personArray.length; i++) {
    personArray[i].sex = genSex();
  }
};

var deleteMale = function() {
  for (var i = 0; i < personArray.length; i++) {
    if (personArray[i].sex === "Male") {
      personArray.splice(i, 1)
      i--
    }
  }
};

var t = timer("Array");

var personArray = [];

genPersons();

changeSex();

deleteMale();

t.stop();

console.log("Done! There are " + personArray.length + " persons.")

Définir un code:

var timer = function(name) {
    var start = new Date();
    return {
        stop: function() {
            var end  = new Date();
            var time = end.getTime() - start.getTime();
            console.log('Timer:', name, 'finished in', time, 'ms');
        }
    }
};

var getRandom = function (min, max) {
  return Math.random() * (max - min) + min;
};

var lastNames = ['SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON','MOORE','TAYLOR','ANDERSON','THOMAS'];

var genLastName = function() {
    var index = Math.round(getRandom(0, lastNames.length - 1));
    return lastNames[index];
};

var sex = ["Male", "Female"];

var genSex = function() {
    var index = Math.round(getRandom(0, sex.length - 1));
    return sex[index];
};

var Person = function() {
	this.name = genLastName();
	this.age = Math.round(getRandom(0,100))
	this.sex = "Male"
};

var genPersons = function() {
for (var i = 0; i < 100000; i++)
	personSet.add(new Person());
};

var changeSex = function() {
	for (var key of personSet) {
		key.sex = genSex();
	}
};

var deleteMale = function() {
	for (var key of personSet) {
		if (key.sex === "Male") {
			personSet.delete(key)
		}
	}
};

var t = timer("Set");

var personSet = new Set();

genPersons();

changeSex();

deleteMale();

t.stop();

console.log("Done! There are " + personSet.size + " persons.")

86voto

OBSERVATIONS:

  • Ensemble des opérations peut être compris comme des instantanés dans le flux d'exécution.
  • Nous ne sommes pas devant un définitif de substitution.
  • Les éléments d'un Ensemble de classe ont pas accessible index.
  • Ensemble de la classe est une classe Array complément, utile dans les scénarios où nous avons besoin de stocker une collection sur laquelle appliquer ajout de base, La suppression, la vérification et l'itération des opérations.

Je partage certains de test de performance. Essayez d'ouvrir votre console et copypaste le code ci-dessous.

La création d'un tableau (125000)

var n = 125000;
var arr = Array.apply( null, Array( n ) ).map( ( x, i ) => i );
console.info( arr.length ); // 125000

1. La localisation d'un Index

Nous avons comparé la méthode de Régler avec le Tableau indexOf:

Tableau/indexOf (0.281 ms) | Set/a (0.053 ms)

// Helpers
var checkArr = ( arr, item ) => arr.indexOf( item ) !== -1;
var checkSet = ( set, item ) => set.has( item );

// Vars
var set, result;

console.time( 'timeTest' );
result = checkArr( arr, 123123 );
console.timeEnd( 'timeTest' );

set = new Set( arr );

console.time( 'timeTest' );
checkSet( set, 123123 );
console.timeEnd( 'timeTest' );

2. L'ajout d'un nouvel élément

Nous comparons les ajouter et de pousser les méthodes de la série de tableaux et d'objets:

Tableau/push (1.612 ms) | Set/ajouter (0.006 ms)

console.time( 'timeTest' );
arr.push( n + 1 );
console.timeEnd( 'timeTest' );

set = new Set( arr );

console.time( 'timeTest' );
set.add( n + 1 );
console.timeEnd( 'timeTest' );

console.info( arr.length ); // 125001
console.info( set.size ); // 125001

3. La suppression d'un élément

Lors de la suppression d'éléments, nous devons garder à l'esprit que le Tableau et le Jeu ne démarre pas dans des conditions d'égalité. Tableau n'est pas une méthode native, donc une fonction externe est nécessaire.

Tableau/deleteFromArr (0.356 ms) | Définir/supprimer (0.019 ms)

var deleteFromArr = ( arr, item ) => {
    var i = arr.indexOf( item );
    i !== -1 && arr.splice( i, 1 );
};

console.time( 'timeTest' );
deleteFromArr( arr, 123123 );
console.timeEnd( 'timeTest' );

set = new Set( arr );

console.time( 'timeTest' );
set.delete( 123123 );
console.timeEnd( 'timeTest' );

Lire l'article complet ici

9voto

Zargold Points 644

J'ai récemment rencontré ce test et a constaté que beaucoup surperformé un Tableau de 1000 articles (environ 10 fois plus d'opérations sont susceptibles de se produire dans la même période). Et selon le navigateur soit battu ou perdu un Objet.hasOwnProperty dans l'un comme pour l'essai.

Les deux Ensemble et de l'Objet, ont leur "a la" méthode de la scène dans ce qui semble être amorti O(1), mais en fonction du navigateur de mise en œuvre d'une seule opération pourrait prendre plus de temps ou plus.

https://jsperf.com/set-has-vs-object-hasownproperty-vs-array-includes/1 Dans le cas où vous souhaitez exécuter vos propres tests avec les différents navigateurs et des milieux.

7voto

Sebastian Lasse Points 487

Mon observation est que un Jeu est toujours mieux à deux écueils pour les grands tableaux à l'esprit :

a) La création d'Ensembles de Matrices doivent être réalisées en for boucle avec une mises en cache au préalable la longueur.

lente (par exemple, 18ms) new Set(largeArray)

rapide (par exemple, 6ms) const SET = new Set(); const L = largeArray.length; for(var i = 0; i<L; i++) { SET.add(largeArray[i]) }

b) l'Itération peut être effectuée de la même façon, parce qu'il est aussi rapide qu'un for of boucle ...

Voir https://jsfiddle.net/0j2gkae7/5/

pour une vraie vie de comparaison pour difference(), intersection(), union() et uniq() ( + leurs iteratee compagnons etc.) avec 40.000 éléments

-6voto

jessh Points 1825
console.time("set")
var s = new Set()
for(var i = 0; i < 10000; i++)
  s.add(Math.random())
s.forEach(function(e){
  s.delete(e)
})
console.timeEnd("set")
console.time("array")
var s = new Array()
for(var i = 0; i < 10000; i++)
  s.push(Math.random())
s.forEach(function(e,i){
  s.splice(i)
})
console.timeEnd("array")

Ces trois opérations sur 10K éléments m'a donné:

set: 7.787ms
array: 2.388ms

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X