Dix choses que vous pouvez faire avec GraalVM


Du traducteur: GraalVM est une nouvelle technologie intéressante, mais sur Habré il n'y a pas beaucoup d'articles sur elle qui pourraient montrer des exemples de capacités Graal. L'article ci-dessous n'est pas seulement une liste de ce que GraalVM peut faire, mais aussi une petite master class similaire à celle que Chris Seaton et Oleg Shelaev ont dirigée à Oracle CodeOne 2018. AprÚs l'auteur, je vous exhorte à essayer de faire des exemples à partir de l'article, c'est vraiment intéressant.


Il y a beaucoup de choses diffĂ©rentes dans GraalVM , et si vous avez dĂ©jĂ  entendu ce nom, ou mĂȘme vu des rapports, il y a encore beaucoup de choses que vous ne savez probablement pas encore, mais que GraalVM peut faire. Dans cet article, nous examinerons les diffĂ©rentes fonctionnalitĂ©s fournies par GraalVM et montrerons ce que vous pouvez en faire.


  1. Exécution rapide Java
  2. Diminuez l'heure de début et l'utilisation de la mémoire pour Java
  3. Combiner JavaScript, Java, Ruby et R
  4. Exécution de programmes écrits dans des langages spécifiques à la plateforme
  5. Outils communs Ă  tous les langages de programmation
  6. Supplément d'application JVM
  7. Applications dépendantes de la plateforme
  8. Code Java en tant que bibliothÚque spécifique à la plate-forme
  9. Prise en charge de plusieurs langages de programmation dans la base de données
  10. Création de langages de programmation pour GraalVM

Vous pouvez faire tout ce qui est montré dans cet article en utilisant GraalVM 1.0.0 RC1, qui est disponible via le lien du site Web de GraalVM . J'ai utilisé MacOS Enterprise Edition, mais le code ici fonctionne sur Linux et GraalVM Community Edition.


Lorsque vous lisez l'article, exĂ©cutez les programmes qui y sont dĂ©crits! Le code peut ĂȘtre tĂ©lĂ©chargĂ© depuis GitHub .


L'installation


AprÚs avoir téléchargé depuis http://graalvm.org/downloads, j'ai ajouté le chemin vers les exécutables GraalVM dans $PATH . Par défaut, cela ajoute la prise en charge de l'exécution Java et JavaScript.


 $ git clone https://github.com/chrisseaton/graalvm-ten-things.git $ cd foo $ tar -zxf graalvm-ee-1.0.0-rc1-macos-amd64.tar.gz # or graalvm-ee-1.0.0-rc1-linux-amd64.tar.gz on Linux $ export PATH=graalvm-1.0.0-rc1/Contents/Home/bin:$PATH # or PATH=graalvm-1.0.0-rc1/bin:$PATH on Linux 

GraalVM est livré avec une prise en charge JavaScript intégrée et contient un gestionnaire de packages appelé gu qui ajoute la possibilité d'installer la prise en charge de langues autres que Java et JavaScript. J'ai également installé Ruby, Python et R, ils sont téléchargés depuis GitHub.


 $ gu install -c org.graalvm.ruby $ gu install -c org.graalvm.python $ gu install -c org.graalvm.R 

Maintenant, si vous exécutez la commande java ou js , vous verrez les versions GraalVM de ces moteurs.


 $ java -version java version "1.8.0_161" Java(TM) SE Runtime Environment (build 1.8.0_161-b12) GraalVM 1.0.0-rc1 (build 25.71-b01-internal-jvmci-0.42, mixed mode) $ js --version Graal JavaScript 1.0 (GraalVM 1.0.0-rc1) 

1. Exécution Java rapide


«Graal» dans GraalVM est le nom du compilateur. Lui seul est crĂ©Ă© pour tout gouverner ! Cela signifie qu'il s'agit d'une implĂ©mentation de compilateur Ă©crite sous la forme d'une bibliothĂšque qui peut ĂȘtre utilisĂ©e pour beaucoup de choses diffĂ©rentes. Par exemple, nous utilisons Graal pour compiler Ă  la fois Ă  l' avance et juste Ă  temps pour compiler du code Ă©crit dans diffĂ©rents langages de programmation, y compris pour diffĂ©rentes architectures de processeur.


La premiÚre et la plus simple façon d'utiliser Graal est de l'utiliser comme compilateur Java JIT.


À titre d'exemple, nous utiliserons un programme qui produit 10 des mots les plus courants dans un document. Le programme utilise les capacitĂ©s du langage Java moderne, telles que les flux et les collections.


 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class TopTen { public static void main(String[] args) { Arrays.stream(args) .flatMap(TopTen::fileLines) .flatMap(line -> Arrays.stream(line.split("\\b"))) .map(word -> word.replaceAll("[^a-zA-Z]", "")) .filter(word -> word.length() > 0) .map(word -> word.toLowerCase()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet().stream() .sorted((a, b) -> -a.getValue().compareTo(b.getValue())) .limit(10) .forEach(e -> System.out.format("%s = %d%n", e.getKey(), e.getValue())); } private static Stream<String> fileLines(String path) { try { return Files.lines(Paths.get(path)); } catch (IOException e) { throw new RuntimeException(e); } } } 

GraalVM inclut le compilateur javac , mais il n'y a aucune différence pour cette démo que ce soit pour l'utiliser ou pour le compilateur standard. Par conséquent, vous pouvez utiliser le compilateur javac standard si vous le souhaitez.


 $ javac TopTen.java 

Si nous exécutons la commande java , qui est incluse dans GraalVM, alors le compilateur Grait JIT sera utilisé automatiquement - aucune étape supplémentaire n'est requise. J'utiliserai la commande time afin d'obtenir des données réelles sur le temps passé à exécuter le programme du début à la fin, au lieu de déployer un micro-benchmark complexe. Une grande quantité d'entrée sera également utilisée afin qu'il n'y ait aucune insinuation sur les quelques secondes enregistrées ici ou là. La taille du fichier large.txt est de 150 Mo.


 $ make large.txt $ time java TopTen large.txt sed = 502701 ut = 392657 in = 377651 et = 352641 id = 317627 eu = 317627 eget = 302621 vel = 300120 a = 287615 sit = 282613 real 0m17.367s user 0m32.355s sys 0m1.456s 

Graal est écrit en Java, pas en C ++, comme la plupart des autres compilateurs JIT pour Java. Nous pensons que cela nous permet de l'améliorer plus rapidement que les compilateurs existants, en ajoutant de nouvelles optimisations puissantes (comme, par exemple, l'analyse d'échappement partielle) qui ne sont pas disponibles dans le compilateur JIT standard pour HotSpot.
Et cela peut rendre vos programmes Java beaucoup plus rapides.


À des fins de comparaison, pour exĂ©cuter des programmes sans le compilateur Grait JIT, j'utiliserai l' -XX:-UseJVMCICompiler . JVMCI est l'interface entre Graal et la JVM. Vous pouvez Ă©galement exĂ©cuter l'exemple sur une machine virtuelle Java standard et comparer les rĂ©sultats.


 $ time java -XX:-UseJVMCICompiler TopTen large.txt sed = 502701 ut = 392657 in = 377651 et = 352641 id = 317627 eu = 317627 eget = 302621 vel = 300120 a = 287615 sit = 282613 real 0m23.511s user 0m24.293s sys 0m0.579s 

Ce test montre que Graal exécute notre programme Java dans environ les trois quarts du temps qu'il faut pour l'exécuter avec le compilateur HotSpot standard. Lorsque nous pensons que l'amélioration de la productivité par unités de pourcentage est une réalisation importante, 25% est une grosse affaire.


Twitter est aujourd'hui la seule entreprise à utiliser Graal sur des serveurs «de combat» , et ils disent que c'est justifié pour eux, en termes d'économies d'argent réel. Twitter utilise Graal pour exécuter des applications écrites en Scala - Graal fonctionne au niveau JVM du bytecode, c'est-à-dire applicable à tout langage JVM.


Il s'agit du premier cas d'utilisation de GraalVM - il suffit de remplacer le compilateur JIT par une meilleure version pour vos applications Java existantes.


2. Diminuez l'heure de début et l'utilisation de la mémoire pour Java


Les atouts de la plate-forme Java sont particuliÚrement évidents lorsque vous travaillez avec des processus de longue durée et des charges de pointe. Les processus de courte durée, en revanche, souffrent de longs temps de démarrage et d'une utilisation relativement élevée de la mémoire.


Par exemple, si nous exécutons l'application de la section précédente, en lui fournissant une quantité beaucoup plus petite de données d'entrée - environ 1 Ko au lieu de 150 Mo, il semble que cela prendra un temps excessivement long et beaucoup de mémoire - environ 60 Mo, afin de traiter un si petit fichier. . Nous utilisons l'option -l pour imprimer la quantité de mémoire utilisée en plus du temps d'exécution.


 $ make small.txt $ /usr/bin/time -l java TopTen small.txt # -v on Linux instead of -l sed = 6 sit = 6 amet = 6 mauris = 3 volutpat = 3 vitae = 3 dolor = 3 libero = 3 tempor = 2 suscipit = 2 0.32 real 0.49 user 0.05 sys 59846656 maximum resident set size 

GraalVM nous donne un outil qui rĂ©sout ce problĂšme. Nous avons dit que Graal est une bibliothĂšque de compilation et qu'elle peut ĂȘtre utilisĂ©e de diffĂ©rentes maniĂšres. L'un d'eux consiste Ă  compiler Ă  l' avance dans une image exĂ©cutable dĂ©pendante de la plate-forme, au lieu de compiler juste Ă  temps au moment de l'exĂ©cution. Ceci est similaire au fonctionnement d'un compilateur classique, tel que gcc .


 $ native-image --no-server TopTen classlist: 1,513.82 ms (cap): 2,333.95 ms setup: 3,584.09 ms (typeflow): 4,642.13 ms (objects): 3,073.58 ms (features): 156.34 ms analysis: 8,059.94 ms universe: 353.02 ms (parse): 1,277.02 ms (inline): 1,412.08 ms (compile): 10,337.76 ms compile: 13,776.23 ms image: 2,526.63 ms write: 1,525.03 ms [total]: 31,439.47 ms 

Cette commande crée un topten plate-forme appelé topten . Ce fichier ne démarre pas la JVM, il n'est pas lié à la JVM et il n'inclut en aucune façon la JVM. La commande native-image compile véritablement votre code Java et les bibliothÚques Java que vous utilisez en code machine complet. Pour les composants d'exécution tels que le garbage collector, nous lançons notre propre nouvelle machine virtuelle appelée SubstrateVM, qui, comme Graal, est également écrite en Java.


Si vous regardez les dépendances topten par topten , vous verrez que ce ne sont que des bibliothÚques systÚme standard. Nous ne pouvons transférer que ce seul fichier vers un systÚme dans lequel la JVM n'a jamais été installée et l'exécuter là-bas pour vérifier qu'il n'utilise pas la JVM ou tout autre fichier. Topten également assez petit - le code exécutable prend moins de 6 Mo.


 $ otool -L topten # ldd topten on Linux topten: .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h topten 5.7M topten 

Si nous exĂ©cutons cet exĂ©cutable, nous verrons qu'il dĂ©marre environ un ordre de grandeur plus rapidement et utilise environ un ordre de grandeur moins de mĂ©moire que le mĂȘme programme exĂ©cutĂ© sous la JVM. Le lancement est si rapide que vous ne remarquerez pas combien de temps cela a pris. Si vous utilisez la ligne de commande, vous ne ressentirez pas la pause qui est gĂ©nĂ©ralement prĂ©sente lorsque vous exĂ©cutez un petit programme de courte durĂ©e sous la JVM


 $ /usr/bin/time -l ./topten small.txt sed = 6 sit = 6 amet = 6 mauris = 3 volutpat = 3 vitae = 3 dolor = 3 libero = 3 tempor = 2 suscipit = 2 0.02 real 0.00 user 0.00 sys 4702208 maximum resident set size 

L'utilitaire d' native-image a certaines limites . Ainsi, au moment de la compilation, toutes les classes doivent ĂȘtre prĂ©sentes, il existe Ă©galement des restrictions sur l'utilisation de l'API Reflection. Mais il existe certains avantages supplĂ©mentaires par rapport Ă  la compilation de base, tels que l'exĂ©cution d'initialiseurs statiques au moment de la compilation. Ainsi, la quantitĂ© de travail effectuĂ©e Ă  chaque tĂ©lĂ©chargement de l'application est rĂ©duite.


Il s'agit de la deuxiÚme application de GraalVM - la distribution et l'exécution de programmes Java existants, avec un démarrage rapide et moins de consommation de mémoire. Cette méthode résout les problÚmes de configuration tels que la recherche du bon bocal au moment de l'exécution et vous permet également de créer des images Docker plus petites.


3. Combiner JavaScript, Java, Ruby et R


Avec Java, GraalVM inclut de nouvelles implĂ©mentations de moteurs JavaScript, Ruby, R et Python. Ils sont Ă©crits Ă  l'aide d'un nouveau framework appelĂ© Truffle . Ce framework permet de crĂ©er des interprĂ©teurs de langage Ă  la fois simples et performants. Lorsque vous Ă©crivez un interprĂ©teur de langue Ă  l'aide de Truffle, il utilise automatiquement Graal pour fournir une compilation JIT pour votre langue. Ainsi, Graal n'est pas seulement un compilateur JIT et un compilateur AOT pour Java, il peut Ă©galement ĂȘtre un compilateur JIT pour JavaScript, Ruby, R et Python.


La prise en charge des langues tierces dans GraalVM vise à remplacer de maniÚre transparente les moteurs existants pour l'exécution de différentes langues. Par exemple, nous pouvons installer le module «couleur» pour Node.js:


 $ npm install --global color ... + color@3.0.0 added 6 packages in 14.156s 

Ensuite, Ă©crivez un programme utilisant ce module pour convertir les couleurs HTML RVB en HSL:


 var Color = require('color'); process.argv.slice(2).forEach(function (val) { print(Color(val).hsl().string()); }); 

Et exécutez-le de la maniÚre habituelle:


 $ node color.js '#42aaf4' hsl(204.89999999999998, 89%, 60.8%) 

Les moteurs d'exécution de différents langages dans GraalVM fonctionnent ensemble - il existe une API qui vous permet d'exécuter du code à partir d'un langage dans un programme écrit dans un autre langage. Et cela vous permet d'écrire des programmes multilingues - des programmes écrits dans plus d'un langage de programmation.


Cela peut ĂȘtre nĂ©cessaire si vous Ă©crivez la plupart de votre programme dans une langue, mais que vous souhaitez utiliser une bibliothĂšque Ă©crite dans un autre langage de programmation. Par exemple, supposons que nous devions Ă©crire une application pour convertir un nom de couleur de CSS en sa reprĂ©sentation numĂ©rique dans Node.js, mais nous voulons utiliser une bibliothĂšque de couleurs Ruby au lieu d'Ă©crire la conversion nous-mĂȘmes.


 var express = require('express'); var app = express(); color_rgb = Polyglot.eval('ruby', ` require 'color' Color::RGB `); app.get('/css/:name', function (req, res) { color = color_rgb.by_name(req.params.name).html() res.send('<h1 style="color: ' + color + '" >' + color + '</h1>'); }); app.listen(8080, function () { console.log('serving at http://localhost:8080') }); 

Dans ce code, nous avons Ă©crit que nous devons exĂ©cuter le code Ruby en tant que chaĂźne, mais notez que nous n'avons pas fait grand chose ici - nous venons de connecter les bibliothĂšques puis de renvoyer l'objet Ruby. Dans Ruby, nous l'utiliserions comme ceci: Color::RGB.by_name (name).html . Si vous regardez comment color_rgb utilisĂ© plus tard dans JavaScript, vous verrez que nous appelons en fait les mĂȘmes mĂ©thodes Ă  partir de JavaScript, bien qu'il s'agisse d'objets et de mĂ©thodes Ruby. Et nous les passons en tant que chaĂźnes JavaScript et combinons le rĂ©sultat, qui est une chaĂźne Ruby, avec une chaĂźne JavaScript.


Installez les deux dépendances - Ruby et JavaScript.


 $ gem install color Fetching: color-1.8.gem (100%) Successfully installed color-1.8 1 gem installed $ npm install express + express@4.16.2 updated 1 package in 10.393s 

Ensuite, vous devez démarrer le node avec quelques options supplémentaires: --polyglot , pour dire que nous avons besoin d'accéder à d'autres langues et --jvm , car l'image de node exécutable par défaut n'inclut rien d'autre que JavaScript.


 $ node --polyglot --jvm color-server.js serving at http://localhost:8080 

Ensuite, accédez à l'URL http: // localhost: 8080 / css / orange (ou une autre couleur), comme d'habitude, dans votre navigateur.

Essayons de faire un exemple plus sérieux, qui utilise plus de langues et de modules.


JavaScript ne prend pas en charge les trÚs grands nombres entiers. J'ai trouvé plusieurs modules tels que big-integer , mais ils sont tous inefficaces car stocker les composants d'un nombre sous forme de nombres à virgule flottante JavaScript. La classe BigInteger en Java est plus efficace, utilisons-la pour effectuer quelques opérations arithmétiques avec de grands nombres entiers.


JavaScript n'a pas non plus de support intégré pour dessiner des graphiques, tandis que R dessine parfaitement des graphiques. Utilisons le module svg de R pour dessiner un nuage de points d'une fonction trigonométrique dans l'espace 3D.


Dans les deux cas, nous utiliserons l'API pour prendre en charge le multilinguisme de GraalVM (ci-aprÚs dénommée API Polyglot) et nous pouvons simplement insérer les résultats de l'exécution de programmes dans d'autres langues en JavaScript.


 const express = require('express') const app = express() const BigInteger = Java.type('java.math.BigInteger') app.get('/', function (req, res) { var text = 'Hello World from Graal.js!<br> ' // Using Java standard library classes text += BigInteger.valueOf(10).pow(100) .add(BigInteger.valueOf(43)).toString() + '<br>' // Using R interoperability to create graphs text += Polyglot.eval('R', `svg(); require(lattice); x <- 1:100 y <- sin(x/10) z <- cos(x^1.3/(runif(1)*5+10)) print(cloud(x~y*z, main="cloud plot")) grDevices:::svg.off() `); res.send(text) }) app.listen(3000, function () { console.log('Example app listening on port 3000!') }) 

Ouvrez http: // localhost: 3000 / dans votre navigateur pour voir le résultat:

C'est la troisiÚme chose que nous pouvons faire avec les programmes exécutés par GraalVM écrits en plusieurs langues et utiliser des modules de ces langues ensemble dans un seul programme. Nous présentons cela comme un moyen d'unifier les environnements d'exécution et les bibliothÚques - vous pouvez utiliser le langage de programmation qui vous semble le mieux adapté pour résoudre la tùche actuelle et n'importe quelle bibliothÚque de votre choix, quel que soit le langage de programmation dans lequel il est écrit.


4. Exécution de programmes écrits dans des langages spécifiques à la plate-forme


Un autre langage pris en charge par GraalVM est C. GraalVM peut exĂ©cuter du code C de la mĂȘme maniĂšre qu'il exĂ©cute des programmes Ă©crits en JavaScript et Ruby.


Ce que GraalVM prend réellement en charge, c'est l'exécution du code résultant de l'exécution des utilitaires LLVM, c'est-à-dire bitcode, pas de prise en charge directe de C. Cela signifie que vous pouvez utiliser les outils existants pour le langage C et d'autres qui prennent en charge LLVM, tels que C ++, Fortran et, potentiellement, plus de langues à l'avenir. Pour simplifier la démonstration, je lance une version spéciale de gzip , qui est assemblée dans un seul fichier ( Stephen McCamant prend en charge cette version). C'est juste le code source gzip et la configuration autoconf combinés en un seul fichier pour plus de simplicité. J'ai dû patcher quelques éléments pour le faire fonctionner sur macOS et avec clang, mais je n'ai rien fait spécifiquement pour prendre en charge GraalVM.


Nous clang gzip en utilisant le clang standard (compilateur LLVM pour C) et voulons qu'il fasse de nous un bitcode LLVM, et non une construction spécifique à la plate-forme, car GraalVM ne le lancera pas. J'utilise clang 4.0.1.


 $ clang -c -emit-llvm gzip.c 

Et puis exécutez le résultat, en utilisant directement la commande lli (interprÚte de code binaire LLVM) de GraalVM. Essayons de compresser le fichier à l'aide de mon archiveur systÚme gzip, puis décompressez-le à l'aide de gzip exécuté sous GraalVM.


 $ cat small.txt Lorem ipsum dolor sit amet... $ gzip small.txt $ lli gzip.bc -d small.txt.gz $ cat small.txt Lorem ipsum dolor sit amet... 

Les implĂ©mentations Ruby et Python dans GraalVM utilisent la mĂȘme technique pour exĂ©cuter des extensions Ă©crites en C pour ces langages. Cela signifie que vous pouvez exĂ©cuter ces extensions Ă  l'intĂ©rieur de la machine virtuelle et cela nous permet de maintenir une vitesse d'exĂ©cution Ă©levĂ©e mĂȘme si nous utilisons des interfaces d'extension spĂ©cifiques Ă  la plate-forme obsolĂštes.


C'est la quatriÚme façon d'utiliser GraalVM - en exécutant des programmes écrits dans des langages spécifiques à la plate-forme, tels que C ou C ++, ainsi qu'en exécutant des extensions de langages tels que Python ou Ruby, qui ne sont pas en mesure de réaliser des implémentations JVM de ces langages, tels que JRuby.


5. Outils généraux pour tous les langages de programmation


Si vous programmez en Java, vous utilisez probablement des outils de trÚs haute qualité tels que les IDE, les débogueurs et les profileurs. Toutes les langues ne disposent pas de cette boßte à outils, mais vous pouvez en obtenir une si vous utilisez des langues prises en charge par GraalVM.


La prise en charge de tous les langages dans GraalVM (sauf Java, pour le moment) est implémentée à l'aide d'un cadre commun - Truffle. Cela nous permet de créer une fonctionnalité, par exemple, un débogueur, et de l'utiliser pour toutes les langues.


Pour essayer cela, nous allons Ă©crire le programme le plus simple - FizzBuzz , car il est visuel (il imprime quelque chose Ă  l'Ă©cran) et il a des branches claires qui ne sont utilisĂ©es que dans certaines itĂ©rations. Ainsi, il nous sera plus facile de dĂ©finir des points d'arrĂȘt. Commençons par une implĂ©mentation JavaScript.


 function fizzbuzz(n) { if ((n % 3 == 0) && (n % 5 == 0)) { return 'FizzBuzz'; } else if (n % 3 == 0) { return 'Fizz'; } else if (n % 5 == 0) { return 'Buzz'; } else { return n; } } for (var n = 1; n <= 20; n++) { print(fizzbuzz(n)); } 

Nous démarrons le programme comme d'habitude, en utilisant l'utilitaire js , sous GraalVM.


 $ js fizzbuzz.js 1 2 Fizz 4 Buzz Fizz 

Nous pouvons Ă©galement exĂ©cuter le programme avec le drapeau --inspect . Cela nous donnera un lien que vous pouvez ouvrir dans Chrome et arrĂȘter le programme dans le dĂ©bogueur.


 $ js --inspect fizzbuzz.js Debugger listening on port 9229. To start debugging, open the following URL in Chrome: chrome-devtools://devtools/bundled/inspector.html?ws=127.0.0.1:9229/6c478d4e-1350b196b409 

Vous pouvez dĂ©finir un point d'arrĂȘt dans le code FizzBuzz puis poursuivre l'exĂ©cution. Lorsque le programme interrompt l'exĂ©cution, nous verrons la valeur de la variable n dans le dĂ©bogueur et nous pouvons continuer l'exĂ©cution du programme ou Ă©tudier l'interface du dĂ©bogueur.

Le dĂ©bogueur dans Chrome est gĂ©nĂ©ralement utilisĂ© pour JavaScript, mais pour GraalVM en JavaScript, il n'y a rien de diffĂ©rent des autres langues. L'indicateur --inspect Ă©galement disponible et fonctionne dans les implĂ©mentations Python, Ruby et R. Je ne vous montrerai pas la source de chaque programme, mais ils fonctionnent de la mĂȘme maniĂšre et vous obtenez le mĂȘme dĂ©bogueur dans Chrome pour chacun d'eux.


 $ graalpython --jvm --inspect fizzbuzz.py 


 $ ruby --inspect fizzbuzz.rb 


 $ Rscript --inspect fizzbuzz.r 


VisualVM est un autre outil que vous connaissez peut-ĂȘtre depuis Java. Il fournit une interface utilisateur Ă  travers laquelle vous pouvez rejoindre une JVM en cours d'exĂ©cution sur votre machine locale ou via un rĂ©seau pour inspecter divers aspects de l'exĂ©cution du programme, tels que l'utilisation de la mĂ©moire ou l'exĂ©cution du thread.


GraalVM inclut VisualVM en tant qu'utilitaire jvisualvm standard.


 $ jvisualvm &> /dev/null & 

Si nous exécutons VisualVM pendant que le programme Java TopTen est en TopTen , nous pouvons observer l'utilisation de la mémoire ou, par exemple, prendre un instantané du contenu de la mémoire et voir quels types d'objets nous utilisons de la mémoire sur le tas.


 $ java TopTen large.txt 


J'ai écrit ce programme en Ruby pour générer des ordures en mémoire lors de l'exécution.


 require 'erb' x = 42 template = ERB.new <<-EOF The value of x is: <%= x %> EOF loop do puts template.result(binding) end 

Si vous exécutez l'implémentation Ruby standard sur la JVM - JRuby, vous serez déçu de VisualVM car vous ne verrez que des objets Java internes au lieu d'objets dans votre langage.


Si vous utilisez la version de Ruby pour GraalVM, VisualVM reconnaĂźt les objets Ruby. Nous devons utiliser l'option --jvm pour utiliser VisualVM, comme il ne prend pas en charge les versions natives de Ruby.


 $ ruby --jvm render.rb 

, , Java , , , Summary, Ruby Heap Ruby .

Truffle — - Nexus . Truffle , , API Truffle' , , Truffle, .


, GraalVM — , . Truffle GraalVM , VisualVM.


6. JVM


, , , Java . API org.graalvm.polyglot , .


 import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; public class ExtendJava { public static void main(String[] args) { String language = "js"; try (Context context = Context.newBuilder().allowNativeAccess(true).build()) { for (String arg: args) { if (arg.startsWith("-")) { language = arg.substring(1); } else { Value v = context.eval(language, arg); System.out.println(v); } } } } } 

javac java GraalVM, org.graalvm.* classpath , .. .


 $ javac ExtendJava.java $ java ExtendJava '14 + 2' 16 $ java ExtendJava -js 'Math.sqrt(14)' 3.7416573867739413 $ java ExtendJava -python '[2**n for n in range(0, 8)]' [1, 2, 4, 8, 16, 32, 64, 128] $ java ExtendJava -ruby '[4, 2, 3].sort' [2, 3, 4] 

, — , node ruby , GraalVM.


GraalVM — Java . Polyglot API “” Java , .


7. -


GraalVM , , — , , GraalVM, - . , JavaScript , V8, Python — CPython , .. . GraalVM — Polyglot .


GraalVM, , JavaScript. Polyglot , , :


 $ graalvm-1.0.0-rc1/Contents/Home/jre/lib/svm/bin/rebuild-images libpolyglot 

C, , , GraalVM, . ExtendJava , , .


 #include <stdlib.h> #include <stdio.h> #include <polyglot_api.h> int main(int argc, char **argv) { graal_isolate_t *isolate = NULL; graal_isolatethread_t *thread = NULL; if (graal_create_isolate(NULL, &isolate) != 0 || (thread = graal_current_thread(isolate)) == NULL) { fprintf(stderr, "initialization error\n"); return 1; } poly_context context = NULL; if (poly_create_context(thread, NULL, 0, &context) != poly_ok) { fprintf(stderr, "initialization error\n"); return 1; } char* language = "js"; for (int n = 1; n < argc; n++) { if (argv[n][0] == '-') { language = &argv[n][1]; } else { poly_value result = NULL; if (poly_context_eval(thread, context, language, "unicalc", argv[n], &result) != poly_ok) { fprintf(stderr, "eval error\n"); return 1; } char buffer[1024]; size_t length; if (poly_value_to_string_utf8(thread, result, buffer, sizeof(buffer), &length) != poly_ok) { fprintf(stderr, "to string error\n"); return 1; } buffer[length] = '\0'; printf("%s\n", buffer); poly_destroy_handle(thread, result); } } return 0; } 

, polyglot GraalVM. , , JVM.


 $ clang -Igraalvm-1.0.0-rc1/Contents/Home/jre/lib/polyglot / -rpath graalvm-1.0.0-rc1/Contents/Home / -Lgraalvm-1.0.0-rc1/Contents/Home/jre/lib/polyglot / -lpolyglot extendc.c -o extendc $ otool -L extendc extendc: .../libpolyglot.dylib ... .../libSystem.B.dylib ... 

 $ ./extendc '14 + 2' 16 $ ./extendc -js 'Math.sqrt(14)' 3.7416573867739413 $ ./extendc -python '[2**n for n in range(0, 8)]' [1, 2, 4, 8, 16, 32, 64, 128] 

, GraalVM — - , , GraalVM.


8. Java -


Java , , , , - , . Java - , JVM , .


GraalVM Java , , - , . , , Java JVM.


, Apache SIS , ( ) . SIS 0.8, http://sis.apache.org/ jar.


 import org.apache.sis.distance.DistanceUtils; public class Distance { public static void main(String[] args) { final double aLat = Double.parseDouble(args[0]); final double aLong = Double.parseDouble(args[1]); final double bLat = Double.parseDouble(args[2]); final double bLong = Double.parseDouble(args[3]); System.out.printf("%.2f km%n", DistanceUtils.getHaversineDistance(aLat, aLong, bLat, bLong)); } public static double distance(IsolateThread thread, double aLat, double aLong, double bLat, double bLong) { return DistanceUtils.getHaversineDistance(aLat, aLong, bLat, bLong); } } 

, -


 $ javac -cp sis.jar -parameters Distance.java $ java -cp sis.jar:. Distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km 

, topten .


 $ native-image --no-server -cp sis.jar:. Distance ... $ ./distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km 

, . , @CEntryPoint


 ... import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.function.CEntryPoint; public class Distance { ... @CEntryPoint(name = "distance") public static double distance(IsolateThread thread, double a_lat, double a_long, double b_lat, double b_long) { return DistanceUtils.getHaversineDistance(a_lat, a_long, b_lat, b_long); } ... } 

javac , GraalVM API classpath . C .


 $ native-image --no-server -cp sis.jar:. -H:Kind=SHARED_LIBRARY \ -H:Name=libdistance $ otool -L libdistance.dylib # .so on Linux libdistance.dylib: .../libdistance.dylib ... .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h libdistance.dylib 4.8M libdistance.dylib 

, . , : VM , , .


 #include <stdlib.h> #include <stdio.h> #include <libdistance.h> int main(int argc, char **argv) { graal_isolate_t *isolate = NULL; graal_isolatethread_t *thread = NULL; if (graal_create_isolate(NULL, &isolate) != 0 || (thread = graal_current_thread(isolate)) == NULL) { fprintf(stderr, "initialization error\n"); return 1; } double a_lat = strtod(argv[1], NULL); double a_long = strtod(argv[2], NULL); double b_lat = strtod(argv[3], NULL); double b_long = strtod(argv[4], NULL); printf("%.2f km\n", distance(thread, a_lat, a_long, b_lat, b_long)); return 0; } 

, ( LD_LIBRARY_PARTH=. Linux)


 $ clang -I. -L. -ldistance distance.c -o distance $ otool -L distance distance: .../libdistance.dylib ... .../libSystem.B.dylib ... $ ./distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km 

GraalVM — java - , JVM


9.


Polyglot — Oracle. Oracle Database Multilingual Engine (MLE), GraalVM SQL.


, front-end, JavaScript email , JavaScript validator . - , SQL PL/SQL. , .


MLE Docker :


https://oracle.imtqy.com/oracle-db-mle/releases/0.2.7/docker/


Docker Daemon.


 $ docker load --input mle-docker-0.2.7.tar.gz 

, Docker, , ( ), Bash .


 $ docker run mle-docker-0.2.7 $ docker ps $ docker exec -ti <container_id> bash -li 

sqlplus ( SQL ), Bash, , , .


 $ sqlplus scott/tiger@localhost:1521/ORCLCDB 

, sqlplus . , Bash Docker, dbjs , . sqlplus .


 $ npm install validator $ npm install @types/validator $ dbjs deploy -u scott -p tiger -c localhost:1521/ORCLCDB validator $ sqlplus scott/tiger@localhost:1521/ORCLCDB 

validator SQL .


 SQL> select validator.isEmail('hello.world@oracle.com') from dual; VALIDATOR.ISEMAIL('HELLO.WORLD@ORACLE.COM') ------------------------------------------- 1 SQL> select validator.isEmail('hello.world') from dual; VALIDATOR.ISEMAIL('HELLO.WORLD') -------------------------------- 0 

, GraalVM — , GraalVM, Oracle. , front-end back-end, , , .


10. GraalVM


Oracle Labs JavaScript, R, Ruby, Python C , Truffle, GraalVM.


Truffle — java , (AST). AST — , , , , , . , , Truffle Graal JIT , AST .


Truffle, GraalVM , , DSL. Truffle Graal , , Truffle — GraalVM. , , , , . , , . Oracle labs Ruby , , .


, , , SimpleLanguage — Truffle, JavaScript. , , , , , if .


, Truffle Oracle Labs, SmallTalk , Newspeak Lisp . Lisp , .


Conclusion


GraalVM — , , . , , , , .


GraalVM, http://www.graalvm.org/ . , , .


, , . , GraalVM @ChrisGSeaton @shelajev .


: Oleg Ć elajev , Olya Gupalo Doug Simon

Source: https://habr.com/ru/post/fr433432/


All Articles