• # Petites corrections

    Posté par . En réponse au journal JavaScript, performances, et Firefox. Évalué à 3.

    Ta nouvelle est très intéressante. Comme tu as laissé quelques fautes, dont certaines piquent très fort les yeux, je me permets de les indiquer ci-dessous.

    Je ne vais pas parler dans ce journal du langage JavaScript lui même, des ses fonctionnalités, ni même discuter de sa qualité. JavaScript existe dans son état actuel, et son importance est telle sur le web qu'il est invraisemblable d'envisager un navigateur entièrement fonctionnel qui ne permette pas de l’exécuter.

    Sans tomber dans un tutoriel complet de JavaScript (que je serais de toute manière incapable d'écrire), il y a quelques caractéristiques du langage qui jouent un rôle important dans les problèmes que peut (削除) représenter (削除ここまで) poser son implémentation.

    Les variables n'ont pas de type associé(削除) , qui est (削除ここまで) connu statiquement. Les types sont associé(削除) e (削除ここまで)s aux valeurs, ce qui permet d'associer n'importe quelle valeur à n'importe quelle variable.

    Un type est associé à "2" qui est un nombre à virgule flo(削除) a (削除ここまで)ttante double précision et à "Hello world" qui est une chaîne de caractère.
    Fonctions de premier ordre

    Les fonctions sont traitées comme des valeurs. Elles peuvent être passée en argument, retourner (削除) comme (削除ここまで) un résultat, être assignées à une variable, etc.

    ajout de deux entiers,
    ajout de deux flo~~a~~**t**tants,
    concaténation de deux chaines,…
    
    

    L'interpréteur doit distinguer selon les cas pour décider quelle opération exécuter, et pour cela, il a besoin des types. Les valeurs doivent donc embarquer des informations sur leur type, encapsul(削除) er (削除ここまで)ées dans une structure de donn(削除) er (削除ここまで)ées. Une valeur encapsul(削除) er (削除ここまで)ée contient donc sa valeur et son type.

    Une variable ne peut contenir qu'une valeur encapsulée, pour permettre à l’interpréteur d'appeler les bonnes opérations sur leur valeur, mais pour effectuer l'opération elle même, il faut dé-encapsuler la valeur.

    L'idée de la compilation à la volée (Just-in-time) est de compiler le bytecode vers du code natif avant de l’exécuter. Cette opération permet de gagner du temps, en effet, supposons que le JIT compile le bytecode vers du code machine, (削除) avec (削除ここまで) alors il ne reste plus qu'a exécuter ce code qui va :

    Il y a deux réponse à cette question. La première est entièrement pragmatique, et c'est celle employée par la majorité des navigateurs. Le code JavaScript qui n'est exécut(削除) e (削除ここまで)é qu'une seule fois peut être lent, c'est triste, mais ce n'est pas dramatique. Par contre, il est utile d’optimiser du code important, qui est exécut(削除) e (削除ここまで)é plusieurs milliers de fois.

    Seulement, même si cette technique (削除) à (削除ここまで) a de grandes chances de permettre de rester dans le code compilé, elle ne permet pas de supprimer les garde-fous.

    Brian Hackett a donc écrit une inférence de types pour JavaScript. En analysant le code, et en appliquant des règles de typages, on peut prouver que certains variables ont un type donné, ou du moins un ensemble de types possible ! Le gros problème de JavaScript, c'est que son typage n'est pas déterministe, c'est à dire qu'on ne peut pas prouver le type de n'importe quelle variable en ne regardant que le code. C'est sûrement le plus gros défaut et problème de JavaScript en ce qui concerne la performance.

    Si l'ont connaît le type exact des variables locales, alors, le code compilé pour effectuer une opération effectue les étapes suivantes :

    Le principe des objets par prototypage entraîne un autre problème : l’accès aux propriétés d'un objet. Pour accéder à une propriété a, il faut chercher dans cet objet, puis potentiellement dans toute la chaine de ses prototypes. Encore quelque chose de lent… Une fois la propriété trouvée, il suffit d'en lire la valeur, ce qui est rapide.

    La forme des objets est gardée en cache, et ce cache contient des méthodes optimisées pour accéder aux propriétés connues. Cette méthode peut s'avérer plus lente quand la chaîne des formes est assez longue et qu'on désire accéder à une propriété du prototype de base. Cela peut par exemple se produire dans les cas des clôtures imbriquées, o(削除) u (削除ここまで)ù un nouvel objet est généré pour chaque clôture.

    IonMonkey est un nouveau compilateur à la volée, encore en développement dans une branche à part. Son but est de produire du code bien plus optimisé que celui produit par JaëgerMonkey. Pour cela, il est construit selon une architecture classique des compilateurs. L'idée actuelle du pipeline est la suivante :

    Enfin, la LIR est transformée en code machine, puis exécutée. Des points de restauration(削除) s (削除ここまで) sont placés dans le code, qui permette de retourner de manière correcte dans la machine virtuelle en cas d'invalidation.

    L'autre problème fondamental de JavaScript est la gestion de la mémoire. Cette gestion n'est pas explicite dans le langage, elle doit être gérée par l’interpréteur. Quand un nouvel objet est créé sur le tas, de la mémoire est allouée pour le stocker. Tout le problème consiste à savoir quand libérer cette mémoire. Note : je fais ici quelques simplifications, notamment, je ne parle pas des Weak references, ni du fait que des objets JavaScript peuvent être liés à des objets C++ dans Firefox, ce qui complique encore les choses.

    L'idée est de trouver les objets en mémoire qui ne sont plus référencé(削除) e (削除ここまで)s, pour pouvoir les supprimer.

    A partir de ces pointeurs, appelés racines, on va marqu(削除) é (削除ここまで)er tout les objets qui sont atteignable.

    Le GC incrémental sépare donc les phases de marquage et de collection en plusieurs petites phases entre lesquelles s’intercale l’exécution du code du navigateur. La difficulté de cette approche consiste à gérer les modifications du tas qui ont lieu quand le GC est en pause. Il a fallut écrire tout(削除) e (削除ここまで) un mécanisme de garde-fous qui surveille les écritures dans le tas et en informe le GC.

    Une manière de le résoudre est d'implémenter un "Moving GC". C'est l(削除) a (削除ここまで)à dessus que porte une partie du travail actuel.

    L'implémentation d'un interpréteur JavaScript performant est donc loin d'être un problème trivial. Malgré les efforts des développeurs, la performance de JavaScript dépend(削除) ant (削除ここまで) de beaucoup de choses, et la façon d'écrire un code peut influer beaucoup sur ses performances (beaucoup peut être un facteur 100 !). Si vous êtes développeurs JavaScript, il y a des bonnes pratiques à respecter, mais réjouissez vous, de nouveaux outils apparaissent pour vous aide(削除) z (削除ここまで)r, comme l'extension JITinspector ou le nouveau profiler