IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Débats sur le développement - Le Best Of Discussion :

La compilation à la volée (just-in-time) ne serait pas ergonomique selon un développeur


Sujet :

Débats sur le développement - Le Best Of

  1. #1
    Chroniqueur Actualités

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    mars 2013
    Messages
    5 997
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : mars 2013
    Messages : 5 997
    Points : 148 042
    Points
    148 042
    Par défaut La compilation à la volée (just-in-time) ne serait pas ergonomique selon un développeur
    Les compilations à la volée (Just-In-Time / JITs) ne seraient pas ergonomique
    selon un développeur qui propose des améliorations

    Les ordinateurs n'exécutent pas le code source que nous écrivons dans les langages de programmation, ils exécutent le code machine. Dans des circonstances normales, il existe deux façons de passer d'un langage de programmation au code machine :
    • les compilateurs, qui créent une fois un exécutable en code machine à partir de votre code source, et vous pouvez exécuter ce blob encore et encore. Compilation lente, exécution rapide
    • les interpréteurs, qui lisent le programme ligne par ligne lors de son exécution et exécutent un autre programme qui exécute ces lignes. Démarrage plus lent, performances plus lentes, mais aucune étape de compilation lente après les modifications.

    Les langages compilés sont plus rapides et plus sûrs. Les langages interprétés sont plus flexibles, plus productifs et plus faciles à apprendre.

    La compilation à la volée (just-in-time compilation ou JIT compilation en anglais) est une technique visant à améliorer la performance de systèmes compilés en bytecode par la traduction de bytecode en code machine natif au moment de l'exécution. La compilation à la volée se fonde sur deux anciennes idées : la compilation de bytecode et la compilation dynamique. Elle apporte donc le meilleur des deux mondes, en théorie.

    La compilation à la volée s'adapte dynamiquement à la charge de travail courante du logiciel, en compilant le code « chaud », c'est-à-dire le code le plus utilisé à un moment donné (ce qui peut représenter tout le programme, mais souvent seules certaines parties du programme sont traitées par compilation à la volée). Obtenir du code machine optimisé se fait beaucoup plus rapidement depuis du bytecode que depuis du code source. Comme le bytecode déployé est portable, la compilation à la volée est envisageable pour tout type d'architecture, à la condition d'avoir un compilateur JIT pour cette architecture, ce qui est facilité par le fait que les compilateurs de bytecode en code machine sont plus faciles à écrire que les compilateurs code source - code natif.

    La compilation à la volée ne serait pas ergonomique selon un développeur

    Abe Winter est un développeur reconverti qui a des années d'expérience professionnelle en tant que programmeur avec différents paradigmes de langage (statique, dynamique, JIT). Il pense que JIT n’est pas ergonomique :

    « Le travail sur les performances en 2020 peut concerner autant la mise en cache et la conception intelligente de RPC que les performances linéaires d'une fonction. Mais les performances en ligne droite comptent toujours. Et l'ergonomie de mesure de la performance d'un morceau de code en ligne droite en prod est mauvaise.

    « J’accuse le JIT.

    « J'aime l'idée de JIT, mais l'outillage est sous-développé. Le battage médiatique dit "compétitif avec C pour les fonctions numériques courtes", mais la réalité est "quelque part entre Python et Java". C’est comme un bus qui vous dépose à mi-chemin et ne vous laisse pas emporter de vélo. Il serait plus rapide de parcourir tout le chemin à vélo plutôt que d’en parcourir la moitié à pied ».

    Nom : JIT.png
Affichages : 176082
Taille : 29,6 Ko

    Voici les arguments qu’il avance pour soutenir son affirmation :

    JS JIT rend le test de performance impossible

    « Je ne sais pas comment faire ces choses en JavaScript :
    • savoir si une fonction est optimisée dans une exécution donnée ;
    • savoir si une fonction sera optimisée en prod ;
    • exiger statiquement qu'une fonction soit optimisée en prod ;
    • être informé des dépôts dans les chemins critiques (hot paths).

    « En l'absence d'un sous-ensemble de ces astuces, je n'ai aucun moyen de tester à la perfection mon code JS sans tester la charge à pleine échelle. Cela finit par être une énorme perte de temps et c'est la raison pour laquelle les gens réécrivent les services JS dans d'autres langages lorsqu'ils grandissent. »

    Les benchmarks mentent

    « C'est peut-être une façon forte de le dire. Mais les langages JIT rendent difficile l'utilisation du micro-benchmarking pour prédire les performances du même morceau de code en prod, pour plusieurs raisons:
    • les benchmarks (qui exécutent la même fonction avec les mêmes entrées des millions de fois de suite) sont très amies avec la gigue (jitter en anglais, variation de la latence au fil du temps) ;
    • la fonction que vous testez peut être appelée avec différentes entrées en prod. Dans JS, même l'ordre des clés dans un objet peut confondre le typer JIT ;
    • si vous comparez une fonction JIT / native et que votre configuration de produit finit par utiliser du code interprété, vous n'aurez rien appris.


    « Ne pas savoir combien de temps prend la réalité mène au vaudou et à la gymnastique.

    « Oui, les langages compilés ont leur propre version de ceci avec une cohérence de cache. Oui, le JIT peut conduire à de meilleures performances que la précompilation en théorie à cause du collecteur de statistiques, mais je ne contrôle aucune de ces choses. »

    Il est plus facile d'écrire du code performant (choisissez votre poison)

    « Et plus important encore, maintenir le code performant. Ne vous méprenez pas, je ne dis pas que C++, Go ou Java sont des langages plus productifs que JS. Mais si votre budget est tel que les serveurs coûtent plus cher que la paie, il est difficile de conserver votre logique de base à grande échelle dans un langage interprété / JIT.

    Pour deux raisons :
    • l’optimisation des hot paths : il y aura un moment où vous aurez besoin d'un chemin de code plus rapide et le JIT fera que cela marche comme si vous étiez en train de vous servir de la gélatine avec des pincettes ;
    • des régressions de performances : quelqu'un va à un moment donné effectuer un changement moyen ou grand dans le code qui va dégrader subtilement les performances et nuire à la qualité du produit, et à moins que votre surveillance soit excellente, vous ne le saurez pas


    Abe Winter ne demande pas d’abandonner le système JIT, mais de l’améliorer

    « Tout ce que je demande, c'est des informations et un contrôle. La prémisse de base de JIT de compiler uniquement des parties de votre programme me convient. Je voudrais pouvoir contrôler les parties en questions et le moment de compilation.

    « Je voudrais une collecte de statistiques efficace sur les dépôts en prod, donc je sais quelles fonctions traiter comme des hot paths.

    « Les langages compilés ont un paquet d'astuces qui sont en quelque sorte sur ce sujet : optimisation guidée statistiquement, optimisation de programme entier. Les compilations à la volée y arriveront. »

    Voici une liste d’éléments qu’il voudrait voir implémentés :

    Nom : element.png
Affichages : 3770
Taille : 9,3 Ko

    Source : Abe Winter

    Et vous ?

    Partagez-vous son avis ? Dans quelle mesure ?
    Que pensez-vous des arguments qu'il a avancés ?
    En avez-vous quelques-un pour soutenir ou relever les limites de son affirmation ?
    Que pensez-vous des propositions qu'il a faites ? En avez-vous d'autres ?
    Contribuez au club : Corrections, suggestions, critiques, ... : Contactez le service news et Rédigez des actualités

  2. #2
    Expert confirmé
    Homme Profil pro
    Responsable informatique, développeur tout-terrain
    Inscrit en
    juin 2004
    Messages
    842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Responsable informatique, développeur tout-terrain
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juin 2004
    Messages : 842
    Points : 4 101
    Points
    4 101
    Par défaut
    En vla encore des beaux poncifs...

    Les langages compilés sont plus rapides et plus sûrs. Les langages interprétés sont plus flexibles, productifs et plus faciles à apprendre.
    Un langage compilé n'est pas plus "sur" qu'un langage interprété, les fuites de mémoire, l'utilisation de pointeurs possiblement mal alloués le rend aussi dangereux qu'un langage interprété (voir peut être plus)

    Un langage interprété n'est pas forcement plus "productif" ni plus facile à apprendre qu'un langage compilé (si on prend perl par exemple... c'est parfois imbitable pour les néophytes...)

  3. #3
    Membre extrêmement actif
    Avatar de Sodium
    Femme Profil pro
    Développeuse web
    Inscrit en
    avril 2014
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeuse web

    Informations forums :
    Inscription : avril 2014
    Messages : 2 323
    Points : 1 928
    Points
    1 928
    Billets dans le blog
    1
    Par défaut
    Par sûr ils veulent dire qu'un programme plante à la compilation s'il y a une erreur, un langage interprété il faut utiliser une librairie pour ça

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    juin 2009
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 364
    Points : 1 208
    Points
    1 208
    Par défaut
    Le titre suggère une attaque sur le JIT en général, cependant les arguments donnés ne semblent concernés que le Javascript.

    Est-ce donc vraiment une critique de JIT globale, ou juste de l'état de celui en JavaScript ?

    Je peux comprendre la difficulté de parler de performance avec du JIT en jeu mais j'imagine que ces questions doivent avoir des réponses avec par exemple le JIT en Java depuis le temps que ça existe non ?

    Enfin, les arguments tel qu'énoncé me rappelle vaguement le genre qu'on peut entendre contre le garbage collector, ou contre quelqu'un qui se plaindrait qu'un compilateur réécrit sa fonction récursive en boucle a la compilation. "Je ne contrôle pas", oui, c'est fait exprès, parce que généralement les éléments en jeu feront mieux que "toi" (toi = le développeur moyen ici), si tu as un besoin absolu de contrôle, utilise un langage qui est fait pour ça, tu peux même écrire ta propre librairie C++ et l'utiliser dans Java, pareil côté nodeJS. Je ne suis pas un expert loin de là, mais il me semble bien que c'est prévu ainsi, ce n'est pas étonnant d'avoir des soucis si on veut faire autrement que comment c'est prévu.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juillet 2007
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : juillet 2007
    Messages : 821
    Points : 1 689
    Points
    1 689
    Par défaut
    Est-ce donc vraiment une critique de JIT globale
    Oui on parle bien de JIT, javascript est pris en exemple.

    Les arguments avancés sont tout a fais justifiés. Il ne dis pas que JIT est inutile il dis juste que dans du code réel (ou il n'y a pas une grande majorité de boucle répétés un grand nombre de fois mais plutôt beaucoup de branchement conditionnel et petites boucle), certes JIT accélère les grande boucle mais il empêche de traiter aussi efficacement qu'on l'aurait fais sans JIT les autres parties du code. Et il explique aussi que c'est très difficile a analyser.

    En ce sens il a raison. Il ne faut pas le voir comme un refus du JIT, mais comme une critique constructive pour focaliser la recherche autour du JIT plutôt que sur le JIT.
    Tout ce que j'écris est libre de droits (Licence CC0) et je vous incite à faire de même.

  6. #6
    Membre éprouvé Avatar de FatAgnus
    Homme Profil pro
    Trouffion de base
    Inscrit en
    août 2015
    Messages
    271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Trouffion de base

    Informations forums :
    Inscription : août 2015
    Messages : 271
    Points : 1 219
    Points
    1 219
    Par défaut
    Citation Envoyé par sergio_is_back Voir le message
    Un langage interprété n'est pas forcement plus "productif" ni plus facile à apprendre qu'un langage compilé (si on prend Perl par exemple... c'est parfois imbitable pour les néophytes...)
    Tu confonds courbe d'apprentissage et productivité. Le langage Perl est certainement plus difficile à apprendre que le langage Python, mais une fois le langage Perl maîtrisé, un développeur Perl écrira un programme en Perl beaucoup plus rapidement que le même programme qu'en langage C.

  7. #7
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    décembre 2003
    Messages
    1 868
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : décembre 2003
    Messages : 1 868
    Points : 2 787
    Points
    2 787
    Par défaut
    Bonjour.

    Le jour où l'auteur comprendra que les OS ne sont pas temps réel, il va se faire de sacrés nœuds au cerveau, en plus du JIT.

  8. #8
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    4 051
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 4 051
    Points : 7 271
    Points
    7 271
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par abriotde Voir le message
    Oui on parle bien de JIT, javascript est pris en exemple.
    Je ne suis pas d'accord.

    L'article ne parle QUE de JavaScript et de problématiques PUREMENT JAVASCRIPT.

    Le meilleur exemple, c'est que le JIT est expliqué comme mode de fonctionnement du Java (le .class, le bytecode, etc.)

    Et pourtant, il ne fait que comparer le JIT merdique de JavaScript avec... Java ! Qui tout d'un coup ne serait plus JIT, comme par enchantement !

    Si JavaScript n'est pas optimisable à cause du JIT, et que c'est le principe même du JIT qui pose problème, alors Java souffre du même problème (tout comme .NET qui, si je ne m'abuse, est le père du JIT, je trouve ça assez surprenant qu'il ne soit même pas mentionné).

    Enfin, je ne suis pas d'accord avec la description du JIT : faite dans l'article. Le bytecode n'est pas interprété (ce que faisait VB6 ou Java 1.4) mais bien compilé en code natif au moment du premier appel (ce que fait .NET depuis la version 1.0).
    On ne jouit bien que de ce qu’on partage.

  9. #9
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    octobre 2005
    Messages
    261
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : octobre 2005
    Messages : 261
    Points : 651
    Points
    651
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Le bytecode n'est pas interprété (ce que faisait VB6 ou Java 1.4) mais bien compilé en code natif au moment du premier appel (ce que fait .NET depuis la version 1.0).
    Désolé pour le déterrage mais petite correction : VB6 permet de compiler vers du code natif ou du byte code au choix.
    Et ce n'est pas une fonctionnalité expérimentale (genre AOT compiler) avec un outil à télécharger Dieu sais où : c'était dans l'IDE de base et je ne me souviens pas avoir faire de compilation vers du byte code.
    Ce qui était irritant et ce pourquoi les développeur VB6 se faisaient charrier à l'époque par les développeurs C et Delphi était (outre le code natif dégueulasse) que l'exécutable généré n'était pas "standalone". Il dépendait de dlls de la VM VB, il fallait donc que ces dll soient déployées sur le poste pour que le .exe fonctionne.

    Pour ce qui est de Abe Winter, il enfonce des portes ouvertes...
    Pour optimiser au cycle d'horloge près, il faut un langage/IDE qui permette de très rapidement visualiser le code machine (désassemblé) qui correspond à une section du code source.
    Et c'est encore mieux si le langage permet d'écrire de l'assembleur en ligne.

  10. #10
    Membre extrêmement actif
    Homme Profil pro
    Inscrit en
    janvier 2014
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : janvier 2014
    Messages : 1 044
    Points : 3 884
    Points
    3 884
    Par défaut
    Faux, il était possible de faire un package code VB6 plus runtime mais cela n'à rien à voir avec la compilation native C++ ou Delphi qui eux disposent d'un vrai compilateur.

    C'était juste du bullshit marketing.
    « L’humour est une forme d'esprit railleuse qui s'attache à souligner le caractère comique, ridicule, absurde ou insolite de certains aspects de la réalité »

  11. #11
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    octobre 2005
    Messages
    261
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : octobre 2005
    Messages : 261
    Points : 651
    Points
    651
    Par défaut
    Du bytecode c'est quelque chose que le processeur de madame Michou n'est pas capable d'exécuter directement.
    Pour pouvoir tourner, le bytecode est soit compilé juste à temps soit interprété.
    C'est par exemple le cas du bytecode java, .NET et aussi du P-Code de VB6.

    A l'inverse, le code machine (ou le code natif), c'est quelque chose que le processeur de madame Michou est capable d'exécuter directement.
    Madame Michou a un PC Windows ou Linux qui comprend uniquement les jeux d'instructions Intel 16, 32 et 64 bits.
    Donc du code natif dans ce cas ce sont des instructions Intel 16, 32 ou 64 bits.

    Jusque là on est d'accord, non ? Maintenant la partie où on ne devrait plus l'être :
    Tout comme le C, le source VB6 est généralement compilé vers du code natif.

    Si vous n'êtes pas d'accord avec ça c'est que soit :
    • Vous considérez que le code natif généré est tellement mauvais que ce n'est plus du code natif.
    • Vous avez lu quelque part que le VB6 était compilé vers du bytecode, et vous l'avez cru sur parole.


    Dans le premier cas, j'ai envie de vous dire qu'un chat, aussi moche soit-il, est un chat. Non, un code natif dégueulasse ne se transforme en bytecode par magie.
    Dans le deuxième cas, voici une implémentation de la suite de Fibonacci en VB6 :
    Code vb : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Dim first, second, temp, i As Long
     
    first = 0
    second = 1
    For i = 1 To n
        temp = first + second
        first = second
        second = temp
    Next
    fibonnaci = first

    Et voici les instructions correspondantes désassemblées et annotées par mes soins depuis le .exe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    :loop
    
    00401d4b 8b4588          mov     eax,dword ptr [ebp-78h]                       eax = n
    00401d4e 3bf8            cmp     edi,eax                                       comparaison de i et n
    00401d50 8d45bc          lea     eax,[ebp-44h]                                 eax -> first
    00401d53 50              push    eax
    00401d54 7f2e            jg      Project1+0x1d84 (00401d84)                    jump exit_loop if edi (i) > eax (n)
    
    00401d56 8d4dcc          lea     ecx,[ebp-34h]                                 ecx -> second
    00401d59 8d55a0          lea     edx,[ebp-60h]                                 edx -> XXX
    00401d5c 51              push    ecx
    00401d5d 52              push    edx
    00401d5e ff1588104000    call    dword ptr [Project1+0x1088 (00401088)]        _vbaVarAdd XXX = first + second
    
    00401d64 8bd0            mov     edx,eax                                       edx -> XXX
    00401d66 8d4ddc          lea     ecx,[ebp-24h]                                 ecx -> temp
    00401d69 ffd6            call    esi                                           _vbaVarMove temp = XXX
    
    00401d6b 8d55cc          lea     edx,[ebp-34h]                                 edx -> second
    00401d6e 8d4dbc          lea     ecx,[ebp-44h]                                 ecx -> first
    00401d71 ffd3            call    ebx                                           _vbaVarCopy first = second
    
    00401d73 8d55dc          lea     edx,[ebp-24h]                                 edx -> temp
    00401d76 8d4dcc          lea     ecx,[ebp-34h]                                 ecx -> second
    00401d79 ffd3            call    ebx                                           _vbaVarCopy second = temp
    
    00401d7b b801000000      mov     eax,1
    00401d80 03f8            add     edi,eax                                       i++
    00401d82 ebc7            jmp     Project1+0x1d4b (00401d4b)                    jmp loop
    
    :exit_loop
    On voit que le compilateur a transformé mon source en code natif.
    Et c'est le comportement par défaut de l'IDE.
    Certe du code très lent avec des appels de fonctions superflues pour les additions et les affectations. Mais pas du byte code.
    Non, un .exe natif VB ce n'est pas une VM VB6 + le byte code.

    Il me semble avoir fourni une preuve, donc si vous contestez toujours mes affirmations, je vous invite à venir avec du concret et pas des rumeurs.


    Au fait, si vous pensez que jamais un compilo C ne génèrerait dans votre dos des appels vers des fonctions d'une grosse dépendance...
    Je vous invite à vous renseigner sur _fltused, __chkstk, memcmp/memcpy/memset/memmove, _alldiv...
    Une des formes de cette grosse dépendance s'appelle le redistributable package, 14 Mo.

    Et si vous pensez que la fonction "main" c'est la première et dernière chose exécutée dans le .exe...
    Je vous invite à vous renseigner sur WinMainCRTStartup/mainCRTStartup, -nodefaultlib, -ffreestanding...

  12. #12
    Membre extrêmement actif
    Homme Profil pro
    Inscrit en
    janvier 2014
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : janvier 2014
    Messages : 1 044
    Points : 3 884
    Points
    3 884
    Par défaut
    Tu n'a rien prouvé du tout avec ton blabla qui mélange tout.
    Des benchmarks ont été faits qui ont montré que la différence de performance entre compiler en pcode ou en natif avec VB6 est minime, genre 1% d'amélioration, parce que c'est bidon, c'est du bullshit marketing, qui a été inventé à l'époque par le marketing justement pour faire croire que c'est du natif comme C++ ou Delphi, mais c'est faux.

    Créer un package .exe qui encapsule à la fois un runtime et du pcode n'à rien à voir avec de la compilation native, comme le fait un compilateur C, C++ ou Delphi.

    De fait les éditeurs de logiciels font généralement des logiciels avec C++ ou parfois Delphi mais absolument pas avec VB6.

    Par exemple Windev c'est pas de la compilation native, par contre Windev est développé en C++.
    « L’humour est une forme d'esprit railleuse qui s'attache à souligner le caractère comique, ridicule, absurde ou insolite de certains aspects de la réalité »

  13. #13
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    octobre 2005
    Messages
    261
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : octobre 2005
    Messages : 261
    Points : 651
    Points
    651
    Par défaut
    Mon blabla ne prouve rien en effet. Tout comme le tien.

    Mais le code assembleur ne ment pas. La réalité technique est que le .exe contient mon algo en code natif, pas en bytecode.

    Par contre je suis entièrement d'accord depuis le début pour dire que le VB6 est un escargot paraplégique comparé à du C ou du Delphi.

    [edit]

    Même exercice en C, compilation du code suivant avec gcc en 32 bits sans optimisations :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int first, second, temp, i;
     
    first = 0;
    second = 1;
    for (i = 0; i < n; i++)
    {
      temp = first + second;
      first = second;
      second = temp;
    }
    return first;

    Désassemblage du .exe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    0040153f c745f400000000  mov     dword ptr [ebp-0Ch],0         first = 0
    00401546 c745f001000000  mov     dword ptr [ebp-10h],1         second = 1
    0040154d c745ec00000000  mov     dword ptr [ebp-14h],0         i = 0
    00401554 eb1b            jmp     fibonnaci+0x1571 (00401571)   jmp second_label
    
    first_label
    00401556 8b55f4          mov     edx,dword ptr [ebp-0Ch]       edx = first
    00401559 8b45f0          mov     eax,dword ptr [ebp-10h]       eax = second
    0040155c 01d0            add     eax,edx                       eax = first + second
    0040155e 8945e8          mov     dword ptr [ebp-18h],eax       temp = eax
    00401561 8b45f0          mov     eax,dword ptr [ebp-10h]       eax = second
    00401564 8945f4          mov     dword ptr [ebp-0Ch],eax       first = second
    00401567 8b45e8          mov     eax,dword ptr [ebp-18h]       eax = temp
    0040156a 8945f0          mov     dword ptr [ebp-10h],eax       second = temp
    0040156d 8345ec01        add     dword ptr [ebp-14h],1         i++
    
    second_label
    00401571 8b45ec          mov     eax,dword ptr [ebp-14h]       eax = i
    00401574 3b4508          cmp     eax,dword ptr [ebp+8]         comparaison de i avec n
    00401577 7cdd            jl      fibonnaci+0x1556 (00401556)   jmp first_label si i < n
    00401579 8b45f4          mov     eax,dword ptr [ebp-0Ch]       Mise en place du résultat dans eax
    Est ce que ce code natif est plus rapide que celui produit par le VB6 ? Oui et dans des proportions astronomiques, pas juste un facteur 2 ou 10. Le principal problème de celui de VB6 c'est l'utilisation de l'instruction call dans la boucle qui coûte un bras sans même considérer ce qui est appellé.

    Mais est ce fondamentalement différent ? Non. Dans les deux cas bin c'est des instructions jmp/mov/lea sur des registres eax/edx/ebp... Du code natif x86 quoi.
    Si vous désassemblez du bytecode Java ou .NET ça sera très différent au niveau des instructions et des opérandes, et du Chinois pour un processeur.

    [edit 2]

    Et pour le C#, ça donne quoi ?
    Comme Abe Winter le remarque, c'est plus difficile de travailler avec un langage qui compile en bytecode:
    1. Il n'y a pas de code natif dans l'exécutable.
    2. Le code natif généré à l'exécution peut varier d'une exécution à l'autre et dépend bien sûr du compilo JIT et de sa version.


    Mais en théorie, à l'exécution, le bytecode est compilé en code natif dans la mémoire du processus puis exécuté.
    Donc avec un bon débogueur genre WinDbg et un point d'arrêt bien senti, on peut retrouver le code natif que voici (.Net Core 5) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    00007ffe`0b69c003 33c0            xor     eax,eax                    eax = 0
    00007ffe`0b69c005 8945fc          mov     dword ptr [rbp-4],eax      first = 0
    00007ffe`0b69c008 c745f801000000  mov     dword ptr [rbp-8],1        second = 1
    00007ffe`0b69c00f 8945f0          mov     dword ptr [rbp-10h],eax    i = 0
    00007ffe`0b69c012 90              nop
    00007ffe`0b69c013 eb1f            jmp     00007ffe`0b69c034          jmp second_label
    
    first_label:
    00007ffe`0b69c015 90              nop
    00007ffe`0b69c016 8b45fc          mov     eax,dword ptr [rbp-4]      eax = first
    00007ffe`0b69c019 0345f8          add     eax,dword ptr [rbp-8]      eax = eax + second
    00007ffe`0b69c01c 8945f4          mov     dword ptr [rbp-0Ch],eax    temp = eax
    
    00007ffe`0b69c01f 8b45f8          mov     eax,dword ptr [rbp-8]      eax = second
    00007ffe`0b69c022 8945fc          mov     dword ptr [rbp-4],eax      first = eax
    
    00007ffe`0b69c025 8b45f4          mov     eax,dword ptr [rbp-0Ch]    eax = temp
    00007ffe`0b69c028 8945f8          mov     dword ptr [rbp-8],eax      second = temp
    
    00007ffe`0b69c02b 90              nop
    
    00007ffe`0b69c02c 8b45f0          mov     eax,dword ptr [rbp-10h]    eax = i
    00007ffe`0b69c02f ffc0            inc     eax                        eax++
    00007ffe`0b69c031 8945f0          mov     dword ptr [rbp-10h],eax    i = eax
    
    second_label:
    00007ffe`0b69c034 8b45f0          mov     eax,dword ptr [rbp-10h]    eax = i
    00007ffe`0b69c037 3b4510          cmp     eax,dword ptr [rbp+10h]    comparaison entre i et n
    00007ffe`0b69c03a 0f9cc0          setl    al                         al = 1 si i < n, donc s'il faut boucler
    00007ffe`0b69c03d 0fb6c0          movzx   eax,al                     eax = al
    00007ffe`0b69c040 8945ec          mov     dword ptr [rbp-14h],eax    [rbp-14h] = eax
    00007ffe`0b69c043 837dec00        cmp     dword ptr [rbp-14h],0      comparaison de 0 avec 1 ou 0
    00007ffe`0b69c047 75cc            jne     00007ffe`0b69c015          jmp first_label si [rbp-14h] != 0
    00007ffe`0b69c049 8b45fc          mov     eax,dword ptr [rbp-4]      Mise en place du résultat dans eax
    C'est donc encore une fois du code natif, mais contrairement au C et VB6, ce code est généré à l'exécution chez le client, et non à la compilation chez le développeur.
    Niveau performance, il devrait être assez proche du code natif produit par le C. Il est plus fastidieux notamment pour le test de la boucle mais ce n'est pas aussi affreux que le code natif produit par VB6.
    Attention cette petite comparaison ne veut pas du tout dire que le C# est presque aussi rapide que le C... Il y a plein d'autres facteurs, trop pour en parler ici.

    Java au prochain épisode ?

  14. #14
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    mai 2004
    Messages
    9 907
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : mai 2004
    Messages : 9 907
    Points : 27 052
    Points
    27 052
    Par défaut
    Hello,
    Citation Envoyé par StringBuilder Voir le message
    Si JavaScript n'est pas optimisable à cause du JIT, et que c'est le principe même du JIT qui pose problème, alors Java souffre du même problème (tout comme .NET qui, si je ne m'abuse, est le père du JIT, je trouve ça assez surprenant qu'il ne soit même pas mentionné).
    JIT : smalltalk, 1983 (https://en.wikipedia.org/wiki/Just-i...lation#History)


    Pour moi, tout ce que dit ce monsieur est d'une évidence navrante.
    J'ai bossé un peu chez Sun Microsystems sur la JVM Java (début des années 2000, OK ça fait un bail, et non vous ne pouvez pas le vérifier), ces problématiques de JIT m'ont clairement été expliquées, et les problématiques étaient exactement les mêmes : que compiler et pourquoi ? Comment tu choisis que tu vas plutôt compiler cette fonction plutôt qu'une autre, et tu peux pousser sur les différentes optimisations de compilation, et pleins d'autres problématiques super intéressantes, mais qui n'ont rien de nouveau.

    « Je voudrais une collecte de statistiques efficace sur les dépôts en prod, donc je sais quelles fonctions traiter comme des hot paths.
    Mais ce que ne voit pas ce monsieur, c'est que la manière dont moi j'utilise un logiciel n'est pas la même que sa manière d'utiliser le même logiciel. Bien sûr, si on prend un hello world de 5 lignes, il n'y a qu'un seul chemin critique, donc c'est simple. Mais si je prends un navigateur, celui qui a 200 onglets d'ouvert et 15 signets n'a pas la même utilisation que celui qui a 20 000 signets mais pas plus de 3 onglets -- c'est le même logiciel, mais le choix des fonctions à compiler par le JIT ne sont clairement pas les mêmes.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

Discussions similaires

  1. Debugger just in time VS 2008
    Par Faiche dans le forum Visual Studio
    Réponses: 1
    Dernier message: 27/04/2008, 14h18
  2. Compiler Just In Time
    Par eclesia dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 17/01/2007, 11h58
  3. Réponses: 3
    Dernier message: 24/08/2005, 14h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo