80 votes

Y a-t-il un avantage en termes de performances à "verrouiller" les objets JavaScript ?

JavaScript 1.8.5 (ECMAScript 5) ajoute quelques méthodes intéressantes qui prévenir les modifications futures d'un objet passé, avec plus ou moins de minutie :

On peut supposer que leur but principal est de détecter les erreurs : si vous savez que vous ne voulez pas modifier un objet après un certain point, vous pouvez le verrouiller de façon à ce qu'une erreur soit déclenchée si vous essayez de le modifier plus tard par inadvertance. (Pour autant que vous ayez fait "use strict"; c'est-à-dire )

Ma question : Dans les moteurs JS modernes tels que V8, y a-t-il un avantage en termes de performances (par exemple, une recherche plus rapide des propriétés, une empreinte mémoire réduite) à verrouiller les objets en utilisant les méthodes ci-dessus ?

(Voir également La belle explication de John Resig - ne mentionne pas les performances, cependant).

0 votes

92voto

Jan Molak Points 606

Il y a eu aucune différence en matière de performances depuis au moins Chrome 47.0.2526.80 (64 bits).

Testing in Chrome 6.0.3359 on Mac OS 10.13.4
-----------------------------------------------
Test               Ops/sec
non-frozen object  106,825,468  ±1.08%  fastest
frozen object      106,176,323  ±1.04%  fastest

Test de performance (disponible sur http://jsperf.com/performance-frozen-object ) :

  const o1 = {a: 1};
  const o2 = {a: 1};

  Object.freeze(o2);

  // Non-frozen object:
  for(var key in o1);

  // Frozen object:
  for(var key in o2);

Mise à jour du 30.10.2019 : Il n'y a pas de différence de performance sur Chrome 78.0.3904 (64 bits)

Mise à jour 17.09.2019 : Il n'y a pas de différence de performance sur Chrome 76.0.3809 (64 bits)

Mise à jour 03.05.2018 : Il n'y a pas de différence de performance sur Chrome 66.0.3359 (64 bits)

Mise à jour 06.03.2017 : Il n'y a pas de différence de performance sur Chrome 56.0.2924 (64 bits)

Mise à jour 13.12.2015 : Il n'y a pas de différence de performance sur Chrome 47.0.2526.80 (64 bits)


Avec Chrome 34, les performances d'un objet gelé sont légèrement supérieures à celles d'un objet non gelé dans le scénario de test de @pimvdb (résultats ci-dessous). La différence ne semble toutefois pas suffisamment importante pour justifier l'utilisation de cette technique pour améliorer les performances.

http://jsperf.com/performance-frozen-object

Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test               Ops/sec
non-frozen object  105,250,353  ±0.41%  3% slower
frozen object      108,188,527  ±0.55%  fastest

L'exécution des cas de test de @kangax montre que les deux versions de l'objet fonctionnent à peu près de la même manière :

http://jsperf.com/performance-frozen-object-prop-access

Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test               Ops/sec
non-frozen object  832,133,923  ±0.26%  fastest
frozen object      832,501,726  ±0.28%  fastest

http://jsperf.com/http-jsperf-com-performance-frozen-object-instanceof

Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test               Ops/sec
non-frozen object  378,464,917  ±0.42%  fastest
frozen object      378,705,082  ±0.24%  fastest

0 votes

Votre réponse est bonne, je l'ai notée +1, mais vous auriez dû modifier la réponse maintenant dépréciée pour faire les choses correctement.

0 votes

Merci pour vos commentaires, @Nicocube. Je ne savais pas s'il valait mieux modifier une réponse obsolète ou en écrire une nouvelle. J'ai vu les deux approches utilisées sur stackoverflow, mais votre suggestion est logique.

0 votes

Vos liens vers jsperf sont cassés avec something went wrong Avez-vous une copie du code que vous avez testé pour votre demande ?

15voto

Raynos Points 82706

En théorie, le fait de geler un objet permet d'apporter des garanties plus fortes sur la forme d'un objet.

Cela signifie que la VM peut compacter la taille de la mémoire.

Cela signifie que la VM peut optimiser les recherches de propriétés dans la chaîne de prototypes.

Cela signifie que toute référence vivante est devenue non vivante parce que l'objet ne peut plus changer.

En pratique, les moteurs JavaScript ne font pas encore ces optimisations agressives.

1 votes

En pratique, dans la plupart des moteurs, il y a peu à gagner du point de vue de la mémoire pour un objet donné. De même, les recherches de propriétés à partir des prototypes sont déjà mises en cache (les performances de la plupart des build-ins seraient terribles si ce n'était pas le cas).

0 votes

C'est vrai. Vous devriez être en mesure d'avoir plus qu'un simple cache en ligne, car vous pouvez mettre en ligne la lecture entière puisque vous avez une valeur connue.

0 votes

(Notez que l'inlining ne permet de gagner qu'une certaine quantité : vous ne voulez pas inliner les chaînes de caractères, par exemple, bien que l'inlining des entiers/doubles soit quelque chose que vous voulez faire).

13voto

pimvdb Points 66332

Mise à jour : Depuis que cette réponse a été écrite à l'origine, le bug dans V8 qui a causé ce problème a été corrigé. Voir la réponse de Jan Molak pour plus d'informations.


Dans Google Chrome (c'est-à-dire dans la version V8), un objet figé itère 98% plus lent qu'un objet ordinaire.

http://jsperf.com/performance-frozen-object

Test name*              ops/sec

non-frozen object    32,193,471
frozen object           592,726

C'est probablement parce que ces fonctions sont relativement nouvelles et probablement pas encore optimisées (mais ce n'est qu'une supposition, je ne connais pas la raison).

Quoi qu'il en soit, je ne recommande vraiment pas de l'utiliser pour améliorer les performances, car cela n'a apparemment aucun sens.


* Le code pour le test est :

var o1 = {a: 1};
var o2 = {a: 1};

Object.freeze(o2);

Test 1 (objet non congelé) :

for(var key in o1);

Test 2 (objet congelé) :

for(var key in o2);

7 votes

Cela ressemble à un bug de la V8 plutôt qu'à quelque chose qui n'est pas optimisé. Note Clé d'objet est seulement 72% plus lent

3 votes

@Raynos : Bon point ; aussi Object.keys ne devrait pas être plus lent . Je suis d'accord pour dire qu'il s'agit plutôt d'un bogue, car le gel ne devrait pas nuire aux performances, bien au contraire.

1 votes

recherches dans le prototype sont également 94% plus lents :\N

2voto

Bardi Harborow Points 136

Conformément à la question du code Google :

La différence de performance est due à la structure de données du backing store. Pour quelques propriétés, le descripteur d'objet décrit l'endroit où les propriétés sont stockées, dans un tableau de propriétés. Si le nombre de propriétés propriétés augmente, nous passons éventuellement à un dictionnaire pour le backing pour le backing store, ce qui est moins performant, mais plus flexible. Lorsque nous gelons un objet, ce que l'on fait c'est que toutes les propriétés sont mises à non configurables et non réinscriptibles. Le stockage de ces attributs est seulement possible que dans un backing store de type dictionnaire, donc on passe à ça.

-1voto

jAndy Points 93076

La seule raison que je vois pour ces méthodes dans le code de production est que vous pouvez avoir des objets scellés ou gelés, à des fins d'intégrité.

Par exemple, j'écris une petite bibliothèque qui fonctionne très bien et vous offre un ensemble de méthodes dans un objet, mais je ne veux pas que vous changiez ou écrasiez une de mes propriétés ou méthodes. Je ne dis pas que je peux vous empêcher de le faire, mais je peux essayer d'empêcher que vous le fassiez par accident, ce qui est peut-être plus important.

De plus, ces méthodes sont faciles à "shimmer" dans un environnement qui ne les connaît pas, en retournant simplement l'objet original. Bien sûr, cela n'aurait alors aucun effet.

Je ne vois pas de raisons liées aux performances pour faire cela.

1 votes

Les objectifs d'intégrité sont les suivants développement

0 votes

@Raynos : Je vois l'utilité des bibliothèques de toute façon. Comme je l'ai dit, il s'agit plutôt de protéger l'intégrité des objets contre des modifications non souhaitées.

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