Maison > Java > javaDidacticiel > le corps du texte

Explorer Graal : compilation JIT de nouvelle génération pour Java

WBOY
Libérer: 2024-08-31 16:36:32
original
815 Les gens l'ont consulté

Le compilateur Graal constitue un bond en avant radical dans la technologie de compilation dynamique Just-In Time (JIT). Considéré comme un facteur important derrière les performances impressionnantes de Java, le rôle et la fonction de la compilation JIT au sein de l'architecture de la machine virtuelle Java (JVM) laisse souvent perplexes de nombreux praticiens en raison de sa nature complexe et plutôt opaque.

Qu'est-ce qu'un compilateur JIT ?

Lorsque vous exécutez la commande javac ou utilisez l'IDE, votre programme Java est converti du code source Java en bytecode JVM. Ceci
Le processus crée une représentation binaire de votre programme Java - un format beaucoup plus simple et compact que le code source d'origine.

Les processeurs classiques présents sur votre ordinateur ou votre serveur sont cependant incapables d'exécuter directement le bytecode JVM. Cela nécessite que la JVM interprète le bytecode.

Exploring Graal: Next-Generation JIT Compilation for Java

Figure 1 – Comment fonctionne un compilateur juste à temps (JIT)

Les interprètes peuvent souvent être sous-performants par rapport au code natif exécuté sur un processeur réel, ce qui motive la JVM à appeler un autre compilateur au moment de l'exécution : le compilateur JIT. Le compilateur JIT traduit votre bytecode en code machine que votre processeur peut exécuter directement. Ce compilateur sophistiqué exécute une gamme d'optimisations avancées pour générer un code machine de haute qualité.

Ce bytecode agit comme une couche intermédiaire, permettant aux applications Java de s'exécuter sur différents systèmes d'exploitation avec différentes architectures de processeur. La JVM elle-même est un logiciel qui interprète ce bytecode instruction par instruction.

Le compilateur Graal JIT – Il est écrit en Java

L'implémentation OpenJDK de la JVM contient deux compilateurs JIT conventionnels : le compilateur client (C1) et le compilateur serveur (C2 ou Opto). Le compilateur client est optimisé pour un fonctionnement plus rapide et une sortie de code moins optimisée, ce qui le rend idéal pour les applications de bureau où des pauses prolongées de compilation JIT peuvent interrompre l'expérience utilisateur. À l'inverse, le compilateur de serveur est conçu pour passer plus de temps à produire du code hautement optimisé, ce qui le rend adapté aux applications serveur de longue durée.

Les deux compilateurs peuvent être utilisés en tandem grâce à une « compilation à plusieurs niveaux ». Dans un premier temps, le code est compilé via C1, suivi de C2 si la fréquence d'exécution justifie le temps de compilation supplémentaire.

Développé en C++, le C2, malgré ses caractéristiques performantes, présente des inconvénients inhérents. C++ est un langage dangereux ; par conséquent, des erreurs dans le module C2 pourraient provoquer le crash de l’ensemble de la VM. La complexité et la rigidité du code C++ hérité ont également fait de sa maintenance et de son extensibilité un défi important.

Unique à Graal, ce compilateur JIT est développé en Java. La principale exigence du compilateur est d'accepter le bytecode JVM et de produire du code machine – une opération de haut niveau qui ne nécessite pas de langage au niveau système comme C ou C++.

Graal étant écrit en Java offre plusieurs avantages :

  • Sécurité améliorée : L'approche de récupération de place et de mémoire gérée de Java élimine le risque de pannes liées à la mémoire du compilateur JIT lui-même.

  • Maintenance et extension plus faciles : La base de code Java est plus accessible aux développeurs pour contribuer et étendre les capacités du compilateur JIT.

  • Portabilité : L'indépendance de la plate-forme Java se traduit par le fait que le compilateur Graal JIT fonctionne potentiellement sur n'importe quelle plate-forme avec une machine virtuelle Java.

L'interface du compilateur JVM (JVMCI)

L'interface du compilateur JVM (JVMCI) est une fonctionnalité innovante et une nouvelle interface dans la JVM (JEP 243 : https://openjdk.org/jeps/243).
Tout comme l'API de traitement des annotations Java, JVMCI permet également l'intégration d'un compilateur Java JIT personnalisé.

L'interface JVMCI comprend une fonction pure d'octet en octet[] :

interface JVMCICompiler {

  byte[] compileMethod(byte[] bytecode);
}
Copier après la connexion

Cela ne rend pas compte de toute la complexité des scénarios réels.

Dans les applications pratiques, nous avons fréquemment besoin d'informations supplémentaires telles que le nombre de variables locales, la taille de la pile et les données collectées à partir du profilage dans l'interpréteur pour mieux comprendre les performances du code. Par conséquent, l’interface prend une entrée plus complexe. Au lieu d'un simple bytecode, il accepte une CompilationRequest :

public interface JVMCICompiler {

  int INVOCATION_ENTRY_BCI = -1;

  CompilationRequestResult compileMethod(CompilationRequest request);
}
Copier après la connexion

JVMCICompiler.java

Une CompilationRequest encapsule des informations plus complètes, telles que la méthode Java destinée à la compilation, et potentiellement beaucoup plus de données nécessaires au compilateur.

CompilationRequest.java

This approach has the benefit of providing all necessary details to the custom JIT-compiler in a more organized and contextual manner. To create a new JIT-compiler for the JVM, one must implement the JVMCICompiler interface.

Ideal Graph

An aspect where Graal truly shines in terms of performing sophisticated code optimization is in its use of a unique data structure: the program-dependence-graph, or colloquially, an "Ideal Graph".

The program-dependence-graph is a directed graph that presents a visual representation of the dependencies between individual operations, essentially laying out the matrix of dependencies between different parts of your Java code.

Let's illustrate this concept with a simple example of adding two local variables, x and y. The program-dependence-graph for this operation in Graal's context would involve three nodes and two edges:

  • Nodes:

    • Load(x) and Load(y): These nodes represent the operations of loading the values of variables x and y from memory into registers within the processor.
    • Add: This node embodies the operation of adding the values loaded from x and y.
  • Edges:

    • Two edges would be drawn from the Load(x) and Load(y) nodes to the Add node. These directional paths convey the data flow. They signify that the values loaded from x and y are the inputs to the addition operation.
      +--------->+--------->+
      | Load(x)  | Load(y)  |
      +--------->+--------->+
                 |
                 v
              +-----+
              | Add |
              +-----+
Copier après la connexion

In this illustration, the arrows represent the data flow between the nodes. The Load(x) and Load(y) nodes feed their loaded values into the Add node, which performs the addition operation. This visual representation helps Graal identify potential optimizations based on the dependencies between these operations.

This graph-based architecture provides the Graal compiler with a clear visible landscape of dependencies and scheduling in the code it compiles. The program-dependence-graph not only maps the flow of data and relationships between operations but also offers a canvas for Gaal to manipulate these relationships. Each node on the graph is a clear candidate for specific optimizations, while the edges indicate where alterations would propagate changes elsewhere in the code - both aspects influence how Graal optimizes your program's performance.

Visualizing and analyzing this graph can be achieved through a tool called the IdealGraphVisualizer, or IGV. This tool is invaluable in understanding the intricacies of Graal's code optimization capabilities. It allows you to pinpoint how specific parts of your code are being analyzed, modified, and optimized, providing valuable insights for further code enhancements.

Let's consider a simple Java program that performs a complex operation in a loop:

public class Demo {
 public static void main(String[] args) {
        for (int i = 0; i < 1_000_000; i++) {
            System.err.println(complexOperation(i, i + 2));
        }
    }

    public static int complexOperation(int a, int b) {
        return ((a + b)-a) / 2;
    }
}
Copier après la connexion

When compiled with Graal, the Ideal Graph for this program would look something like this(Figure 2).

Exploring Graal: Next-Generation JIT Compilation for Java

Figure 2 – Graal Graphs

Therefore, along with its method level optimizations and overall code performance improvements, this graph-based representation constitutes the key to understanding the power of the Graal compiler in optimizing your Java applications

In Conclusion

The Graal JIT compiler represents a significant leap forward in Java performance optimization. Its unique characteristic of being written in Java itself offers a compelling alternative to traditional C-based compilers. This not only enhances safety and maintainability but also paves the way for a more dynamic and adaptable JIT compilation landscape.

The introduction of the JVM Compiler Interface (JVMCI) further amplifies this potential. By allowing the development of custom JIT compilers in Java, JVMCI opens doors for further experimentation and innovation. This could lead to the creation of specialized compilers targeting specific needs or architectures, ultimately pushing the boundaries of Java performance optimization.

In essence, Graal and JVMCI represent a paradigm shift in JIT compilation within the Java ecosystem. They lay the foundation for a future where JIT compilation can be customized, extended, and continuously improved, leading to even more performant and versatile Java applications.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!