Les boucles sont - elles vraiment plus rapides à l'envers?

j'ai entendu ça plusieurs fois. Les boucles JavaScript sont-elles vraiment plus rapides quand on compte à rebours? Si oui, pourquoi? J'ai vu quelques exemples de suites de test montrant que les boucles inversées sont plus rapides, mais je n'arrive pas à trouver d'explication sur le pourquoi!

je suppose que c'est parce que la boucle n'a plus à évaluer une propriété chaque fois qu'elle vérifie si elle est terminée et qu'elle vérifie juste par rapport à la valeur numérique finale.

i. e.

for (var i = count - 1; i >= 0; i--)
{
  // count is only evaluated once and then the comparison is always on 0.
}
231
demandé sur Anders 2009-08-27 15:53:10

30 réponses

ce n'est pas que i-- soit plus rapide que i++ . En fait, ils sont tous les deux aussi rapides.

ce qui prend du temps dans les boucles ascendantes est d'évaluer, pour chaque i , la taille de votre tableau. Dans cette boucle:

for(var i = array.length; i--;)

vous évaluez .length une seule fois, lorsque vous déclarez i , alors que pour cette boucle

for(var i = 1; i <= array.length; i++)

vous évaluez .length chaque fois que vous incrémentez i , lorsque vous vérifiez si i <= array.length .

dans la plupart des cas, vous ne devrait même pas vous soucier de ce genre d'optimisation .

849
répondu alestanis 2015-12-30 00:59:14

Ce mec par rapport à beaucoup de boucles en javascript, dans beaucoup de navigateurs. Il a aussi une suite test donc vous pouvez les exécuter vous-même.

dans tous les cas (sauf si j'en ai oublié un dans ma lecture) la boucle la plus rapide était:

var i = arr.length; //or 10
while(i--)
{
  //...
}
188
répondu Tom Ritter 2017-07-13 14:08:41

j'essaie de donner une vue d'ensemble avec cette réponse.

les pensées suivantes entre parenthèses était ma croyance jusqu'à ce que je viens de tester la question:

[[En termes de faible niveau de langues comme C / C++ , le code est compilé, de sorte que le processeur a un saut conditionnel de commande lorsqu'une variable est nulle ou non nulle).

En outre, si vous vous souciez de cette optimisation , vous pouvez choisir ++i au lieu de i++ , parce que ++i est une commande de processeur unique tandis que i++ signifie j=i+1, i=j .]]

boucles vraiment rapides peut être fait en les déroulantâ:

for(i=800000;i>0;--i)
    do_it(i);

il peut être beaucoup plus lent que

for(i=800000;i>0;i-=8)
{
    do_it(i); do_it(i-1); do_it(i-2); ... do_it(i-7);
}

mais les raisons peuvent être assez compliquées (juste pour mentionner, il y a les questions de prétraitement de commande de processeur et de manipulation de cache dans le jeu).

en termes de langues de haut niveau , comme JavaScript comme vous l'avez demandé, Vous pouvez optimiser les choses si vous comptez sur les bibliothèques, les fonctions intégrées pour la boucle. Laissez-les décider de la meilleure façon de procéder.

par conséquent, en JavaScript, je suggère d'utiliser quelque chose comme

array.forEach(function(i) {
    do_it(i);
});

il est également moins sujet aux erreurs et les navigateurs ont une chance d'optimiser votre code.

[remarque: non seulement les navigateurs, mais vous aussi avez un espace pour optimiser facilement, il suffit de redéfinir la fonction forEach (navigateur dépendant) de sorte qu'il utilise la dernière meilleure supercherie! :) @A. M. K. dit que dans des cas particuliers, il vaut mieux utiliser array.pop ou array.shift . Si vous le faites, mettez-le derrière le rideau. Le Overkill extrême est d'ajouter options à forEach pour sélectionner l'algorithme de boucle.]

de plus, même pour les langues de bas niveau, la meilleure pratique est d'utiliser une fonction de bibliothèque intelligente pour des opérations complexes et en boucle si cela est possible.

ces bibliothèques peuvent aussi mettre des choses (multi-threaded) derrière votre dos et aussi les programmeurs spécialisés les tiennent à jour.

j'ai fait un peu plus d'examen et il s'avère que dans C / C++, même pour 5e9 = (50,000x100,000) opérations, il n'y a pas de différence entre monter et descendre si le test est fait contre une constante comme @alestanis dit. (Les résultats du JsPerf sont parfois incohérents, mais dans l'ensemble, ils sont les mêmes: on ne peut pas faire une grande différence.)

Donc --i se trouve être plutôt une chose" chic". Ça te donne l'air d'un meilleur programmeur. :)

d'autre part, pour-unrolling dans cette situation 5e9, il m'a fait descendre de 12 sec à 2,5 sec quand je suis passé par 10s, et à 2,1 sec quand je suis passé par 20s. C'était sans optimisation, et l'optimisation a ramené les choses à peu de temps Impossible à mesurer. :) (Déroulage peut être fait, à ma manière, au-dessus ou à l'aide de i++ , mais qui n'apporte pas les choses à l'avance en JavaScript. )

dans l'Ensemble: garder i-- / i++ et ++i / i++ différences pour les entrevues d'emploi, de bâton à array.forEach ou à d'autres fonctions de bibliothèque complexes lorsqu'elles sont disponibles. ;)

127
répondu Barnabas Szabolcs 2012-11-19 17:49:49

i-- est aussi rapide que i++

ce code ci-dessous est aussi rapide que le vôtre, mais utilise une variable supplémentaire:

var up = Things.length;
for (var i = 0; i < up; i++) {
    Things[i]
};

La recommandation est de ne PAS évaluer la taille du tableau à chaque fois. Pour les grands tableaux, on peut voir la dégradation des performances.

34
répondu sainiuc 2012-10-30 10:21:34

depuis, Vous êtes intéressé par le sujet, jetez un oeil à Greg Reimer's weblog post about a JavaScript loop benchmark, Quelle est la façon la plus rapide de coder une boucle en JavaScript? :

j'ai construit une suite de test de benchmarking de boucle pour différentes façons de coder les boucles en JavaScript. Il y en a déjà quelques-uns là-bas, mais je n'en ai trouvé aucun qui reconnaissait la différence entre les tableaux natifs et Collections HTML.

vous pouvez également faire un test de performance sur une boucle en ouvrant https://blogs.oracle.com/greimer/resource/loop-test.html (ne fonctionne pas si JavaScript est bloqué dans le navigateur par, par exemple, NoScript ).

EDIT:

un benchmark plus récent créé par Milan Adamovsky peut être exécuté dans le temps d'exécution ici pour différents navigateurs.

Pour un les Tests dans Firefox 17.0 sur Mac OS X 10.6 j'ai eu la boucle suivante:

var i, result = 0;
for (i = steps - 1; i; i--) {
  result += i;
}

comme le plus rapide précédé par:

var result = 0;
for (var i = steps - 1; i >= 0; i--) {
  result += i;
}

Benchmark example.

21
répondu dreamcrash 2014-01-15 03:47:26

Ce n'est pas le -- ou ++ , c'est l'opération de comparaison. Avec -- vous pouvez utiliser un Comparer avec 0, tandis qu'avec ++ vous devez le comparer avec la longueur. Sur le processeur, de comparer avec zéro est normalement disponible, tandis que comparer avec un entier fini nécessite une soustraction.

a++ < length

est en fait compilé comme

a++
test (a-length)

donc il prend plus de temps sur le processeur quand compiler.

19
répondu Dr BDO Adams 2012-11-19 17:37:02

réponse Courte

pour le code normal, en particulier dans un langage de haut niveau comme JavaScript , il n'y a pas de différence de performance dans i++ et i-- .

le critère de performance est l'utilisation dans la boucle for et l'énoncé comparer .

ce s'applique à toutes les langues de haut niveau et est principalement indépendant de l'utilisation de JavaScript. L'explication est le code assembleur résultant à la ligne de fond.

explication détaillée

Une différence de performance peut se produire dans une boucle. Le fond est que sur le code assembleur niveau, vous pouvez voir qu'un compare with 0 est juste une déclaration qui n'a pas besoin d'un registre supplémentaire.

Cette comparaison est émis à chaque passage de la boucle et peut entraîner une amélioration mesurable du rendement.

for(var i = array.length; i--; )

sera évalué à un pseudo code comme ceci:

 i=array.length
 :LOOP_START
 decrement i
 if [ i = 0 ] goto :LOOP_END
 ... BODY_CODE
 :LOOP_END

noter que 0 est une valeur littérale, ou en d'autres termes, une valeur constante.

for(var i = 0 ; i < array.length; i++ )

sera évalué à un pseudo code comme ceci (optimisation normale de l'interpréteur supposée):

 end=array.length
 i=0
 :LOOP_START
 if [ i < end ] goto :LOOP_END
 increment i
 ... BODY_CODE
 :LOOP_END

Note que end est une variable qui nécessite un CPU registre. Cela peut nécessiter un échange de Registre supplémentaire dans le code et nécessite un état de comparaison plus coûteux dans l'état if .

Juste mon 5 cents

pour un langage de haut niveau, la lisibilité, qui facilite la maintenabilité, est plus importante comme une performance mineure amélioration.

Normalement le classique itération du tableau du début à la fin est mieux.

l'itération la plus rapide à partir du tableau end to start résulte dans la séquence inversée éventuellement non désirée.

Post scriptum

Comme demandé dans un commentaire: "La différence de --i et i-- est dans l'évaluation de i avant ou après la décrémentation.

la meilleure explication est de l'essayer ;-) voici un exemple Bash .

 % i=10; echo "$((--i)) --> $i"
 9 --> 9
 % i=10; echo "$((i--)) --> $i"
 10 --> 9
16
répondu H.-Dirk Schmitt 2012-11-19 18:14:02

j'ai vu la même recommandation dans le texte Sublime 2.

comme il a déjà été dit, la principale amélioration n'est pas d'évaluer la longueur du tableau à chaque itération de la boucle for. C'est une technique d'optimisation bien connue et particulièrement efficace en JavaScript lorsque le tableau fait partie du document HTML (faire un for pour tous les éléments li ).

par exemple,

for (var i = 0; i < document.getElementsByTagName('li').length; i++)

est beaucoup plus lent que

for (var i = 0, len = document.getElementsByTagName('li').length; i < len; i++)

de là où je me trouve, la principale amélioration dans la forme dans votre question Est le fait qu'il ne déclare pas une variable supplémentaire ( len dans mon exemple)

mais si vous me demandez, le point entier n'est pas sur l'optimisation i++ vs i-- , mais sur le fait de ne pas avoir à évaluer la longueur du tableau à chaque itération (vous pouvez voir un test de référence sur jsperf ).

15
répondu BBog 2012-10-31 10:10:02

Je ne pense pas qu'il soit logique de dire que i-- est plus rapide que i++ en JavaScript.

tout D'abord , cela dépend totalement de L'implémentation du moteur JavaScript.

Deuxièmement , à condition que les constructions les plus simples JIT'ED et traduit en instructions natives, alors i++ vs i-- dépendra totalement du CPU qui l'exécute. C'est, sur le Bras (mobile phones) il est plus rapide de descendre à 0 depuis décrément et comparer à zéro sont exécutés dans une seule instruction.

probablement, vous avez pensé que l'un était plus faible que l'autre parce que la voie suggérée est

for(var i = array.length; i--; )

mais la voie suggérée n'est pas parce que l'un plus rapide que l'autre, mais simplement parce que si vous écrivez

for(var i = 0; i < array.length; i++)

puis sur chaque itération array.length a dû être évalué (Smart JavaScript engine peut-être pourrait comprendre que la boucle ne changera pas la longueur du tableau). Même s'il ressemble à une simple déclaration, c'est en fait une fonction qui est appelée sous le capot, le moteur JavaScript.

l'autre raison pour laquelle i-- pourrait être considéré comme" plus rapide "est parce que le moteur JavaScript a besoin d'allouer une seule variable interne pour contrôler la boucle (variable à la var i ). Si vous avez par rapport à la matrice.longueur ou à une autre variable alors il fallait être plus d'une variable interne pour contrôler la boucle, et le nombre de variables internes sont une ressource limitée d'un moteur JavaScript. Moins il y a de variables utilisées dans une boucle, plus JIT a de chance d'être optimisé. C'est pourquoi i-- pourrait être considéré plus rapide...

14
répondu Pavel 2013-02-08 19:54:14

comme aucune des autres réponses ne semble répondre à votre question spécifique (plus de la moitié d'entre elles montrent des exemples C et discutent de langues de niveau inférieur, votre question Est pour JavaScript) j'ai décidé d'écrire la mienne.

alors, voilà:

réponse Simple: i-- est généralement plus rapide parce qu'il ne doit pas exécuter une comparaison à 0 chaque fois qu'il exécute, les résultats des tests sur diverses méthodes sont ci-dessous:

résultat du Test: Comme "prouvé" par ce jsPerf, arr.pop() est en fait le plus rapide de la boucle de loin. Mais, en se concentrant sur --i , i-- , i++ et ++i comme vous l'avez demandé dans votre question, voici jsPerf (ils sont de plusieurs jsPerf, s'il vous plaît voir les sources ci-dessous) résultats résumés:

--i et i-- sont les mêmes dans Firefox alors que i-- est plus rapide dans google Chrome.

dans Chrome un basic pour boucle ( for (var i = 0; i < arr.length; i++) ) est plus rapide que i-- et --i tandis que dans Firefox il est plus lent.

dans les deux Chrome et Firefox a caché arr.length est beaucoup plus rapide avec Chrome en avant d'environ 170 000 ops/sec.

sans différence significative, ++i est plus rapide que i++ dans la plupart des navigateurs, AFAIK, ce n'est jamais le contraire dans n'importe quel navigateur.

résumé plus court: arr.pop() est de loin la boucle la plus rapide; pour les boucles spécifiquement mentionnées, i-- est la boucle la plus rapide.

Sources: http://jsperf.com/fastest-array-loops-in-javascript/15 , http://jsperf.com/ipp-vs-ppi-2

j'espère que cela répondra à votre question.

14
répondu A.M.K 2014-11-25 19:50:16

cela dépend de l'emplacement de votre tableau dans la mémoire et du nombre de pages de mémoire que vous frappez pendant que vous accédez à ce tableau.

dans certains cas, accéder aux membres du tableau dans l'ordre des colonnes est plus rapide que l'ordre des lignes en raison de l'augmentation du taux de succès.

13
répondu Akbar Bayati 2012-12-12 12:55:47

la dernière fois que je m'en suis soucié c'était en écrivant 6502 assembly (8-bit, yeah!). Le grand gain est que la plupart des opérations arithmétiques (en particulier les décréments) mis à jour un ensemble de drapeaux, l'un d'entre eux était Z , l'indicateur "atteint zéro".

donc, à la fin de la boucle vous avez juste fait deux instructions: DEC (décrément) et JNZ (saut si pas zéro), aucune comparaison nécessaire!

11
répondu Javier 2012-11-19 17:55:16

pour couper court: il n'y a absolument aucune différence dans le JavaScript.

tout d'Abord, vous pouvez tester vous-même:

non seulement pouvez-vous tester et exécuter n'importe quel script dans n'importe quelle bibliothèque JavaScript, mais vous avez également accès à l'ensemble des scripts précédemment écrits, ainsi que la capacité de voir des différences entre le temps d'exécution dans différents navigateurs sur différentes plates-formes.

autant que vous pouvez voir, il n'y a pas de différence entre les performances dans n'importe quel environnement.

si vous voulez améliorer la performance de votre script, des choses que vous pouvez essayer de faire:

  1. avoir une déclaration var a = array.length; de sorte que vous ne serez pas calculer sa valeur à chaque fois dans la boucle
  2. Ne déroulement de la boucle http://en.wikipedia.org/wiki/Loop_unwinding

mais vous devez comprendre que l'amélioration que vous pouvez obtenir sera si insignifiante, que la plupart du temps vous ne devriez même pas vous soucier de lui.

ma propre opinion pourquoi une telle idée fausse (Dec vs Inc) est apparu

il y a très longtemps, il y avait une instruction machine commune, DSZ (décrément et sautez sur zéro). Les personnes qui ont programmé en langage assembleur ont utilisé cette instruction pour implémenter des boucles afin de sauvegarder un registre. Maintenant, ces anciens faits sont obsolètes, et je suis presque sûr que vous n'obtiendrez aucune amélioration de performance dans n'importe quelle langue en utilisant cette pseudo amélioration.

je pense que la seule façon qu'une telle connaissance peut propager dans notre temps est quand vous lisez le code d'une autre personne. Voyez une telle construction et demandez pourquoi elle a été mise en œuvre et voici la réponse: "elle améliore les performances parce qu'elle se compare à zéro". Vous avez été déconcerté par la connaissance supérieure de votre collègue et pensez à l'utiliser pour être beaucoup plus intelligent: -)

8
répondu Salvador Dali 2012-11-19 18:04:47

il peut être expliqué par JavaScript (et toutes les langues) éventuellement être transformé en opcodes pour fonctionner sur le CPU. Les CPU ont toujours une seule instruction pour comparer à zéro, ce qui est sacrément rapide.

en aparté, si vous pouvez garantir count est toujours >= 0 , vous pouvez simplifier:

for (var i = count; i--;)
{
  // whatever
}
7
répondu searlea 2009-08-27 11:58:14

cela ne dépend pas du signe -- ou ++ , mais cela dépend des conditions que vous appliquez dans la boucle.

par exemple: votre boucle est plus rapide si la variable a une valeur statique que si vos conditions de vérification de boucle à chaque fois, comme la longueur d'un tableau ou d'autres conditions.

mais ne vous inquiétez pas de cette optimisation, car cette fois son effet est mesuré en nanosecondes.

7
répondu Arvind Kanjariya 2012-11-19 17:52:06

for(var i = array.length; i--; ) n'est pas beaucoup plus rapide. Mais quand vous remplacez array.length par super_puper_function() , cela peut être de manière significative plus rapide (car il est appelé dans chaque itération). C'est toute la différence.

Si vous allez changer en 2014, vous n'avez pas besoin de penser à l'optimisation. Si vous allez changer avec "Rechercher & Remplacer", vous n'avez pas besoin de penser à l'optimisation. Si vous n'avez pas le temps, vous n'avez pas besoin de penser à l'optimisation. Mais maintenant, vous avez le temps de réfléchir.

P. S.: i-- n'est pas plus rapide que i++ .

7
répondu Dmitry Isaev 2012-11-19 17:53:57

apporter parfois des changements très mineurs à la façon dont nous écrivons notre code peut faire une grande différence à la vitesse à laquelle notre code tourne réellement. Une zone où un changement de code mineur peut faire une grande différence dans les temps d'exécution est celle où nous avons une boucle for qui traite un tableau. Lorsque le tableau est composé d'éléments sur la page web (comme les boutons radio), le changement a l'effet le plus important, mais il vaut quand même la peine d'appliquer ce changement même si le tableau est interne au code Javascript.

la méthode conventionnelle de codage A pour boucle pour traiter un tableau lis comme ceci:

for (var i = 0; i < myArray.length; i++) {...

le problème avec ceci est que l'évaluation de la longueur du tableau en utilisant myArray.longueur prend du temps et de la manière dont nous avons codé la boucle signifie que cette évaluation doit être effectuée à chaque fois autour de la boucle. Si le tableau contient 1000 éléments alors la longueur du tableau sera évaluée 1001 fois. Si on regardait des boutons radio et qu'on avait myForm.myButtons.longueur alors il faudra encore plus de temps pour évaluer puisque le groupe approprié de boutons dans la forme spécifiée doit d'abord être localisé avant que la longueur puisse être évaluée à chaque fois autour de la boucle.

évidemment, nous ne nous attendons pas à ce que la longueur du tableau change pendant que nous le traitons, donc tous ces recalculs de la longueur ne font qu'ajouter inutilement au temps de traitement. (Bien sûr si vous avez du code à l'intérieur de la boucle qui ajoute ou supprime le tableau les entrées alors la taille du tableau peut changer entre les itérations et donc nous ne pouvons pas changer le code qui teste pour elle)

Ce que nous pouvons faire pour corriger ce pour une boucle où la taille est fixe est d'évaluer la longueur une fois au début de la boucle et de l'enregistrer dans une variable. Nous pouvons ensuite tester la variable pour décider quand arrêter la boucle. Ceci est beaucoup plus rapide que l'évaluation de la longueur du tableau à chaque fois en particulier quand le tableau contient plus que quelques entrées ou fait partie de la page web.

le code pour faire ceci est:

for (var i = 0, var j = myArray.length; i < j; i++) {...

donc maintenant nous n'évaluons la taille du tableau qu'une seule fois et nous testons notre compteur de boucle par rapport à la variable qui tient cette valeur à chaque fois autour de la boucle. Cette variable supplémentaire peut être accédée beaucoup plus rapidement que l'évaluation de la taille du tableau et donc notre code fonctionnera beaucoup plus vite qu'avant. Nous avons juste une variable supplémentaire dans notre script.

souvent, peu importe l'ordre nous avons procédé de la matrice en tant que toutes les entrées dans le tableau traités. Dans ce cas, nous pouvons rendre notre code légèrement plus rapide en supprimant la variable supplémentaire que nous venons d'ajouter et en traitant le tableau dans l'ordre inverse.

le code final qui traite notre réseau de la manière la plus efficace possible est:

for (var i = myArray.length-1; i > -1; i--) {...

ce code n'évalue toujours la taille du tableau qu'une seule fois au début mais au lieu de comparer la boucle compteur avec une variable de nous comparer avec une constante. Depuis une constante est encore plus efficace pour accéder à une variable et depuis nous avons, moins une instruction d'affectation qu'avant notre troisième version du code est maintenant légèrement plus efficace que la deuxième version et beaucoup plus efficace que la première.

5
répondu Sid 2012-10-31 06:52:08

j'ai fait un comparaison sur jsbench .

comme alestani l'a souligné, une chose qui prend du temps dans les boucles ascendantes, est d'évaluer, pour chaque itération, la taille de votre tableau. Dans cette boucle:

for ( var i = 1; i <= array.length; i++ )

vous évaluez .length chaque fois que vous incrémentez i . Dans celui-ci:

for ( var i = 1, l = array.length; i <= l; i++ )

vous évaluez .length une seule fois, lorsque vous déclarez i . Dans celui-ci:

for ( var i = array.length; i--; )

la comparaison est implicite, elle intervient juste avant la décrémentation de i , et le code est très lisible. Cependant, ce qui peut faire une énorme différence, c'est ce que vous mettez dans la boucle.

boucle avec appel à la fonction (définie ailleurs):

for (i = values.length; i-- ;) {
  add( values[i] );
}

boucle avec code inlined:

var sum = 0;
for ( i = values.length; i-- ;) {
  sum += values[i];
}

si vous pouvez inline votre code, au lieu d'appeler une fonction, sans sacrifier la lisibilité, vous pouvez avoir une boucle d'un ordre de grandeur plus rapide!


Note : comme le navigateur sont devenant bon à la lining fonctions simples, il dépend vraiment de la façon dont Complexe votre code est. Donc, profil avant d'optimiser, parce que

  1. le goulot d'étranglement peut être ailleurs (ajax, reflow, ...)
  2. , Vous pouvez choisir un meilleur algorithme
  3. vous pouvez choisir une meilleure structure de données

mais rappelez-vous:

Code est écrit pour les gens à lire, et seulement accessoirement pour les machines à exécuter.

5
répondu Spyryto 2017-10-23 12:57:11

la façon dont vous le faites maintenant n'est pas plus rapide (à part que c'est une boucle indéfinie, je suppose que vous vouliez faire i-- .

Si vous voulez le rendre plus rapide à faire:

for (i = 10; i--;) {
    //super fast loop
}

bien sûr, vous ne le remarqueriez pas sur une si petite boucle. La raison pour laquelle il est plus rapide est parce que vous décrémentez I tout en vérifiant qu'il est "vrai" (il évalue à "faux" quand il atteint 0)

4
répondu peirix 2009-08-27 11:57:44

dans de nombreux cas, cela n'a essentiellement rien à voir avec le fait que les processeurs peuvent comparer à zéro plus rapidement que d'autres comparaisons.

c'est parce que seuls quelques moteurs Javascript (ceux de la liste JIT) génèrent effectivement du code de langage machine.

la plupart des moteurs Javascript construisent une représentation interne du code source qu'ils interprètent ensuite (pour avoir une idée de ce que c'est, Regardez près de le fond de cette page sur Firefox SpiderMonkey ). En général, si un morceau de code fait pratiquement la même chose mais conduit à une représentation interne plus simple, il s'exécute plus rapidement.

garder à l'esprit qu'avec des tâches simples comme ajouter/soustraire une variable d'une variable, ou comparer une variable à quelque chose, le plafond de l'interprète passant d'une "instruction" interne à l'autre est assez élevé, de sorte que les moins "instructions" qui sont utilisées en interne par le moteur JS, le mieux c'est.

3
répondu Artelius 2009-10-08 08:36:26

Eh bien, je ne sais pas à propos de JavaScript, il devrait vraiment s'agir d'une question de réévaluation de la longueur du tableau et peut-être quelque chose à voir avec les tableaux associatifs (si vous ne faites que décrémenter, il est peu probable que de nouvelles entrées devraient être attribuées - si le tableau est dense, c'est-à-dire. quelqu'un peut optimiser pour cela).

en assemblage bas niveau, il y a une instruction en boucle, appelée DJNZ (décrément et saut si non-zéro). Donc le décrément et le saut sont tous dans une instruction, ce qui le rend peut-être un peu plus rapide que INC et JL / JB (increment, jump si moins que / jump Si ci-dessous). De plus, comparer par rapport à zéro est plus simple que comparer par rapport à un autre nombre. Mais tout cela est vraiment marginal et dépend également de l'architecture cible (pourrait faire la différence, par exemple sur bras dans un smartphone).

Je ne m'attendais pas à ce que ces différences de bas niveau aient un si grand impact sur les langues interprétées, Je n'ai juste pas vu DJNZ parmi les réponses donc j'ai pensé que je partagerait une pensée intéressante.

3
répondu the swine 2012-10-30 12:54:06

Il utilisé pour dire que --j'ai été plus rapide (en C++) car il n'existe qu'un seul résultat, la valeur décrémentée. i -- doit stocker la valeur décrémentée à i et aussi conserver la valeur originale comme résultat (j = i--;). Dans la plupart des compilateurs, cela a utilisé deux registres plutôt qu'un qui pourrait causer une autre variable d'avoir à être écrite à la mémoire plutôt que conservée comme une variable de registre.

je suis d'accord avec les autres qui ont dit ça ne fait aucune différence de nos jours.

3
répondu Ant 2012-10-30 18:09:18

en termes très simples

"je-- et j'++. En fait, les deux prennent le même temps".

mais dans ce cas, quand vous avez une opération progressive.. processeur évaluer le .Longueur chaque variable de temps est incrémentée de 1 et en cas de décrément.. en particulier dans ce cas, il va évaluer .longueur qu'une seule fois jusqu'à ce que nous obtenons 0.

3
répondu Ravi_Parmar 2012-10-31 11:00:14

++ vs. -- n'a pas d'importance parce que JavaScript est un langage interprété, pas un langage compilé. Chaque instruction se traduit par plus d'un langage machine et vous ne devriez pas vous soucier de l'détails sanglants.

les personnes qui parlent d'utiliser -- (ou ++ ) pour faire un usage efficace des instructions d'assemblage se trompent. Ces instructions s'appliquent à l'arithmétique entière et il n'y a aucun entier dans JavaScript, juste les numéros .

vous devez écrire le code lisible.

3
répondu Salman A 2012-10-31 13:42:47

Première", 151940920" et i-- prendre exactement la même heure sur n'importe quel langage de programmation, y compris le code JavaScript.

le code suivant prend un temps très différent.

Fast:

for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };

Lente:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

par conséquent le code suivant prend aussi du temps différent.

Fast:

for (var i = Things.length - 1; i >= 0; i--) { Things[i] };

Lente:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

P.S. Slow est lent seulement pour quelques langues (moteurs JavaScript) en raison de l'optimisation du compilateur. La meilleure façon est d'utiliser '<' à la place de '<=' (ou '=') et '--i' à la place de 'i--' .

3
répondu Dmitry 2012-11-17 23:39:25

Pas beaucoup de temps est consommé par je-ou i++. Si vous allez profondément à l'intérieur de l'architecture CPU le ++ est plus rapide que le -- , puisque l'opération -- fera le complément du 2, mais il se produit à l'intérieur du matériel de sorte que cela le rendra rapide et aucune différence majeure entre le ++ et -- aussi ces opérations sont considérées du moins de temps consommé dans le CPU.

le pour boucle court comme ceci:

  • initialiser la variable une fois au début.
  • vérifier la contrainte dans le deuxième opérande de la boucle, < , > , <= , etc.
  • ensuite appliquer la boucle.
  • incrémenter la boucle et boucle encore jeter ces processus à nouveau.

,

for (var i = Things.length - 1; i >= 0; i--) {
    Things[i]
}; 

sera calculer la longueur du tableau qu'une seule fois au début et ce n'est pas beaucoup de temps, mais

for(var i = array.length; i--; ) 

calculera la longueur à chaque boucle, il faudra donc beaucoup de temps.

3
répondu Omar Freewan 2012-11-19 18:10:27

la meilleure façon de répondre à ce genre de question Est de l'essayer. Mettre en place une boucle qui compte un million d'itérations ou peu importe, et le faire dans les deux sens. Chronométrer les deux boucles et comparer les résultats.

La réponse dépendra probablement du navigateur que vous utilisez. Certains auront des résultats différents des autres.

1
répondu Greg Hewgill 2009-08-27 11:58:44

l'Amour, beaucoup de marques, mais aucune réponse :D

simplement mettre une comparaison contre Zéro est toujours la comparaison la plus rapide

donc (a = = 0) est en fait plus rapide à retourner vrai que (a = = 5)

c'est petit et insignifiant et avec 100 millions de rangées dans une collection c'est mesurable.

I. sur une boucle, vous pourriez dire où i < = array.la longueur et l'incrémentation de i

on une boucle vers le bas que vous pourriez être en train de dire où i >= 0 et être en train de décrémenter i à la place.

La comparaison est plus rapide. Pas la 'direction' de la boucle.

1
répondu Robert 2009-08-27 12:08:46

AIDEZ LES AUTRES À ÉVITER LES MAUX DE TÊTE --- VOTEZ CECI!!!

la réponse la plus populaire sur cette page ne fonctionne pas pour Firefox 14 et ne passe pas le jsLinter. "alors que les" boucles besoin d'un opérateur de comparaison, pas une cession. Il fonctionne sur chrome, safari, et même ie. Mais meurt dans firefox.

C'EST CASSÉ!

var i = arr.length; //or 10
while(i--)
{
  //...
}

ÇA VA MARCHER! (travaux sur firefox, passe le jsLinter)

var i = arr.length; //or 10
while(i>-1)
{
  //...
  i = i - 1;
}
1
répondu mrbinky3000 2012-08-17 17:43:44

c'est juste une supposition, mais c'est peut-être parce que c'est plus facile pour le processeur de comparer quelque chose avec 0 ( i >= 0 ) plutôt qu'avec une autre valeur ( i < Things.longueur.)

1
répondu Rorchackh 2012-10-30 10:13:01