127 votes

v8 Implications pour les performances JavaScript de const, let et var?

Indépendamment des différences fonctionnelles, le fait d'utiliser les nouveaux mots clés 'laisser' et 'const' ont aucune généralisée ou spécifique de l'impact sur les performances par rapport à 'var'?

Après l'exécution du programme:

function timeit(f, N, S) {
    var start, timeTaken;
    var stats = {min: 1e50, max: 0, N: 0, sum: 0, sqsum: 0};
    var i;
    for (i = 0; i < S; ++i) {
        start = Date.now();
        f(N);
        timeTaken = Date.now() - start;

        stats.min = Math.min(timeTaken, stats.min);
        stats.max = Math.max(timeTaken, stats.max);
        stats.sum += timeTaken;
        stats.sqsum += timeTaken * timeTaken;
        stats.N++
    }

    var mean = stats.sum / stats.N;
    var sqmean = stats.sqsum / stats.N;

    return {min: stats.min, max: stats.max, mean: mean, spread: Math.sqrt(sqmean - mean * mean)};
}

var variable1 = 10;
var variable2 = 10;
var variable3 = 10;
var variable4 = 10;
var variable5 = 10;
var variable6 = 10;
var variable7 = 10;
var variable8 = 10;
var variable9 = 10;
var variable10 = 10;

function varAccess(N) {
    var i, sum;
    for (i = 0; i < N; ++i) {
        sum += variable1;
        sum += variable2;
        sum += variable3;
        sum += variable4;
        sum += variable5;
        sum += variable6;
        sum += variable7;
        sum += variable8;
        sum += variable9;
        sum += variable10;
    }
    return sum;
}

const constant1 = 10;
const constant2 = 10;
const constant3 = 10;
const constant4 = 10;
const constant5 = 10;
const constant6 = 10;
const constant7 = 10;
const constant8 = 10;
const constant9 = 10;
const constant10 = 10;

function constAccess(N) {
    var i, sum;
    for (i = 0; i < N; ++i) {
        sum += constant1;
        sum += constant2;
        sum += constant3;
        sum += constant4;
        sum += constant5;
        sum += constant6;
        sum += constant7;
        sum += constant8;
        sum += constant9;
        sum += constant10;
    }
    return sum;
}


function control(N) {
    var i, sum;
    for (i = 0; i < N; ++i) {
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
    }
    return sum;
}

console.log("ctl = " + JSON.stringify(timeit(control, 10000000, 50)));
console.log("con = " + JSON.stringify(timeit(constAccess, 10000000, 50)));
console.log("var = " + JSON.stringify(timeit(varAccess, 10000000, 50)));

.. Mes résultats étaient les suivants:

ctl = {"min":101,"max":117,"mean":108.34,"spread":4.145407097016924}
con = {"min":107,"max":572,"mean":435.7,"spread":169.4998820058587}
var = {"min":103,"max":608,"mean":439.82,"spread":176.44417700791374}

Cependant la discussion comme indiqué ici semble indiquer un réel potentiel pour les différences de performances selon certains scénarios: https://esdiscuss.org/topic/performance-concern-with-let-const

172voto

T.J. Crowder Points 285826

TL;DR

En théorie, un unoptimized version de cette boucle:

for (let i = 0; i < 500; ++i) {
    doSomethingWith(i);
}

serait plus lent qu'un unoptimized version de la même boucle avec var:

for (var i = 0; i < 500; ++i) {
    doSomethingWith(i);
}

en raison d'un différent i variable est créée pour chaque itération de boucle avec let, alors qu'il n'y a qu'un i avec var.

Dans la pratique, ici à 2018, le V8 n'a assez d'introspection de la boucle de savoir quand il peut optimiser la différence de distance. (Avant même alors, les chances sont de votre boucle était en train de faire assez de travail que les autres let-frais généraux connexes a été lavé de toute façon. Mais maintenant, vous n'avez même pas à vous inquiéter à ce sujet.)

Détails

La différence importante entre var et let en for boucle est qu'un autre i est créé pour chaque itération; il s'adresse à la classique "fermetures de boucle" problème:

function usingVar() {
  for (var i = 0; i < 3; ++i) {
    setTimeout(function() {
      console.log("var's i: " + i);
    }, 0);
  }
}
function usingLet() {
  for (let i = 0; i < 3; ++i) {
    setTimeout(function() {
      console.log("let's i: " + i);
    }, 0);
  }
}
usingVar();
setTimeout(usingLet, 20);

La création de la nouvelle EnvironmentRecord pour chaque corps de boucle (spec lien) c'est le travail, et le travail prend du temps, c'est pourquoi, en théorie, l' let version est plus lente que l' var version.

Mais la différence n'questions si vous créez une fonction (la fermeture) à l'intérieur de la boucle qui utilise i, comme je l'ai fait dans cet extrait de code exécutable exemple ci-dessus. Sinon, la distinction ne peut pas être observée et peut être optimisé à l'écart.

Ici à 2018, il ressemble à la V8 (et SpiderMonkey dans Firefox) est en train de faire suffisamment d'introspection qu'il n'y a pas de coût de performance dans une boucle qui ne fait pas usage de l' let's variable par itération de la sémantique. Voir ce jsPerf test.


Dans certains cas, const peut constituer une opportunité pour l'optimisation de la var ne serait pas, en particulier pour les variables globales.

Le problème avec une variable globale, c'est que c'est, eh bien, mondiale; aucun code n'importe où pourraient y avoir accès. Donc, si vous déclarez une variable var que vous n'avez jamais l'intention de changer (et ne jamais faire de changement dans votre code), le moteur ne peut pas supposer qu'il ne va pas changer le résultat de code chargé ultérieures ou similaires.

Avec const, bien que, vous avez indiquez explicitement le moteur que la valeur ne peut pas climatique1. Il est donc libre de faire tout d'optimisation qu'il veut, y compris en émettant un littéral au lieu d'une variable de référence code de l'utiliser, sachant que les valeurs ne peuvent pas être modifiés.

1 Rappelez-vous que avec des objets, la valeur est une référence à l'objet et non l'objet lui-même. Donc, avec const o = {}, vous pouvez modifier l'état de l'objet (o.answer = 42), mais vous ne pouvez pas faire d' o point à un nouvel objet (car cela nécessiterait de modifier la référence de l'objet qu'il contient).


Lors de l'utilisation d' let ou const autres vardes situations, ils ne sont pas susceptibles d'avoir des performances différentes. Cette fonction doit avoir exactement le même rendement que vous utilisez var ou let, par exemple:

function foo() {
    var i = 0;
    while (Math.random() < 0.5) {
        ++i;
    }
    return i;
}

C'est tout, bien sûr, rare à la matière et à quelque chose à vous soucier seulement si et quand il y a un vrai problème à résoudre.

29voto

Amn Points 1

"LET" EST MIEUX DANS LES DÉCLARATIONS EN BOUCLE

Avec un simple test (5 fois) dans le navigateur comme ça:

 // WITH VAR
console.log(new Date().getTime());
for(var i = 0; i < 500000; i++){}
console.log(new Date().getTime())
 

Le temps moyen d'exécution est plus de 2.5ms

 // WITH LET
console.log(new Date().getTime());
for(let i = 0; i < 500000; i++){}
console.log(new Date().getTime())
 

Le temps moyen d'exécution est plus que 1.5ms

J'ai trouvé que le temps de boucle avec let est meilleur.

11voto

isaacdre Points 406

T. J. Crowder's réponse est donc excellente.

Voici un ajout de: "Quand dois-je obtenir la plupart de coup pour mon buck sur l'édition existant var déclarations de const ?"

J'ai trouvé que la plupart des boost de performance de a à faire avec "exporté" des fonctions.

Donc, si le fichier A, B, R, et Z appellent un "utilitaire" de la fonction dans le fichier de U qui est couramment utilisé par votre application, puis en passant que la fonction d'utilité sur "const" et le fichier parent référence à un const peut eak certains amélioration de la performance. Il semble que pour moi, il n'était pas sensiblement plus rapide, mais l'ensemble de la consommation de mémoire a été réduit d'environ 1% à 3% pour mon grossièrement monolithique Frankenstein-ed app. Si vous êtes à la dépenses de les sacs de caisse dans le cloud ou votre baremetal serveur, pourrait être une bonne raison de passer 30 minutes à passer au peigne fin et de mettre à jour certains de ceux var déclarations de const.

Je me rends compte que si vous lisez comment const, var, et de laisser le travail sous les couvertures que vous avez probablement déjà conclu ci-dessus... mais dans le cas où vous "jeté un coup d'oeil": D.

À partir de ce que je me souviens de l'analyse comparative sur le nœud v8.12.0, quand je faisais la mise à jour, mon appli est passé de l'inactivité de la consommation de ~240 mo de RAM pour ~233MB de RAM.

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