if x < 2 vs if 2 > x

WRInaute impliqué
Bonjour,
en soumettant un bout de javascript à l'outil de "compression" Google, j'ai remarqué qu'il remplaçait "if(x<2)" par "if(2>x)" par exemple. Je me doute bien qu'un éventuel gain serait de l'ordre de la fraction de milliseconde, mais savez-vous pourquoi la deuxième écriture serait plus optimisée ? (juste par curiosité)
Merci !
 
WRInaute accro
Salut, je dirais, par hypothèse, d’abord les chiffres et ensuite les lettres. Le premier index est plus petit.
 
WRInaute impliqué
c'est peut être juste parce que le code est évalué et ensuite ils fournissent un code suivant ce qui est évalué, sans forcément que ce soit écrit de la même façon, et ils ont choisi cet ordre de façon arbitraire
 
WRInaute accro
Je pense que c'est une question de registre processeur (mais rien de sur la dessus la dermière fois ou j'ai manipulé du code assembleur remonte a loin)

Pour faire une comparaison les processeurs font en fait une soustraction tu as donc supériorité, égalité ou infériorité en fonction du résultat (voir bit de signe, flag "N" dans la photo ci dessous qui te donne +/- et bit de zéro, flag "Z" qui te donne l'égalité dans une opération arithmétique).

Hors charger "2" dans un registre de données(EDX) (cellule mémoire du processeur destinée a de la data) et lui soustraire un accumulateur (EAX) (registre de travail particulier du processeur) est plus rapide car tu n'as pas a recharger ensuite l'accumulateur (le restaurer),

Les accumulateurs ayant des fonctions dédiées et étendues qui leurs sont propres dans le fonctionnement on ne peut pas forcement faire tout ce qu'on veux ...

Le résultat de l'opération se trouve alors dans le registre des flag qui permet de répondre supérieur, inférieur ou égale avec un simple test électronique sur deux bits (donc avec juste une Fctn logique cablée de base)...

Là j'imagine que le code javascript place 2 en mémoire donc c'est commode de charger un registre de données avec ça, et j'imagine aussi que X qui est une variable a des chances de se trouver déjà dans un registre processeur de type accumulateur (de part un appel de fonction par exemple) du coup au final la comparaison (soustraction) se fait plus vite et la variable (présente dans l'accumulateur) reste manipulable juste après pour un éventuel autre traitement.

Exemple de registres "classiques" :
Register_8086.PNG

Exemple de registre de flag (attention chaque processeur est différent donc c'est juste un exemple simple sur un vieux truc) :
ccr68k.jpg
 
WRInaute accro
salva a dit:
d’abord les chiffres et ensuite les lettres. Le premier index est plus petit.
Ils ont aucun moyen de savoir si 2 est plus petit ou pas il ont même la certitude que c'est pas toujours le cas puisque c'est un test d'infériorité ou de supériorité :wink: .
En revanche la notion de constante et variable me semble plus payante pour un ordre de préséance.
 
WRInaute impliqué
et l'optimisation de l'ordre x < 2 et 2 > x, si elle est vraiment réelle, n'est-elle pas faite directement par le moteur javascript pour qu'on n'ait pas à réfléchir à ces problématiques en assembleur quand on code en javascript ?
 
WRInaute passionné
Après ça je ne regarderai plus jamais zeb de la même façon 8O

J'allais dire que c'est peut-être la bonne pratique qui consiste à placer la valeur avant la variable dans un test parce que ... si on fait une erreur ... ça n'affecte pas la variable ... enfin je crois. Je ne sais plus ce qui était recommandé mais j'avais lu un truc sur le sujet. De toute façon je ne le fais pas :p
 
WRInaute accro
madri2 a dit:
et l'optimisation ... n'est-elle pas faite directement par le moteur javascript pour qu'on n'ait pas à réfléchir à ces problématiques en assembleur quand on code en javascript ?
Il est probable (enfin si c'était moi qui codait le truc), que tu ai une forme d'optimisation qui soit faite en interne sur le moteur javascript en effet.
Il y a forcement en tous cas une forme de traitement qui est fait pour mettre en forme les données (vu du moteur javascript ton programme est en fait des données textuelles qu'il doit comrpendre) dans la mesure ou un interpréteur de code voir même un compilateur (pour prendre les deux cas standards des langages) sont obligés de réduire a des cas "traitable" une infinité d'options que les codeurs vont écrire.

Dans cette mesure, en tant que codeur, soit tu te place dans le cas ou tu fourni une syntaxe optimisée, soit tu laisse le moteur de langage (ou le compilateur) gérer le truc. La différence sera dans le nombres de conditions (if) et traitements (do) que tu va traverser pour arriver au résultat.

Faut comprendre que tu ne passe pas d'un langage quasi naturel (comme javascript) du genre si(ceci)alors(cela puis ceci)ou_alors(cela)... a une suite d'opcode processeur, bref si tu veux réellement faire performant il faut rapprocher le "langage naturel" du code intermédiaire que va générer le moteur (ex javascript) ou le compilateur (ex C).

* les langages compilés (ex C et dérivés)
A noter toutefois que s'étendre dans te tels optimisations pour un langage compilé est un peut ridicule, car d'une part tu as moins de fonctions de haut niveau a la syntaxe flexible comme javascript donc tu est déjà plus cadré dans ta syntaxe (comprendre que tu ne peux pas écrire tout et n'importe quoi dans l'ordre que tu veux) et d'autre part le code intermédiaire généré va de toute façon être compilé en un exécutable compatible avec le processeur que tu aura spécifié donc une suite d'opcode directement exécutable. Si tu décortique ce genre de fichier (un soir d'hivers ou t'as rien d'autre a faire) tu te rend compte que c'est que des valeurs binaires qui correspondent a des suite d'opcode & data qui vont être présentées sur le bus de données du processeur et qui de fait représentent les états électriques des "fil, cables" de la puce.

Le gain doit donc se trouver dans le temps de compilation ici.

* les langages interprétés (genre javascript)
Par opposition aux langages compilés, un langage interprété (donc qui traverse à chaque exécution les couches d'optimisaton et de mise en forme avant d'être exécuté) va refaire le traitement de mise en forme a chaque utilisation du code ... Imagine donc comme la moindre petite ligne gourmandes va engendre une débauche de consommation électrique 8O Dans le cas de figure vis a vis du problème soulevé, on peut imaginer que ce genre de "bonnes pratiques" est en mesure d'avoir un impact réel sur une machine même si pour une page web isolée ça change quedal ou presque. Mais pense que javascript est utilisé dans les plugins de ton navigateur et pour d'autre trucs sur la machine, sans parler du fait qu'il n'y a pas que javascript qui est interprété ... Là tu touche du doigt la différence de réputation des langages quand on oppose compilé et interprété.

Le gain est proportionnel a l'utilisation ici donc important

Après, en général les conditions sont probablement après les opérations arithmétiques les instructions processeurs les plus utilisées mais aussi les moins gourmandes dans les micro instruction de base (une grosse majorité du code) et si je met de côté les opérations complexes (multiplications et division par exemple qui sont des itératives sur les anciens processeurs) tu en as une tétra chié qui sont exécitées en une seconde sur ta machine ... Bref moins c'est mieux :D :wink:

Faut noter au passable que le monde de l'objet arrivé dans les années 80/90 a induit avec force la notion de réutilisation du code ... :( cette même notion prise dans un sens erroné à même crée (hypothèse) le célèbre "tu va pas réinventer la roue" ... Au final 20/30 ans plus tard tu constate quoi ? :
* le codeur ne sais plu ce qui se passe sur la carte mère du système qu'il programme
* on empile des couches logicielles les une par dessus les autres pour arriver au processeur
* on fait appel a des bibliothèques très riches, gourmandes et lourdes pour faire un BL
* on est obligé de doubler la puissance de calcul et la taille mémoire souvent pour suivre l'évolution ...

On fait de la merde avec 10 fois plus que necessaire. :(

Le corolaire est qu'on le fera dix fois moins longtemps, le monde n'est pas une ressource inépuisable :D
 
WRInaute accro
Axiso a dit:
Après ça je ne regarderai plus jamais zeb de la même façon 8O
Je suis vraiment tombé dans la matrice quand j'étais petit donc il y a très longtemps :lol:
Tu veux le bonbon rouge ou le bleu ?
 
WRInaute impliqué
le fou il nous a rédigé un truc pendant une demi heure :D

je me demande si des cache d'opcode compilés ça existe en javascript (ça existe en php pour éviter de révaluer le code à chaque fois)
 
WRInaute discret
Désolé, je n'ai pas lu les longs textes de Zeb (en faites j'ai essayé, mais ... j'ai vite abandonné).

Pour répondre, sans vraiment répondre, j'ai fais un bench pour PHP (d'ou le fait que je ne réponds pas vraiment), sur 1500 lancements*, les cas suivants sont légèrement plus rapide :

2 < $var
2 <= $var

par rapport à

$var > 2
$var >= 2

* (500 avec un nombre élevé, 500 avec un nombre plus petit donc 1 et 500 lancement avec un peu plus grand).

La différence est négligeable (mais existe) avec le "<", la différence est plus marqué avec le ">=".

Et j'en ai profiter pour faire pareil pour 2==$var et $var==2, même résultat 2==$var est plus rapide.

Evidemment, ça reste suffisamment négligeable pour ne pas s'amuser à tout recoder :D mais si on est exigeant, autant prendre l'habitude. (d'autant que dans certains cas, ce n'est pas du tout négligeable, notamment quand le string comparé (pour un ==) est important).
 
Nouveau WRInaute
Dans le même genre, on recommande d'utiliser ++x plutôt x++. Ca permet d'appliquer le calcul directement sur la variable sans la mettre en mémoire.
Le principe est identique avec 2>x.
 
Nouveau WRInaute
Je me demande si ça ne vient pas du fait qu'il est, pour des raisons de sécurité, plus logique de mettre la constante à gauche du signe d'égalité.

Il est recommandé, en particulier d'écrire
if(2==x)
plutôt que
if(x==2)
pour la simple raison que si, on omet un signe =, dans le premier cas, une erreur surviendra alors que dans le second cas, le code est parfaitement légal et extrêmement à debugger.

Dans ce cas, il est possible que la modif ait été appliquée à tous les signes de comparaison.
 
Haut