Qu'est-ce que la performance des Objets ou des Tableaux en JavaScript? (spécifiquement pour Google V8)
De Performance associés à des Tableaux et des Objets en JavaScript (en particulier Google V8) serait très intéressant de document. Je ne trouve aucun article complet sur ce sujet n'importe où sur Internet.
Je comprends que certains Objets de l'utilisation des classes que leurs données sous-jacentes de la structure. Si il y a un grand nombre de propriétés, il est parfois traitée comme une table de hachage?
Je comprends aussi que les Tableaux sont parfois traités comme C++ Tableaux (c'est à dire aléatoire rapide de l'indexation, de lent, de suppression et de redimensionnement). Et, d'autres fois, ils sont traités plus comme des Objets (indexation rapide, rapide insertion/suppression, plus de mémoire). Et, peut-être que parfois ils sont stockés comme des listes liées (c'est à dire ralentir aléatoire de l'indexation, l'élimination rapide/insertion en début/fin)
Qu'est-ce que la précision et les performances de Tableau/Objet de récupérations et de manipulations en JavaScript? (spécifiquement pour Google V8)
Plus précisément, quel est l'impact sur les performances de:
- Ajout d'une propriété à un Objet
- Suppression d'une propriété d'un Objet
- L'indexation d'une propriété à un Objet
- L'ajout d'un élément à un Tableau
- Suppression d'un élément dans un Tableau
- L'indexation d'un élément dans un Tableau
- L'Appel De Tableau.pop()
- L'Appel De Tableau.push()
- L'Appel De Tableau.maj()
- L'Appel De Tableau.unshift()
- L'Appel De Tableau.slice()
Des articles ou des liens pour plus de détails serait appréciée, ainsi. 🙂
EDIT: je me demande vraiment comment les tableaux JavaScript et des objets de travail sous le capot. Aussi, dans ce contexte le moteur V8 de "savoir" à "bascule" vers une autre structure de données?
Par exemple, supposons que je crée un tableau avec...
var arr = [];
arr[10000000] = 20;
arr.push(21);
Ce qui se passe réellement ici?
Ou... quoi à ce sujet...???
var arr = [];
//Add lots of items
for(var i = 0; i < 1000000; i++)
arr[i] = Math.random();
//Now I use it like a queue...
for(var i = 0; i < arr.length; i++)
{
var item = arr[i].shift();
//Do something with item...
}
Pour les réseaux classiques, le rendement serait terrible; considérant que, si une LinkedList a été utilisé... pas si mal.
- Visitez le site jsperf.com, et de créer des cas de test.
- Il n'y a plus en jeu ici que de simples tests peuvent rendre compte de ce qui nécessite la connaissance de la façon dont les compilateurs JIT travail, et ce qui est fait avec les données. Si je trouve le temps je vais ajouter une réponse, mais j'espère que quelqu'un aura le temps de passer aux choses sérieuses. Aussi, j'aimerais quitter ce lien ici
- JIT choses dont je parle sont des choses comme la "forme" d'un objet, ou des tableaux avec des valeurs non définies entre les éléments définis, ainsi que plus récemment essayé de type spécialisé de fonctionnalités... tableau-méthodes spécifiques peuvent dépendre de l'utilisation ainsi que si le prototype a été manipulé ou non. Il n'y a pas une telle chose comme "un savoir" passer à un autre type de données autant que je sache.
- Il y a des représentants de Google ont discuté, comment les différents optimiseur et du système interne des œuvres. Et comment les optimiser pour eux. (pour les jeux!!!) youtube.com/watch?v=XAqIpGU8ZZk
Vous devez vous connecter pour publier un commentaire.
Mise à JOUR: Notez que JSPref est actuellement en panne
(j'ai sauvegardé une copie du cas de test, et sera mise à jour de la réponse une fois JSPref est fixe et qu'un successeur soit trouvé)
Hmm... peut-être trop pour la réponse... mais j'ai créé une suite de tests, précisément pour explorer ces questions (et bien plus) (copie archivée).
Et, dans ce sens, vous pouvez voir les problèmes de performances de ce 50+ cas de test testeur (il va prendre un certain temps).
Aussi comme son nom l'indique, il explore l'utilisation de l'aide de la maternelle liste liée à la nature de la DOM structure.
(Actuellement en panne, reconstruit en cours) Plus de détails sur mon blog à propos de ce.
Le résumé est suivi
Array.shift()
est rapide ~environ 6x plus lent qu'un tableau de la pop, mais il est ~environ 100 fois plus rapide qu'un attribut de l'objet de la suppression.Array.push( data );
est plus rapide queArray[nextIndex] = data
de près de 20 (tableau dynamique) à 10 (tableau fixe) fois plus.Array.unshift(data)
est plus lent que prévu, et est ~environ 5x plus lent que l'ajout d'une nouvelle propriété.array[index] = null
est plus rapide que de le supprimerdelete array[index]
(undefined) dans un tableau par ~environ 4x plus rapide++.obj[attr] = null
~environ 2x plus lent que tout simplement en supprimant l'attributdelete obj[attr]
Array.splice(index,0,data)
est lent, très lent.Array.splice(index,1,data)
a été optimisé (pas de changement de longueur) et est 100x plus rapide que seulement épissureArray.splice(index,0,data)
dll.splice(index,1)
la suppression (Où il a cassé le système de test).Remarque: Ces mesures ne s'applique qu'aux grands tableaux/objets, dont le v8 n'est pas "entièrement optimiser out". Il peut être très isolé des performances optimisées pour les cas de tableau/taille de l'objet à moins d'une taille arbitraire (24?). Plus de détails peuvent être vus largement à travers plusieurs google IO vidéos.
Note 2: Ces merveilleux résultats de performance ne sont pas partagées entre les différents navigateurs, en particulier
*cough*
IE. Aussi le test est énorme, j'ai donc pas encore pleinement d'analyser et d'évaluer les résultats : merci de modifier en =)Mise à jour de la Note (décembre 2012): représentants de Google ont des vidéos sur ses youtubes décrivant le fonctionnement interne de chrome lui-même (comme quand on passe d'un linkedlist tableau un tableau fixe, etc), et comment les optimiser. Voir La GDC 2012: à Partir de la Console de Chrome pour plus d'.
Mise à jour de la Note (février 2013): Thx @badunk, pour fournir le lien vidéo à l'exact point de
Mise à jour de la Note (juin 2016): Thx @Benedikt, à propos de la matrice de pousser différence de rendement fixe /tableaux dynamiques.
null
ouundefined
est plus rapide quedelete
ilArray.push( data )
est plus rapide queArray[nextIndex] = data
par près de 20 fois plus." attention: Ceci s'applique seulement si votre taille de la matrice ne peut pas être déterminé à l'avance. Le redimensionnement des tableaux coûte beaucoup d'exécution! Voir ce violon.Array.clear
?À un niveau de base qui reste dans les limites de JavaScript, les propriétés sur les objets sont beaucoup plus complexes entités. Vous pouvez créer des propriétés avec des setters/getters, avec différentes enumerability, writability, et la configurabilité. Un élément dans un tableau ne peut pas être personnalisé de cette façon: soit il existe ou qu'il n'a pas. Le moteur sous-jacent niveau, cela permet beaucoup plus de l'optimisation en termes d'organisation de la mémoire qui représente la structure.
En termes d'identification d'un tableau à partir d'un objet (dictionnaire), JS moteurs ont toujours fait explicite des lignes entre les deux. C'est pourquoi il existe une multitude d'articles sur les méthodes d'essayer de faire un semi-faux Tableau comme objet qui se comporte comme un, mais permet à d'autres fonctionnalités. La raison de cette séparation même existe, c'est parce que le JS les moteurs eux-mêmes stocker les deux différemment.
Propriétés peuvent être stockées sur un tableau d'objet, mais cela démontre simplement comment JavaScript insiste sur faire tout un objet. L'indexation des valeurs d'un tableau sont stockés différemment de toutes les propriétés que vous décidez de fixer sur le tableau de l'objet qui représente le sous-jacent de la matrice de données.
Chaque fois que vous êtes à l'aide d'une pièce de théâtre d'objet tableau et à l'aide de l'une des méthodes standard de la manipulation de ce tableau, vous allez être frappé dans la sous-jacentes de la matrice de données. En V8 spécifiquement, ces sont essentiellement les mêmes qu'en C++ tableau afin que ces règles s'appliqueront. Si pour quelque raison vous travaillez avec un tableau que le moteur n'est pas en mesure de déterminer avec confiance est un tableau, alors vous êtes beaucoup shakier sol. Avec les versions récentes de V8 il y a plus de place pour un travail même si. Par exemple, il est possible de créer une classe qui a de la Matrice.prototype que son prototype et toujours obtenir un accès efficace aux divers tableau natif méthodes de manipulation. Mais ce changement est récent.
Des liens spécifiques des récentes modifications apportées à la gamme de manipulation peut être utile ici:
Un peu plus, voici la Matrice de la Pop et de la Matrice de Pousser directement à partir d'un V8 de la source, à la fois mis en œuvre en JS lui-même:
Lors de l'exécution en vertu de l'node.js 0.10 (construit sur v8), j'ai été voir l'utilisation du PROCESSEUR qui semble excessif de la charge de travail. J'ai tracé un problème de performances à une fonction qui était de vérifier l'existence d'une chaîne de caractères dans un tableau. Alors, j'ai couru quelques tests.
Chargement 91k entrées dans un tableau (à valider & push) est plus rapide que le paramètre obj[clé]=valeur.
Dans le prochain test, j'ai regardé chaque nom d'hôte dans la liste une fois (91k itérations, en moyenne à la recherche du temps):
L'application ici est Haraka (un serveur SMTP) et charge le host_list fois au démarrage (et modifications) et ensuite effectue cette recherche des millions de fois au cours de l'opération. Le passage à un objet a été un énorme performance de gagner.
Je voudrais, pour compléter les réponses à une enquête à la question de savoir comment les implémentations de se comporter concernant la croissance des tableaux: Si ils en œuvre du cadre "habituel" façon, on pouvait voir de nombreux rapide pousse rares, entrecoupées de ralentir la pousse à quel point la mise en œuvre des copies de la représentation interne de la matrice à partir d'un tampon pour un plus grand.
Vous pouvez voir cet effet de très bien, c'est à partir de google Chrome:
Même si chaque poussée est profilé, la sortie ne contient que ceux qui prennent le temps au-dessus d'un certain seuil. Pour chaque test, je l'ai adapté le seuil d'exclure toutes les poussées qui semblent représenter la pousse rapide.
Donc, le premier nombre représente l'élément inséré (la première ligne est pour la 17e élément), le second est combien de temps il a fallu (pour de nombreux tableaux de l'indice de référence se fait en parallèle), et la dernière valeur de la division du premier nombre par celui de l'une dans les ancienne ligne.
Toutes les lignes qui ont moins de 2 ms de temps d'exécution est exclue pour Chrome.
Vous pouvez voir que le Chrome augmente la taille du tableau dans les puissances de 1,5, plus un certain décalage à prendre en compte pour les petits tableaux.
Pour Firefox, c'est une puissance de deux:
J'ai dû mettre le seuil un peu dans Firefox, c'est pourquoi nous commençons à #126.
Avec IE, on obtient un mélange:
C'est une puissance de deux au début, puis il se déplace à des puissances de cinq tiers.
Donc tous les implémentations utilisent la voie "normale" pour les tableaux (au lieu d'aller fou avec cordes, par exemple).
Voici le code de référence et voici le violon c'est dans.