J'essaie de donner une vue d'ensemble avec cette réponse.
Les réflexions suivantes entre parenthèses était ma conviction jusqu'à ce que j'aie récemment testé le problème :
[[En termes de les langages de bas niveau comme C / C++ le code est compilé de manière à ce 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 d'une telle optimisation, vous pouvez opter pour ++i
au lieu de i++
parce que ++i
est une commande pour un seul processeur alors que i++
signifie j=i+1, i=j
.]]
Les boucles très rapides peuvent être réalisées 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 de cette situation peuvent être assez compliquées (pour ne citer que 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 vous appuyez sur des bibliothèques, des fonctions intégrées pour le bouclage. 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 : les navigateurs ne sont pas les seuls à disposer d'un espace à optimiser facilement, il suffit de redéfinir l'élément forEach
(en fonction du navigateur) pour qu'elle utilise les meilleures astuces les plus récentes ! :) @A.M.K. dit que dans des cas particuliers, il est préférable d'utiliser plutôt array.pop
ou array.shift
. Si vous le faites, mettez-le derrière le rideau. Le site exagération extrême est d'ajouter des options à forEach
pour sélectionner l'algorithme de bouclage].
De plus, même pour les langages de bas niveau, la meilleure pratique consiste à utiliser une fonction intelligente de la bibliothèque pour les opérations complexes et en boucle, si cela est possible.
Ces bibliothèques peuvent également mettre des choses (multithread) dans votre dos et des programmeurs spécialisés les maintiennent à jour.
J'ai fait un peu plus de recherches et il s'avère qu'en 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 par rapport à une constante comme le dit @alestanis. (Les résultats de JsPerf sont parfois incohérents mais dans l'ensemble disent la même chose : on ne peut pas faire une grande différence).
Alors --i
se trouve être une chose plutôt "chic". Cela ne fait que vous faire passer pour un meilleur programmeur :)
Par contre, pour le déroulement dans cette situation de 5e9, il m'a fait passer 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 à un petit temps non mesurable :) (Le déroulement peut être fait de la manière décrite ci-dessus ou en utilisant i++
mais cela ne fait pas avancer les choses en JavaScript. )
Dans l'ensemble : garder i--
/ i++
et ++i
/ i++
différences aux entretiens d'embauche, tenez-vous en à array.forEach
ou d'autres fonctions complexes de la bibliothèque lorsqu'elles sont disponibles ;)
6 votes
À l'envers
for
est plus rapide parce que la variable de contrôle de la boucle à limite supérieure (hehe, à limite inférieure) ne doit pas être définie ou récupérée à partir d'un objet ; c'est une constante zéro.3 votes
Avez-vous essayé un fiddler ou tout autre outil de performance pour javascript ?
0 votes
@Floradu88 : Vraiment, pas encore mais je crois que c'est correct. J'ai vu cela dans plusieurs articles et suggestions d'éditeurs :)
92 votes
Il y a aucune différence réelle . Les constructions de boucles natives vont toujours être très rapide . Ne vous inquiétez pas de leurs performances.
0 votes
@billyonecan : Lol ! 58% plus lent que l'incrément ici. Wtf.
25 votes
@Afshin : Pour des questions comme celle-ci, veuillez nous montrer les articles auxquels vous faites référence.
0 votes
@billyonecan si vous convertissez le commentaire en réponse vous avez mon vote en haut.
5 votes
Liés : Est-il plus rapide de compter vers le bas que vers le haut ?
0 votes
@billyonecan le test que vous avez posté est plus un test de type JS Array que -- vs ++.
0 votes
AshwinPrabhu, oui, j'ai vu. votre révision
23 votes
La différence est surtout importante pour les appareils très bas de gamme et les appareils alimentés par batterie. La différence est qu'avec i-- vous comparez à 0 pour la fin de la boucle, alors qu'avec i++ vous comparez à un nombre > 0. Je crois que la différence de performance était de l'ordre de 20 nanosecondes (quelque chose comme cmp ax,0 vs. cmp ax,bx) - ce qui n'est rien mais si vous bouclez des milliers de fois par seconde, pourquoi ne pas avoir un gain de 20 nanosecondes pour chacune :)
1 votes
Vous ne posez pas vraiment la bonne question sur la base des échantillons de code que vous montrez. Ce n'est pas le cas de i-- qui est rapide, c'est la construction de la boucle où la longueur du tableau n'est évaluée qu'une seule fois qui est la plus rapide.
0 votes
Alors comment
for(i = 0; i < arr.length; i++)
comparer avecfor(i in arr)
?3 votes
Downvoting parce qu'il n'y a pas de repères, juste une hypothèse incorrecte.
1 votes
@Lyuben : Complètement faux. Quelque chose comme la comparaison de deux registres et la comparaison d'un registre avec zéro vont s'exécuter à la même vitesse.
0 votes
@Billy ONeal : Comment est-ce possible, quand dans un cas le CPU doit récupérer la valeur du registre et dans l'autre il ne récupère rien ?
0 votes
@BillyONeal comparer deux registres signifie que les deux doivent être activés, mais comparer avec 0 nécessite un seul registre. Mais puisque la différence n'est presque rien et qu'elle est juste dans l'initialisation de la boucle, je pense qu'utiliser le comptage dans de nombreux cas est plus suffisant car cela augmente la lisibilité.
1 votes
Je me souviens avoir programmé l'assemblage sur le processeur 6502. La version de décrémentation était plus rapide à l'époque. Mais c'était il y a longtemps... Cela ne devrait pas faire de différence (mesurable) aujourd'hui.
0 votes
@BillyONeal : Tout dépend du processeur. Dans le cas de la décrémentation, il peut y avoir des cas où la comparaison avec zéro n'est même pas nécessaire.
2 votes
@Axel : Complètement hors sujet. En C, vous pourriez avoir raison. En JavaScript ? Aucun - il n'y a pas de relation 1:1 entre le code et le matériel dans ce langage. (Par exemple, JavaScript n'a pas d'entiers, donc ce sera toujours une comparaison en virgule flottante dans tous les cas).
1 votes
Les tests de référence montrent que la version décrémentale est systématiquement plus rapide que les autres, quel que soit le navigateur utilisé.
0 votes
@NullUserException - Ce que je voulais dire, c'est que même si les benchmarks peuvent le montrer, la différence en termes réels est insignifiante et ne mérite pas qu'on s'en préoccupe. Il s'agit d'une micro-optimisation aussi poussée que possible. Notez également que le benchmark auquel j'ai fait référence tombe dans le piège mentionné dans la réponse la plus votée ici.
0 votes
@JamesAllardice - il n'est jamais négligeable d'écrire un jeu en temps réel ou de faire un rendu en temps réel. Imaginez un instant que vous avez 200 objets que vous devez parcourir en boucle à chaque image et que vous avez 50 images/par seconde - alors la boucle sera exécutée 1000 fois par seconde. Chaque gain me semble bon dans ce cas.
0 votes
@BillyONeal : Oui, et Javascript n'existait même pas à l'époque. Mais je faisais référence à votre commentaire "Quelque chose comme comparer deux registres et comparer un registre à zéro vont s'exécuter à la même vitesse", ce qui n'est pas vrai pour tous les processeurs.
1 votes
Ce qui manque à tant de réponses, même à celle qui a été acceptée avec 700 votes en septembre 2015, c'est que vous pouvez assigner multiple dans la première partie de votre boucle for. De la manière suivante par exemple, vous n'accédez qu'une seule fois à la longueur du tableau :
for (var i=0, n=msSeriesNames.validIds.length; i<n; i++) {