Compilateur Just-In-Time (JIT) : qu'est-ce que c'est et comment ça marche en programmation

La programmation ne consiste pas seulement à écrire du code dans un éditeur. C'est l'ensemble du processus à partir du moment où nous préparons le projet, écrivons le pseudo-code et le convertissons en code jusqu'à ce que nous le compilions, le déboguions et vérifiions que, en fait, il fonctionne correctement. Toutes ces étapes sont importantes dans un projet. Mais l'un de ceux dont on sait le moins comment ils fonctionnent, et les différents types qui existent est le dernier, la compilation. Et c'est ce que nous allons apprendre aujourd'hui.

Qu'est-ce que la compilation ?

Compilateur juste-à-temps (JIT)

A moins de programmer en binaire, ou dans un langage de très très bas niveau, comme l'assembleur, les machines ne comprennent pas les lignes de code que nous écrivons. Et plus le langage que nous utilisons est élevé, plus il sera naturel pour nous, mais plus il sera complexe pour la machine. Et c'est pourquoi, pour convertir notre langage de haut niveau en langage machine, nous devons compiler le code .

La compilation du code est le processus par lequel nous convertissons nos lignes de code de haut niveau en langage machine. Pour ce faire, il faut d'une part disposer d'un fichier texte en clair avec tout le code, et d'autre part un programme, le compilateur , qui se charge de convertir chacune des lignes de code en binaire ou dans le langage de bas niveau correspondant.

Programme de compilation Esquema

Grâce à l'utilisation de ces compilateurs, la programmation est très simple, et un même code peut être utilisé, moyennant quelques ajustements, sur plusieurs types de machines différents. De plus, étant donné que ces programmes sont optimisés pour fonctionner sur des architectures spécifiques, ils ont tendance à offrir de bonnes performances globales. Cependant, pas tous les avantages. Un programme compilé ne fonctionnera que sur la machine pour laquelle le compilateur est conçu, par exemple un x64 Processeur or BRAS processeur. Il est également nécessaire de compiler plusieurs fois le même programme selon les systèmes d'exploitation (WindowsmacOS, Linux/Unix, Android, iOS, etc.) où nous allons l'exécuter.

Différences avec l'interprète

Interprètes sont créés précisément pour résoudre les deux problèmes que nous venons de voir dans les compilateurs. Ce sont des programmes qui s'exécutent entre notre code d'origine et notre machine et sont chargés d'interpréter chacune des instructions en fonction de la machine ou du système d'exploitation où nous l'exécutons.

Ces interpréteurs sont placés au même point où les compilateurs commenceraient à traduire le code. Ainsi, ils éliminent toutes les limitations du système d'exploitation ou de la plate-forme, étant capables d'utiliser le même code pour tout.

Bien sûr, on ne peut pas penser qu'un interprète soit parfait. La première chose à garder à l'esprit est que ceux-ci ne sont pas valables pour tous les types de langages de programmation. Les interpréteurs peuvent fonctionner, par exemple, avec Python ou JavaScript, mais ils ne seraient pas exploitables dans d'autres langages, tels que C++. Aussi, devoir interpréter le code en même temps qu'il est exécuté implique une perte de performances considérable en devant traduire et manipuler chaque instruction comme s'il s'agissait d'un compilateur séparé.

Et c'est là que les compilateurs JIT entrent en jeu.

Qu'est-ce qu'un compilateur juste-à-temps

Alors qu'un compilateur normal est chargé de compiler tout le code lorsque nous allons exécuter le programme, de convertir le code en binaire et de générer l'exécutable, le compilateur JIT optimise ce travail en compiler uniquement le code de chaque fonction lorsque cela est nécessaire. .

De cette façon, lorsque nous allons exécuter un programme, le compilateur Just-In-Time, ou JIT, ne compilera que les fonctions qui vont être utilisées à ce moment-là, en sauvegardant le résultat dans un cache. Au fur et à mesure que nous utilisons le programme, lorsque nous rencontrons une nouvelle fonction qui n'a pas encore été compilée, elle est à nouveau compilée. Mais, lorsque nous trouvons une fonction qui a déjà été utilisée, au lieu de la compiler à nouveau, elle est recherchée dans le cache, ce qui permet de gagner un temps considérable.

Quelques exemples d'utilisation compilateurs JIT sont les suivants:

  • Java : la machine virtuelle Java, JVM, utilise le juste-à-temps.
  • .NET Framework – L'environnement de programmation de Microsoft.
  • C# : CLR (Common Language Runtime).
  • Android : lorsqu'il est utilisé avec DVM (Dalvik Virtual Machine) ou ART (Android RunTime).
  • Émulateurs : ces compilateurs sont également utilisés dans les émulateurs pour consoles et autres PC. C'est ainsi que le code machine est traduit d'une architecture CPU à une autre.

Compiler JIT Java

Ces types de compilateurs ont de meilleures performances que les interprètes , car, au lieu d'interpréter tout le code, ils compilent ce dont ils ont besoin comme ils en ont besoin. Cependant, devoir compiler le code à l'exécution a un impact plus ou moins important sur les performances par rapport à l'utilisation d'un compilateur standard qui génère le binaire et permet de l'exécuter directement sur la machine. Et plus le programme que nous essayons d'exécuter est grand, plus l'impact sur les performances est important. Cela fait que certains programmes très volumineux mettent jusqu'à une minute pour exécuter les premières fonctions.

Pour réduire cet impact, il existe des pré-compilateurs tels que MicrosoftGénérateur d'images natif de (Ngen) , qui se chargent d'éliminer le temps d'exécution et de faire fonctionner le compilateur JIT dès le départ.

De plus, comme la compilation Just-In-Time utilise principalement des données exécutables, la protégeant des exploits potentiels est un défi majeur pour les développeurs. La mémoire doit être surveillée de près et protégée par des techniques de sécurité avancées, telles que l'isolement, pour éviter de prendre des risques inutiles.

Optimiser le compilateur JIT (Just-In-Time)

Selon le type de compilateur que nous utilisons, il est possible de trouver différents niveaux d'optimisation du code. Par exemple, dans le cas de OuvrirJ9 (compilateur Eclipse JIT pour le code Java ), il est possible de choisir le niveau d'optimisation du code que l'on souhaite. Plus l'optimisation du compilateur Just-In-Time est élevée, plus le code s'exécutera rapidement sur notre ordinateur, bien sûr, au prix d'une utilisation beaucoup plus importante de RAM et CPU.

De plus, ces compilateurs sont conçus pour analyser et tracer les fonctions d'un programme et détecter celles qui sont les plus répétées. Ainsi, certaines optimisations leur sont appliquées, et celles qui sont les moins appelées, les laissant un peu en arrière-plan pour éviter une utilisation inutile des ressources.