Essayez d'accélérer le démarrage des programmes de console Java avec l'image native de GraalVM

Aperçu

Dans cette entrée, la fonction de "[Native Image]" (https://www.graalvm.org/docs/reference-manual/native-image/) de GraalVM Utilisé pour réduire le temps de démarrage des programmes de la console Java.

En résumé

Après avoir fait ceci et cela, le programme qui a pris environ 1 seconde pour démarrer sur la JVM avec les performances d'un ordinateur spécifique (équivalent à une micro instance d'OCI) est devenu binaire natif, et le démarrage est devenu environ 100 ms.

Lecteur supposé

Chose que tu veux faire

Préparation

environnement

Préparation de Graal VM et de l'image native

Comme ça, je l'ai présenté sous / opt. Au moment de la rédaction de cet article, 19.3.1 est la dernière version de GraalVM.

cd /opt
sudo curl -L -O https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-19.3.1/graalvm-ce-java8-linux-amd64-19.3.1.tar.gz
sudo tar zxvf graalvm-ce-java8-linux-amd64-19.3.1.tar.gz

Utilisez l'outil GraalVM "gu" pour présenter l'outil pour Native Image.

sudo  /opt/graalvm-ce-java8-19.3.1/bin//gu install native-image

Pour que native-image fonctionne, vous avez besoin d'un ensemble de boîtes à outils pour créer le binaire sur la plate-forme cible. Étant donné que cette entrée utilise CentOS7, installez les packages comme indiqué ci-dessous.

sudo yum install -y glibc-devel zlib-devel gcc

Préparer le programme Java cible

Le programme utilisé dans cette entrée est une simple calculatrice de console. Cliquez ici pour la version GitHub. https://github.com/hrkt/commandline-calculator/releases/tag/0.0.4

cd master
../gradlew :calculator-cli-without-spring:shadowJar

Ensuite, calculator-cli-without-spring / build / libs / calculator-cli-without-spring-0.0.1-SNAPSHOT-all.jar sera créé. Ce fichier Jar est nécessaire pour l'exécution en utilisant le plug-in "Gradle Shadow" qui rassemble la partie auto-fabriquée et le Jar qui a été utilisé pour la première fois. Il s'agit d'une collection de fichiers dans un seul fichier JAR. Le fichier JAR terminé faisait environ 760 Ko.

$ ls -la calculator-cli-without-spring/build/libs/calculator-cli-without-spring-0.0.1-SNAPSHOT-all.jar
-rw-rw-r--. 1 opc opc 757383 Jan 31 23:13 calculator-cli-without-spring/build/libs/calculator-cli-without-spring-0.0.1-SNAPSHOT-all.jar

Exécutez-le et essayez d'exécuter "1 + 1".

[opc@instance-20200117-1627 commandline-calculator]$ java -jar calculator-cli-without-spring/build/libs/calculator-cli-without-spring-0.0.1-SNAPSHOT-all.jar
Calculator is running. Press ctrl-c to exit.(boot in 1272 msec.)
1+1=
1+1
=2
q
[opc@instance-20200117-1627 commandline-calculator]$

À ce stade, vous pouvez voir qu'il a fallu environ 1,3 seconde pour démarrer le programme. Le temps est mesuré par la méthode suivante.

            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            long uptimeInMillis = runtimeMXBean.getUptime();
            terminal.writer().println(String.format("Calculator is running. Press ctrl-c to exit.(boot in %d msec.)",
                    uptimeInMillis));

Créer une image native

Préparation

Décompressez le fichier JAR créé ci-dessus et décompressez-le dans votre espace de travail.

cd calculator-cli-without-spring/build/libs
mkdir inside
cd inside
jar xvf ../calculator-cli-without-spring-0.0.1-SNAPSHOT-all.jar

Après cela, créez un répertoire pour obtenir des informations de profil à utiliser dans native-image.

mkdir -p META-INF/native-image

Obtenir le profil d'exécution

Exécutez comme un programme Java normal avant d'exécuter native-image. En travaillant avec l'agent, il collecte des informations qui ne peuvent pas être obtenues par analyse statique, telles que le type de réflexion utilisé pendant le fonctionnement et si la bibliothèque de JNI est utilisée.

/opt/graalvm-ce-java8-19.3.1/bin/java -agentlib:native-image-agent=config-output-dir=META-INF/native-image -cp . com.hrkt.commandlinecalculator.Main

Lorsque vous exécutez "1 + 1 =" et entrez "q" pour quitter le programme de la même manière que décrit ci-dessus, les informations suivantes seront collectées.

[opc@instance-20200117-1627 inside]$ ls -la META-INF/native-image/
total 16
drwxrwxr-x. 2 opc opc 109 Jan 31 23:15 .
drwxrwxr-x. 6 opc opc  88 Jan 31 23:15 ..
-rw-rw-r--. 1 opc opc 689 Jan 31 23:15 jni-config.json
-rw-rw-r--. 1 opc opc   4 Jan 31 23:15 proxy-config.json
-rw-rw-r--. 1 opc opc 366 Jan 31 23:15 reflect-config.json
-rw-rw-r--. 1 opc opc 472 Jan 31 23:15 resource-config.json

Créer un binaire avec une image native

Construire. La signification de l'option est expliquée sur le site. ](Http://www.graalvm.org/docs/reference-manual/native-image/)

 /opt/graalvm-ce-java8-19.3.1/bin/native-image  --no-server --no-fallback  --report-unsupported-elements-at-runtime -cp . com.hrkt.commandlinecalculator.Main

Cela prend du temps de l'ordre de quelques minutes. Attendons patiemment. L'environnement et le programme cible de cette entrée prendront environ 5 minutes.

[com.hrkt.commandlinecalculator.main:13836]    classlist:  11,879.57 ms
[com.hrkt.commandlinecalculator.main:13836]        (cap):   3,604.46 ms
[com.hrkt.commandlinecalculator.main:13836]        setup:   9,898.60 ms
[com.hrkt.commandlinecalculator.main:13836]   (typeflow):  36,059.72 ms
[com.hrkt.commandlinecalculator.main:13836]    (objects):  23,227.98 ms
[com.hrkt.commandlinecalculator.main:13836]   (features):   3,516.18 ms
[com.hrkt.commandlinecalculator.main:13836]     analysis:  63,682.08 ms
[com.hrkt.commandlinecalculator.main:13836]     (clinit):   1,281.12 ms
[com.hrkt.commandlinecalculator.main:13836]     universe:   3,092.99 ms
[com.hrkt.commandlinecalculator.main:13836]      (parse):  10,531.88 ms
[com.hrkt.commandlinecalculator.main:13836]     (inline):  28,108.04 ms
[com.hrkt.commandlinecalculator.main:13836]    (compile): 176,012.21 ms
[com.hrkt.commandlinecalculator.main:13836]      compile: 227,565.33 ms
[com.hrkt.commandlinecalculator.main:13836]        image:   6,261.29 ms
[com.hrkt.commandlinecalculator.main:13836]        write:   2,044.20 ms
[com.hrkt.commandlinecalculator.main:13836]      [total]: 326,546.79 ms

Courir

Déplaçons le binaire terminé. Commençons plusieurs fois pour voir à quoi cela ressemble. Vous pouvez voir qu'il peut être démarré à partir de la première moitié de la ms à 2 chiffres jusqu'à environ 100 ms au plus tard. Il démarre beaucoup plus rapidement que sur la JVM.

[opc@instance-20200117-1627 inside]$ ./com.hrkt.commandlinecalculator.main
Calculator is running. Press ctrl-c to exit.(boot in 66 msec.)
^C
[opc@instance-20200117-1627 inside]$ ./com.hrkt.commandlinecalculator.main
Calculator is running. Press ctrl-c to exit.(boot in 14 msec.)
^C
[opc@instance-20200117-1627 inside]$ ./com.hrkt.commandlinecalculator.main
Calculator is running. Press ctrl-c to exit.(boot in 16 msec.)
^C
[opc@instance-20200117-1627 inside]$ ./com.hrkt.commandlinecalculator.main
Calculator is running. Press ctrl-c to exit.(boot in 24 msec.)
^C
[opc@instance-20200117-1627 inside]$ ./com.hrkt.commandlinecalculator.main
Calculator is running. Press ctrl-c to exit.(boot in 131 msec.)
^C
[opc@instance-20200117-1627 inside]$ ./com.hrkt.commandlinecalculator.main
Calculator is running. Press ctrl-c to exit.(boot in 27 msec.)
^C

Vérifions le binaire.

Commençons par vérifier le type.

[opc@instance-20200117-1627 inside]$ file com.hrkt.commandlinecalculator.main
com.hrkt.commandlinecalculator.main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=b5ce8429a80c97c4e12c87c516a8b24b59c64086, not stripped

C'est juste un binaire ELF ordinaire. Quel type de bibliothèque utilisez-vous ...

[opc@instance-20200117-1627 inside]$ ldd com.hrkt.commandlinecalculator.main
        linux-vdso.so.1 =>  (0x00007fff5abf9000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f74c3bf7000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f74c39db000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f74c37d7000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f74c35c1000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f74c33b9000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f74c2feb000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f74c3ef9000)

J'utilise une bibliothèque très standard dans ma distribution Linux. Et la taille est ...

[opc@instance-20200117-1627 inside]$ ls -la com.hrkt.commandlinecalculator.main
-rwxrwxr-x. 1 opc opc 10066064 Feb  1 04:08 com.hrkt.commandlinecalculator.main

Environ 10 Mo. Il a considérablement gonflé.

Résumé

Cette entrée portait sur la tentative d'accélérer le lancement des programmes de console Java avec l'image native de GraalVM.

J'ai admiré "démarrer", mais gardez à l'esprit que cela ne mentionne pas la vitesse à laquelle il fonctionne continuellement après cela.

Supplément

Pour utiliser JNI, le programme que j'écrivais, j'ai d'abord utilisé JNA comme je l'ai écrit dans Another entry, mais natif -image n'a pas pu être exécuté avec succès. GitHub avait également un échange tel que (L'utilisation de JNA dans une image native ne fonctionne pas # 673) [https://github.com/oracle/graal/issues/673].

Il semble que le côté Image native de GraalVM ne prend pas encore en charge la fonction utilisant JNA utilisée dans cette entrée.

Recommended Posts

Essayez d'accélérer le démarrage des programmes de console Java avec l'image native de GraalVM
Essayez d'intégrer Ruby et Java avec Dapr
Essayez d'implémenter TCP / IP + NIO avec JAVA
Essayez de déboguer un programme Java avec VS Code
Essayez de vous connecter à l'émulateur AzureCosmosDB pour Docker avec Java
Essayez de créer Java dans un module natif avec GraalVM
Programme Java pour redimensionner une photo dans un carré avec des marges
[Débutant] Essayez de créer un jeu RPG simple avec Java ①
Java pour jouer avec Function
Essayez la connexion DB avec Java
Essayez gRPC avec Java, Maven
Connectez-vous à DB avec Java
Connectez-vous à MySQL 8 avec Java
Entrée dans la console Java
Java pour apprendre avec les ramen [Partie 1]
[Java] Points à noter avec Arrays.asList ()
Osez défier Kaggle avec Java (1)
[Rails] Comment accélérer la composition de docker
Essayez d'utiliser Redis avec Java (jar)
J'ai essayé d'interagir avec Java
[Java] Essayez de mettre en œuvre à l'aide de génériques
Essayez d'extraire la méthode publique de java
Essayez la communication bidirectionnelle avec gRPC Java
Essayez d'implémenter Yuma en Java
Java, des tableaux pour débuter avec les débutants
J'ai essayé de mesurer et de comparer la vitesse de Graal VM avec JMH
Lorsque j'essaye de m'inscrire avec devise, il redirige automatiquement vers root_path