J'ai entendu cela plusieurs fois. Les boucles JavaScript sont-elles vraiment plus rapides lors du comptage à rebours? Si oui, pourquoi? J'ai vu quelques exemples de suite de tests montrant que les boucles inversées sont plus rapides, mais je ne trouve aucune explication sur 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 simplement la valeur numérique finale.
C'est à dire
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
for
boucle en arrière est plus rapide car la variable de contrôle de boucle de limite supérieure (hehe, borne inférieure) n'a pas besoin d'être définie ou extraite d'un objet; c'est un zéro constant.Réponses:
Ce n'est pas que
i--
c'est plus rapide quei++
. En fait, ils sont tous deux aussi rapides.Ce qui prend du temps dans les boucles ascendantes, c'est d'évaluer, pour chacune
i
, la taille de votre tableau. Dans cette boucle:Vous n'évaluez
.length
qu'une seule fois, lorsque vous déclarezi
, alors que pour cette bouclevous évaluez
.length
chaque fois que vous augmentezi
, lorsque vous vérifiez sii <= array.length
.Dans la plupart des cas, vous ne devriez même pas vous soucier de ce type d'optimisation .
la source
.length
un certain nombre de fois ou de déclarer et définir une nouvelle variable? Dans la plupart des cas, il s'agit d'une optimisation prématurée (et erronée), sauf si votrelength
évaluation est très coûteuse.0
est plus rapide à évaluer quearray.length
. Eh bien, soi-disant..length
soit en déclarationfor loop
ou non.Ce mec a comparé beaucoup de boucles en javascript, dans beaucoup de navigateurs. Il dispose également d'une suite de tests pour que vous puissiez les exécuter vous-même.
Dans tous les cas (sauf si j'en ai manqué un dans ma lecture), la boucle la plus rapide était:
la source
--i
alors vous devez utiliservar current = arr[i-1];
à l'intérieur de la boucle ou il sera éteint par un ...J'essaie de donner une vue d'ensemble avec cette réponse.
Les réflexions suivantes entre parenthèses étaient ma conviction jusqu'à ce que je viens de tester le problème récemment:
[[En termes de langages de bas niveau comme C / C ++ , le code est compilé de sorte que le processeur dispose d'une commande de saut conditionnel spéciale lorsqu'une variable est nulle (ou non nulle).
De plus, si vous vous souciez de cette optimisation, vous pouvez aller à la
++i
place dei++
, car il++i
s'agit d'une commande à processeur unique alors que celai++
signifiej=i+1, i=j
.]]Des boucles vraiment rapides peuvent être faites en les déroulant:
Cela peut être beaucoup plus lent que
mais les raisons peuvent être assez compliquées (juste pour mentionner, il y a les problèmes de prétraitement des commandes du processeur et de gestion du cache dans le jeu).
En termes de langages de haut niveau , comme JavaScript comme vous l'avez demandé, vous pouvez optimiser les choses si vous comptez sur des bibliothèques, des 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
Il est également moins sujet aux erreurs et les navigateurs ont la possibilité d'optimiser votre code.
[REMARQUE: non seulement les navigateurs, mais vous aussi avez un espace pour optimiser facilement, redéfinissez simplement la
forEach
fonction (en fonction du navigateur) afin qu'elle utilise la dernière supercherie! :) @AMK dit que dans des cas particuliers, il vaut mieux utiliserarray.pop
ouarray.shift
. Si vous faites cela, mettez-le derrière le rideau. Le plus exagéré est d'ajouter des optionsforEach
pour sélectionner l'algorithme de bouclage.]De plus, également pour les langages de bas niveau, la meilleure pratique consiste à utiliser une fonction de bibliothèque intelligente pour les opérations complexes en boucle si cela est possible.
Ces bibliothèques peuvent également mettre des choses (multithread) derrière votre dos et des programmeurs spécialisés les tiennent à jour.
J'ai fait un peu plus de contrôle et il s'avère qu'en C / C ++, même pour les opérations 5e9 = (50,000x100,000), il n'y a pas de différence entre monter et descendre si le test est effectué contre une constante comme @alestanis le dit. (Les résultats JsPerf sont parfois incohérents, mais en gros, ils disent la même chose: vous ne pouvez pas faire une grande différence.)
Il
--i
se trouve donc que c'est plutôt une chose "chic". Cela vous fait seulement ressembler à un meilleur programmeur. :)D'un autre côté, pour se dérouler dans cette situation de 5e9, cela m'a ramené de 12 secondes à 2,5 secondes quand je suis passé de 10 secondes, et à 2,1 secondes quand je suis allé de 20 secondes. C'était sans optimisation, et l'optimisation a réduit les choses à peu de temps. :) (Le déroulement peut être fait à ma façon ci-dessus ou en utilisant
i++
, mais cela ne fait pas avancer les choses en JavaScript.)Dans l'ensemble: conservez
i--
/i++
et++i
/ lesi++
différences dans les entretiens d'embauche, respectezarray.forEach
ou d'autres fonctions de bibliothèque complexes lorsqu'elles sont disponibles. ;)la source
array.each(...)
. Je ne pense pas qu'ils essaieraient d'expérimenter avec des boucles de boucles simples.+1
obtenez unGreat Answer
badge. Vraiment une excellente réponse. :)i--
est aussi rapide quei++
Ce code ci-dessous est aussi rapide que le vôtre, mais utilise une variable supplémentaire:
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.
la source
for (var i=0, up=Things.length; i<up; i++) {}
Depuis, vous êtes intéressé par le sujet, jetez un œil au billet de blog de Greg Reimer sur un benchmark de boucle JavaScript, Quel est le moyen le plus rapide de coder une boucle en JavaScript? :
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 ).ÉDITER:
Un benchmark plus récent créé par Milan Adamovsky peut être exécuté au moment de l'exécution ici au pour différents navigateurs.
Pour un test dans Firefox 17.0 sur Mac OS X 10.6 j'ai obtenu la boucle suivante:
comme le plus rapide précédé de:
la source
Ce n'est pas le
--
ou++
, c'est l'opération de comparaison. Avec,--
vous pouvez utiliser une comparaison avec 0, tandis qu'avec,++
vous devez la comparer avec la longueur. Sur le processeur, la comparaison avec zéro est normalement disponible, tandis que la comparaison avec un entier fini nécessite une soustraction.a++ < length
est en fait compilé comme
Cela prend donc plus de temps au processeur lors de la compilation.
la source
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 performances dans
i++
eti--
.Le critère de performance est l'utilisation dans la
for
boucle et l' instruction compare .Cela s'applique à tous les langages de haut niveau et est principalement indépendant de l'utilisation de JavaScript. L'explication est le code assembleur résultant en bout de ligne.
Explication détaillée
Une différence de performances peut se produire dans une boucle. L'arrière-plan est qu'au niveau du code assembleur , vous pouvez voir que a
compare with 0
n'est qu'une instruction qui n'a pas besoin d'un registre supplémentaire.Cette comparaison est émise à chaque passage de la boucle et peut entraîner une amélioration mesurable des performances.
sera évalué en un pseudo-code comme celui-ci:
Notez que 0 est un littéral, ou en d'autres termes, une valeur constante.
sera évalué en un pseudo-code comme celui-ci (optimisation normale de l'interpréteur supposée):
Notez que end est une variable qui a besoin d'un registre CPU . Cela peut invoquer un échange de registre supplémentaire dans le code et nécessite une instruction de comparaison plus coûteuse dans l'
if
instruction.Juste mes 5 cents
Pour un langage de haut niveau, la lisibilité, qui facilite la maintenabilité, est plus importante en tant qu'amélioration mineure des performances.
Normalement, l' itération classique du début à la fin du tableau est meilleure.
L'itération plus rapide de la fin du tableau au début entraîne la séquence inversée potentiellement indésirable.
Post Scriptum
Comme demandé dans un commentaire: La différence de
--i
eti--
réside dans l’évaluation desi
avant ou après la décrémentation.La meilleure explication est de l'essayer ;-) Voici un exemple Bash .
la source
--i
eti--
aussi?J'ai vu la même recommandation dans Sublime Text 2.
Comme cela 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 (en faisant un
for
pour tous lesli
éléments).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++)
D'où je me tiens, la principale amélioration du formulaire dans votre question est le fait qu'il ne déclare pas de variable supplémentaire (
len
dans mon exemple)Mais si vous me demandez, le point ne concerne pas l' optimisation
i++
vsi--
, mais 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 ).la source
Je ne pense pas qu'il soit logique de dire que
i--
c'est plus rapide quei++
JavaScript.Tout d'abord , cela dépend totalement de l'implémentation du moteur JavaScript.
Deuxièmement , à condition que les constructions les plus simples soient JIT et traduites en instructions natives, alors
i++
vsi--
dépendra totalement du CPU qui l'exécute. Autrement dit, sur les ARM (téléphones mobiles), il est plus rapide de descendre à 0 car la décrémentation et la comparaison avec zéro sont exécutées en une seule instruction.Vous pensiez probablement que l'un était plus gaspillé que l'autre parce que la manière suggérée est
mais la manière suggérée n'est pas parce que l'un est plus rapide que l'autre, mais simplement parce que si vous écrivez
puis à chaque itération
array.length
devait être évaluée (un moteur JavaScript plus intelligent pourrait peut-être comprendre que la boucle ne changerait pas la longueur du tableau). Même si cela ressemble à une simple déclaration, c'est en fait une fonction qui est appelée sous le capot par le moteur JavaScript.L'autre raison, qui
i--
pourrait être considérée comme "plus rapide", est que le moteur JavaScript n'a besoin d'allouer qu'une seule variable interne pour contrôler la boucle (variable à lavar i
). Si vous comparez à array.length ou à une autre variable, il doit y avoir plus d'une variable interne pour contrôler la boucle, et le nombre de variables internes est un atout limité d'un moteur JavaScript. Moins les variables sont utilisées dans une boucle, plus JIT a de chances d'optimiser. Voilà pourquoii--
pourrait être considéré comme plus rapide ...la source
array.length
est évalué. La longueur n'est pas calculée lorsque vous vous y référez. (C'est juste une propriété qui est définie chaque fois qu'un index de tableau est créé ou modifié ). Lorsqu'il y a un coût supplémentaire, c'est parce que le moteur JS n'a pas optimisé la chaîne de recherche pour ce nom.getLength(){return m_length; }
car il y a un peu d'entretien interne impliqué. Mais si vous essayez de penser en arrière: ce serait assez ingénieux d'écrire une implémentation de tableau où la longueur devrait être réellement calculée :)length
doit être mis à jour immédiatement chaque fois qu'une propriété-qui-est-un-tableau-index est ajoutée ou modifiée.dec/jnz
par rapport àinc eax / cmp eax, edx / jne
.Puisqu'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 des langages de niveau inférieur, votre question est pour JavaScript) J'ai décidé d'écrire la mienne.
Alors, c'est parti:
Réponse simple:
i--
est généralement plus rapide car il n'a pas à exécuter une comparaison à 0 à chaque exécution, les résultats des tests sur différentes méthodes sont ci-dessous:Résultats des tests: Comme "prouvé" par ce jsPerf,
arr.pop()
c'est en fait la boucle la plus rapide de loin. Mais, en se concentrant sur--i
,i--
,i++
et++i
que vous avez demandé à votre question, voici jsPerf (ils sont de multiples jsPerf de, s'il vous plaît voir les sources ci - dessous) Les résultats résumés:--i
eti--
sont les mêmes dans Firefox tandis quei--
c'est plus rapide dans Chrome.Dans Chrome, une boucle for de base (
for (var i = 0; i < arr.length; i++)
) est plus rapidei--
et--i
tandis que dans Firefox, elle est plus lente.Dans Chrome et Firefox, un cache
arr.length
est beaucoup plus rapide avec Chrome en avance d'environ 170 000 opérations / s.Sans différence significative,
++i
est plus rapide quei++
dans la plupart des navigateurs, AFAIK, ce n'est jamais l'inverse dans n'importe quel navigateur.Résumé plus court:
arr.pop()
c'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épond à votre question.
la source
pop
test ne semble que très rapide car il réduit la taille du tableau à 0 pour la majorité de la boucle - pour autant que je sache. Cependant, pour m'assurer que les choses sont justes, j'ai conçu ce jsperf pour créer le tableau de la même manière à chaque test - ce qui semble se révéler.shift()
être le gagnant pour mes quelques navigateurs - pas ce à quoi je m'attendais cependant :) jsperf.com / comparer-différents-types-de boucle++i
: DCela dépend du placement de votre baie dans la mémoire et du taux de succès des pages de mémoire lorsque vous accédez à cette baie.
Dans certains cas, l'accès aux membres du tableau dans l'ordre des colonnes est plus rapide que l'ordre des lignes en raison de l'augmentation du taux d'accès.
la source
La dernière fois que je m'en suis inquiété, c'était lors de l'écriture de l' assemblage 6502 (8 bits, oui!). Le gros gain est que la plupart des opérations arithmétiques (en particulier les décrémentations) ont mis à jour un ensemble de drapeaux, dont l'un était
Z
l'indicateur «atteint zéro».Donc, à la fin de la boucle, vous venez de faire deux instructions:
DEC
(décrémenter) etJNZ
(sauter sinon zéro), aucune comparaison nécessaire!la source
i--
vsi++
est probablement qu'avec le premier, vous n'introduisez pas de variables de contrôle supplémentaires dans la portée de la boucle. Voir ma réponse ci-dessous ...dec/jnz
au lieu duinc/cmp/jne
cas x86. Vous ne verrez pas une boucle vide s'exécuter plus rapidement (les deux satureront le débit de la branche), mais le décompte réduit légèrement la surcharge de la boucle. Les pré-récupérateurs Intel HW actuels ne sont pas gênés non plus par les modèles d'accès à la mémoire qui vont dans l'ordre décroissant. Je pense que les processeurs plus anciens pourraient suivre comme 4 flux en arrière et 6 ou 10 flux en avant, IIRC.Cela peut s'expliquer par le fait que JavaScript (et toutes les langues) est éventuellement transformé en opcodes pour s'exécuter sur le CPU. Les processeurs ont toujours une seule instruction pour comparer avec zéro, ce qui est sacrément rapide.
Soit dit en passant, si vous pouvez garantir
count
est toujours>= 0
, vous pouvez simplifier pour:la source
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 votre boucle vérifie les conditions à 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.
la source
for(var i = array.length; i--; )
n'est pas beaucoup plus rapide. Mais lorsque vous remplacezarray.length
parsuper_puper_function()
, cela peut être beaucoup plus rapide (car il est appelé à chaque itération). Voilà la différence.Si vous comptez le changer en 2014, vous n'avez pas besoin de penser à l'optimisation. Si vous voulez le changer avec "Rechercher et 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 d'y penser.
PS:
i--
n'est pas plus rapide quei++
.la source
Pour faire court: il n'y a absolument aucune différence à le faire en JavaScript.
Tout d'abord, vous pouvez le tester vous-même:
jsperf - est une excellente plate-forme pour toutes sortes de tests de performances en JavaScript .
http://jsperf.com/inc-vs-dec-2
Non seulement vous pouvez 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 qu'à la possibilité de voir les différences entre le temps d'exécution dans différents navigateurs sur différentes plates-formes.
Pour autant que vous puissiez voir, il n'y a aucune différence entre les performances dans n'importe quel environnement.
Si vous souhaitez améliorer les performances de votre script, vous pouvez essayer de faire les choses suivantes:
var a = array.length;
déclaration pour que vous ne calculiez pas sa valeur à chaque fois dans la boucleMais vous devez comprendre que l'amélioration que vous pouvez obtenir sera si insignifiante que vous ne devriez même pas vous en soucier.
Ma propre opinion pourquoi une telle idée fausse (Dec vs Inc) est apparue
Il y a très longtemps, il y avait une instruction machine commune, DSZ (décrémentation et saut 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 faits anciens sont obsolètes, et je suis sûr que vous n'obtiendrez aucune amélioration des performances dans aucune langue en utilisant cette pseudo amélioration.
Je pense que la seule façon dont de telles connaissances peuvent se propager à notre époque est lorsque vous lisez le code personne d'un autre. Voir une telle construction et demander pourquoi a-t-elle été implémentée et voici la réponse: "elle améliore les performances car elle se compare à zéro". Vous êtes devenu déconcerté par une meilleure connaissance de votre collègue et pensez à l'utiliser pour être beaucoup plus intelligent :-)
la source
array.length
n'entraîne pas nécessairement une baisse des performances, simplement parce que la machine virtuelle JS est suffisamment intelligente pour déterminer si le tableau n'est pas modifié par le corps de la boucle. Voir ma réponse ci-dessous.J'ai fait une comparaison sur jsbench .
Comme l'a souligné alestani, 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:
vous évaluez
.length
chaque fois que vous augmentezi
. Dans celui-ci:vous évaluez
.length
qu'une seule fois, lorsque vous déclarezi
. Dans celui-ci:la comparaison est implicite, elle se produit juste avant la décrémentation
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):
Boucle avec code intégré:
Si vous pouvez aligner votre code, au lieu d'appeler une fonction, sans sacrifier la lisibilité, vous pouvez avoir une boucle d'un ordre de grandeur plus rapidement!
Remarque : le navigateur devient bon à intégrer des fonctions simples, cela dépend vraiment de la complexité de votre code. Donc, profil avant optimisation, car
Mais rappelles-toi:
la source
La façon dont vous le faites maintenant n'est pas plus rapide (à part qu'il s'agit d'une boucle indéfinie, je suppose que vous vouliez le faire
i--
.Si vous voulez accélérer les choses, faites:
bien sûr, vous ne le remarqueriez pas sur une si petite boucle. La raison pour laquelle c'est plus rapide est parce que vous décrémentez i tout en vérifiant que c'est "vrai" (il est évalué à "faux" quand il atteint 0)
la source
(i = 10; i--;)
Parfois, apporter des modifications très mineures à la façon dont nous écrivons notre code peut faire une grande différence dans la rapidité d'exécution de notre code. Un domaine où un changement de code mineur peut faire une grande différence dans les temps d'exécution est celui où nous avons une boucle for qui traite un tableau. Lorsque le tableau contient des éléments sur la page Web (tels que des boutons radio), le changement a le plus grand effet, mais il vaut toujours la peine d'appliquer ce changement même lorsque le tableau est interne au code Javascript.
La manière conventionnelle de coder une boucle for pour traiter un tableau est comme ceci:
Le problème avec cela est que l'évaluation de la longueur du tableau à l'aide de myArray.length prend du temps et la façon 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, la longueur du tableau sera évaluée 1001 fois. Si nous regardions les boutons radio et que nous avions myForm.myButtons.length, il faudra encore plus de temps pour évaluer car le groupe de boutons approprié dans le formulaire spécifié doit d'abord être localisé avant que la longueur puisse être évaluée à chaque fois dans 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 dans la boucle qui ajoute ou supprime des entrées de tableau, la taille du tableau peut changer entre les itérations et nous ne pouvons donc pas changer le code qui le teste)
Ce que nous pouvons faire pour corriger cela 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 terminer la boucle. C'est beaucoup plus rapide que d'évaluer la longueur du tableau à chaque fois, en particulier lorsque le tableau contient plus que quelques entrées ou fait partie de la page Web.
Le code pour ce faire est:
Alors maintenant, nous n'évaluons la taille du tableau qu'une seule fois et testons notre compteur de boucles par rapport à la variable qui détient cette valeur à chaque fois dans la boucle. Cette variable supplémentaire est accessible beaucoup plus rapidement que l'évaluation de la taille du tableau et notre code s'exécutera donc beaucoup plus rapidement qu'auparavant. Nous avons juste une variable supplémentaire dans notre script.
Souvent, peu importe l'ordre dans lequel nous traitons le tableau tant que toutes les entrées du tableau sont traitées. 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 tableau de la manière la plus efficace possible est:
Ce code n'évalue toujours la taille du tableau qu'une seule fois au début, mais au lieu de comparer le compteur de boucle avec une variable, nous le comparons avec une constante. Puisqu'une constante est encore plus efficace d'accès qu'une variable et que nous avons une instruction d'affectation de moins 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.
la source
++
vs.--
n'a pas d'importance car JavaScript est un langage interprété, pas un langage compilé. Chaque instruction se traduit par plus d'un langage machine et vous ne devez pas vous soucier des détails sanglants.Les gens qui parlent d'utiliser
--
(ou++
) pour utiliser efficacement les instructions de montage ont tort. Ces instructions s'appliquent à l'arithmétique des entiers et il n'y a pas d'entiers en JavaScript, juste des nombres .Vous devez écrire du code lisible.
la source
Dans de nombreux cas, cela n'a essentiellement rien à voir avec le fait que les processeurs peuvent se comparer à zéro plus rapidement que les autres comparaisons.
En effet, seuls quelques moteurs Javascript (ceux de la liste JIT) génèrent réellement du code en 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 à quoi cela ressemble, jetez un œil au bas de cette page sur SpiderMonkey de Firefox ). Généralement, si un morceau de code fait pratiquement la même chose mais conduit à une représentation interne plus simple, il s'exécutera plus rapidement.
Gardez à l'esprit qu'avec des tâches simples telles que l'ajout / la soustraction d'une variable ou la comparaison d'une variable à quelque chose, la surcharge de l'interpréteur passant d'une "instruction" interne à la suivante est assez élevée, donc les moins "instructions" qui sont utilisé en interne par le moteur JS, mieux c'est.
la source
Eh bien, je ne sais pas pour JavaScript, cela devrait vraiment être juste une question de longueur de tableau de réévaluation et peut-être quelque chose à voir avec les tableaux associatifs (si vous décrémentez seulement, il est peu probable que de nouvelles entrées soient allouées - si le tableau est dense, c'est-à-dire que quelqu'un peut optimiser pour cela).
Dans un assemblage de bas niveau, il existe une instruction de bouclage, appelée DJNZ (décrémentation et saut si non nul). Ainsi, la décrémentation et le saut sont tous dans une instruction, ce qui la rend probablement un peu plus rapide que INC et JL / JB (incrémenter, sauter si moins que / sauter si ci-dessous). En outre, la comparaison avec zéro est plus simple que la comparaison avec 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 Arm dans un smartphone).
Je ne m'attendrais pas à ce que ces différences de bas niveau aient un si grand impact sur les langages interprétés, je n'ai tout simplement pas vu DJNZ parmi les réponses, alors j'ai pensé partager une pensée intéressante.
la source
DJNZ
est une instruction dans le 8051 (z80) ISA. x86 adec/jnz
au lieu deinc/cmp/jne
, et apparemment arm a quelque chose de similaire. Je suis sûr que ce n'est pas la cause de la différence Javascript; c'est d'avoir plus à évaluer dans la condition de boucle.Il a utilisé à dire que -I était plus rapide (en C ++) parce qu'il n'y a qu'un seul résultat, la valeur décrémentée. i-- doit stocker la valeur décrémentée sur i et conserver également la valeur d'origine comme résultat (j = i--;). Dans la plupart des compilateurs, cela utilisait deux registres plutôt qu'un seul, ce qui pouvait entraîner l'écriture d'une autre variable en mémoire plutôt que sa conservation en tant que variable de registre.
Je suis d'accord avec les autres qui ont dit que cela ne fait aucune différence ces jours-ci.
la source
En termes très simples
"i-- et i ++. En fait, ils prennent tous les deux le même temps".
mais dans ce cas, lorsque vous avez un fonctionnement incrémentiel .. le processeur évalue la .length chaque fois que la variable est incrémentée de 1 et en cas de décrémentation .. en particulier dans ce cas, il n'évaluera .length qu'une seule fois jusqu'à ce que nous obtenions 0.
la source
Tout d'abord,
i++
eti--
prenez exactement le même temps sur n'importe quel langage de programmation, y compris JavaScript.Le code suivant prend beaucoup de temps.
Vite:
Lent:
Par conséquent, le code suivant prend également un temps différent.
Vite:
Lent:
PS Slow n'est lent que pour quelques langues (moteurs JavaScript) en raison de l'optimisation du compilateur. La meilleure façon est d'utiliser '<' à la place '<=' (ou '=') et '--i' à la place 'i--' .
la source
Pas beaucoup de temps est consommé par i-- ou i ++. Si vous allez profondément dans l'architecture du processeur, le
++
est plus rapide que le--
, car l'--
opération fera le complément du 2, mais elle s'est produite à l'intérieur du matériel, ce qui le rendra rapide et aucune différence majeure entre le++
et--
ces opérations sont également considérées comme le le moins de temps consommé dans le CPU.La boucle for fonctionne comme ceci:
<
,>
,<=
, etc.Alors,
va calculer la longueur du tableau une seule fois au début et ce n'est pas beaucoup de temps, mais
calculera la longueur à chaque boucle, donc cela prendra beaucoup de temps.
la source
var i = Things.length - 1; i >= 0; i--
calculera également la durée 1 fois.--
opération fera le complément à 2" signifie, mais je suppose que cela signifie qu'il annulera quelque chose. Non, cela n'annule rien sur aucune architecture. Soustraire 1 est aussi simple que d'ajouter 1, vous faites juste un circuit qui emprunte plutôt que porte.La meilleure approche pour répondre à ce genre de question est de l'essayer. Configurez une boucle qui compte un million d'itérations ou autre, et faites-le dans les deux sens. Minutez les deux boucles et comparez les résultats.
La réponse dépendra probablement du navigateur que vous utilisez. Certains auront des résultats différents des autres.
la source
J'adore, beaucoup de marques mais pas de réponse: D
Mettre simplement une comparaison contre zéro est toujours la comparaison la plus rapide
Donc (a == 0) est en fait plus rapide à renvoyer True que (a == 5)
C'est petit et insignifiant et avec 100 millions de lignes dans une collection, il est mesurable.
c'est-à-dire sur une boucle, vous pourriez dire où i <= array.length et incrémenter i
sur une boucle descendante, vous pourriez dire où i> = 0 et décrémenter i à la place.
La comparaison est plus rapide. Pas la «direction» de la boucle.
la source
AIDEZ LES AUTRES À ÉVITER UN MAUX DE TÊTE --- VOTER ICI !!!
La réponse la plus populaire sur cette page ne fonctionne pas pour Firefox 14 et ne passe pas le jsLinter. Les boucles "while" nécessitent un opérateur de comparaison, pas une affectation. Il fonctionne sur Chrome, Safari et même IE. Mais meurt dans Firefox.
C'EST CASSÉ!
Cela fonctionnera! (fonctionne sur firefox, passe le jsLinter)
la source
while (i--)
et qui fonctionnent sur de nombreux navigateurs. Aurait-il pu y avoir quelque chose de bizarre dans votre test? Utilisez-vous une version bêta de Firefox 14?C'est juste une supposition, mais c'est peut-être parce qu'il est plus facile pour le processeur de comparer quelque chose avec 0 (i> = 0) plutôt qu'avec une autre valeur (i <Things.length).
la source