Java à la vitesse de la lumière grâce au Graal !

Anthony Pena

Reprenons les bases

langages interprétés VS langages compilés

Java est un langage

un peu à cheval entre les deux

Et la JVM dans tout ça ?

Qu'est-ce que le Graal(VM) !

Polyglotte ?

import org.graalvm.polyglot.*;

class Polyglot {
    public static void main(String[] args) {
        Context polyglot = Context.create();
        Value array = polyglot.eval("js", "[1,2,42,4]");
        int result = array.getArrayElement(2).asInt();
        System.out.println(result);
    }
}

On peut aussi écrire :

import org.graalvm.polyglot.*;

public class App {
    public static void main(String[] args) {
        try (Context context = Context.create()) {
            var x = 1;
            context.eval("js", "const y=2");
            Value fn = context.eval("js", "function foo(x) { return x+y; } foo"});
            System.out.println(fn.execute(x)); // will print 3
        }
    }
}

Mais on ne peut pas écrire :

import org.graalvm.polyglot.*;
public class App {
    public static void main(String[] args) {
        try (Context context = Context.create()) {
            var x = 1;
            context.eval("js", "const y=2");
+            context.eval("ruby", "z = 3");
-            Value fn = context.eval("js", "function foo(x) { return x+y; } foo"});
+            Value fn = context.eval("js", "function foo(x) { return x+y+z; } foo"});
            System.out.println(fn.execute(x)); // will print 6
        }
    }
}

Compilation native pourquoi faire ?

Le Graal nous sauvera !

Oui mais...

Quelques metriques

Selon l'équipe GraalVM

Quand on compare GraalVM native et GraalVM en mode Hotspot

  • le démarrage est 50x plus rapide
  • la consommation mémoire est 5 fois plus faible

Temps de compilation

Taille du binaire/jar

+ JRE pour OpenJDK (325Mo)
+ GraalVM HotSpot (967Mo)

Temps de démarrage

Consommation RAM

Production ready ?

Conclusion

Anthony Pena

Développeur Web Fullstack @ center height:2em

@_Anthony_Pena_

@kuroidoruido

@penaanthony

https://k49.fr.nf

https://pixabay.com/photos/highway-traffic-long-exposure-393492/

Interprétés : PHP, JavaScript, Lua, Python - on ne va pas créer une binaire - le code est lu par un programme qui va interprêter le code directement - généralement portable entre différente plateforme Compilés : C/C++, Ada - le binaire n'est pas portable mais dédié à une plateforme - le binaire est composé d'instruction machine - c'est plus rapide

https://unsplash.com/photos/5N75xeV9x9Q

- on compile mais vers un bytecode - ce bytecode sera compilé une seconde fois via un JIT à l'exécution - le bytecode n'est pas du java, c'est des instructions proche d'un assembleur - le jar est juste une archive zip avec des conventions

https://unsplash.com/photos/LmQRYcJmtv8

c'est la plateforme qui va faire de la magie avec le bytecode - interprétation du bytecode - compilation JIT (Just In Time) - intéraction avec l'OS - garbage collector - gestion des threads - ... Tout ce qui fait qu'en Java on s'abstrait de la machine

https://unsplash.com/photos/7C8c-7fwk34

- on va maintenant rentrer au cœur du sujet : GraalVM - C'est un set d'outils qui va se greffer autour d'une copie de l'OpenJDK - ce n'est pas juste une réécriture, mais il y a 2 grandes nouveautés : la compilation native et la JVM polyglotte

- on peut faire exécuter plusieurs langages sur la JVM : JavaScript (dont Node.js), Ruby, Python, R et LLVM - WebAssembly en experimental - ces langages seront exécutés dans le même AST, dans la JVM, donc sans latence - il y a juste des bridges pour demander l'exécution d'un autre langage (par exemple js dans Java)

refs: - https://www.graalvm.org/ - https://www.graalvm.org/reference-manual/wasm/

tiré de la documentation : https://www.graalvm.org/reference-manual/polyglot-programming/#start-language-java

- sur une JVM classique on a un temps de warm up assez long - pas forcément un problème dans beaucoup de cas d'usage - peu poser problème pour des cas comme le cloud où on démarre/coupe des services souvent - un JRE est assez lourd et on utilise jamais tout - le JIT prend du temps à tout compiler et donc au démarrage l'exécution est lente

https://unsplash.com/photos/cYRMl1HeuVo

- compilation en binaire dès la première compilation - plus de jar, plus de jvm à installer, mais directement un executable all-in-one incluant une jvm - plus de JIT (comme tout est déjà compilé)

https://unsplash.com/photos/2MSMhiycQuY

- executable all-in-one veut aussi dire plus de chargement dynamique de jar - pour être très optimisé une partie des API reflexions ne fonctionnent pas avec GraalVM - la réflexion est autodétecté et partiellement calculé à la compilation - parfois il faut faire une configuration manuelle pour que le compilateur permettent certains éléments de réflexion - on n'a plus de jar portable, il faut compiler pour chaque plateforme - on ne peut plus suivre les versions de java tous les semestres (Java 11 ou Java 17 uniquement)

refs: https://www.graalvm.org/reference-manual/native-image/Reflection/

https://pixabay.com/illustrations/matrix-technology-tech-data-3109378/

- tirés du site officiel

refs: https://medium.com/graalvm/lightweight-cloud-native-java-applications-35d56bc45673

https://pixabay.com/illustrations/superhero-girl-speed-runner-534120/

- premier OpenJDK 11.0.12 - second GraalVM CE 21.2 - troisièle GraalVM CE 21.2 en mode natif

https://pixabay.com/photos/child-tower-building-blocks-blocks-1864718/

- premier OpenJDK 11.0.12 - second GraalVM CE 21.2 - troisièle GraalVM CE 21.2 en mode natif

https://pixabay.com/photos/child-tower-building-blocks-blocks-1864718/

- premier OpenJDK 11.0.12 (jar) - second GraalVM CE 21.2 (jar) - troisièle GraalVM CE 21.2 en mode natif (exe)

https://pixabay.com/photos/child-running-children-girl-happy-817371/

- premier OpenJDK 11.0.12 (jar) - second GraalVM CE 21.2 (jar) - troisièle GraalVM CE 21.2 en mode natif (exe)

https://pixabay.com/photos/child-running-children-girl-happy-817371/

- utilisé en prod chez Oracle, Twitter, Facebook, etc. au moins en partie - Des frameworks ont été construits spécialement pour être efficace avec GraalVM en natif : Micronaut, Quarkus, Helidon - Il y a le module Spring Native pour faire du GraalVM avec Spring et compilé en natif

https://pixabay.com/photos/factory-powerplant-landscape-clouds-4338627/

- Surtout si on est dans un contexte cloud, il faut se poser la question de GraalVM en natif - Pas de gain à utiliser GraalVM en production en mode HotSpot - On voit un vrai gain sur la taille des images docker par exemple - les démarrages sont vraiment plus rapide

https://pixabay.com/photos/king-coast-arthur-tintagel-statue-3879305/