Originaltext: https://medium.com/graalvm/graalvm-ten-things-12d9111f307d

!! Top 10 Dinge, die man mit GraalVM machen kann

Chris Seaton
25. April 2018 · 21 min gelesen

Dieser Beitrag wurde auf GraalVM 19.3.0 aktualisiert

GraalVM hat viele verschiedene Teile. Wenn Sie also den Namen schon einmal gehört oder einige unserer Vorträge gesehen haben, gibt es mit Sicherheit Dinge, die Sie tun können, von denen Sie noch nichts wissen. In diesem Artikel werden wir einige der verschiedenen Funktionen von GraalVM auflisten und Ihnen zeigen, was sie für Sie tun können.

     1. Hochleistungsfähiges modernes Java
     2. Java mit geringem Platzbedarf und schnellem Start
     3. Kombinieren Sie JavaScript, Java, Ruby und R.
     4. Führen Sie Muttersprachen in der JVM aus
     5. Tools, die in allen Sprachen funktionieren
     6. Erweitern Sie eine JVM-basierte Anwendung
     7. Erweitern Sie eine native Anwendung
     8. Java-Code als native Bibliothek
     9. Polyglot in der Datenbank
     10. Erstellen Sie Ihre eigene Sprache
     
Sie können alles, was ich in diesem Artikel zeige, mit GraalVM 19.3.0 reproduzieren, das unter graalvm.org/downloads verfügbar ist. Ich verwende die Enterprise Edition unter macOS, die wie hier kostenlos ausgewertet werden kann. Die Anweisungen funktionieren jedoch auch unter Linux. Die meisten von ihnen funktionieren auch mit der Community Edition.

Folgen Sie diesen Programmen und führen Sie sie aus, während Sie lesen! Der Code, den ich auf GraalVM ausführe, kann unter github.com/chrisseaton/graalvm-ten-things/ geklont werden.
Konfiguration

! Setup

Ich habe GraalVM Enterprise Edition basierend auf JDK8 für macOS von https://www.oracle.com/downloads/graalvm-downloads.html heruntergeladen und die Programme daraus auf meinen $ PATH gestellt. Dies gibt mir standardmäßig die Sprachen Java und JavaScript.

%%prettify 
{{{
$ git-Klon https://github.com/chrisseaton/graalvm-ten-things.git
$ cd foo
$ tar -zxf graalvm-ee-java8-darwin-amd64-19.3.0.tar.gz
     # oder graalvm-ee-java8-linux-amd64-19.3.0.tar.gz unter Linux
$ export PATH = graalvm-ee-java8-19.3.0 / Inhalt / Home / bin: $ PATH
     # oder PATH = graalvm-ee-java8-19.3.0 / bin: $ PATH unter Linux

}}}
/%

GraalVM wird mit JavaScript geliefert und verfügt über einen Paketmanager namens gu, mit dem Sie zusätzliche Sprachen installieren können. Ich habe die Sprachen Ruby, Python und R installiert. Ich habe auch das native-imagetool installiert. Diese werden alle von GitHub heruntergeladen.

%%prettify 
{{{
$ gu installiere native-image
$ gu Ruby installieren
$ gu Python installieren
$ gu installiere R.
}}}
/%


Wenn Sie jetzt Java oder js ausführen, erhalten Sie die GraalVM-Versionen dieser Laufzeiten.

%%prettify 
{{{
$ java -version
Java-Version "1.8.0_231"
Java (TM) SE-Laufzeitumgebung (Build 1.8.0_231-b11)
Java HotSpot (TM) 64-Bit-GraalVM EE 19.3.0 (Build 25.231-b11-jvmci-19.3-b05, gemischter Modus) $ js --version
GraalVM JavaScript (GraalVM EE Native 19.3.0)

}}}
/%

! 1. Hochleistungsfähiges modernes Java

Der Graal-Name in der GraalVM stammt vom GraalVM-Compiler. GraalVM ist ein Compiler, der sie alle regiert. Dies bedeutet, dass es sich um eine einzelne Implementierung eines Compilers handelt, der als Bibliothek geschrieben wurde und für viele verschiedene Zwecke verwendet werden kann. Zum Beispiel verwenden wir den GraalVM-Compiler, um sowohl vorab als auch just-in-time zu kompilieren, mehrere Programmiersprachen zu kompilieren und mehrere Architekturen zu erstellen.

Eine einfache Möglichkeit, GraalVM zu verwenden, besteht darin, es als Java JIT-Compiler zu verwenden.

Wir verwenden dieses Beispielprogramm, das Ihnen die zehn wichtigsten Wörter in einem Dokument enthält. Es verwendet moderne Java-Sprachfunktionen wie Streams und Collectors.

GraalVM enthält einen Javac-Compiler, der sich jedoch für die Zwecke dieser Demo nicht vom Standard-Compiler unterscheidet. Sie können also stattdessen Ihren System-Javac verwenden, wenn Sie möchten.

%%prettify 
{{{
$ javac TopTen.java
}}}
/%


Wenn wir den in GraalVM enthaltenen Java-Befehl ausführen, verwenden wir automatisch den Graal JIT-Compiler - es ist keine zusätzliche Konfiguration erforderlich. Ich werde den Befehl time verwenden, um die tatsächliche Zeit zu ermitteln, die für die Ausführung des gesamten Programms von Anfang bis Ende benötigt wird, anstatt einen komplizierten Mikro-Benchmark einzurichten, und ich werde eine große Eingabe verwenden, damit wir streiten hier und da nicht über ein paar Sekunden. Die Datei large.txt ist 150 MB groß.

%%prettify 
{{{
$ 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 = 282613real 0m12.950s
Benutzer 0m17.827s
sys 0m0.622s
}}}
/%


GraalVM ist in Java geschrieben und nicht wie die meisten anderen JIT-Compiler für Java in C ++. Wir glauben, dass wir dies schneller als vorhandene Compiler verbessern können, mit leistungsstarken neuen Optimierungen wie der partiellen Escape-Analyse, die in den Standard-JIT-Compilern für HotSpot nicht verfügbar sind. Dadurch können Ihre Java-Programme erheblich schneller ausgeführt werden.

Um ohne den zu vergleichenden GraalVM JIT-Compiler zu laufen, kann ich das Flag -XX: -UseJVMCICompiler verwenden. JVMCI ist die Schnittstelle zwischen GraalVM und der JVM. Sie können auch mit Ihrer Standard-JVM vergleichen.

%%prettify 
{{{
$ 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 = 282613real 0m19.602s
Benutzer 0m20.357s
sys 0m0.498s
}}}
/%


Dies zeigt, dass GraalVM unser Java-Programm in etwa zwei Dritteln der Wanduhrzeit ausführt, die für die Ausführung mit einem Standard-HotSpot-Compiler erforderlich ist. In einem Bereich, in dem wir es gewohnt sind, einstellige prozentuale Leistungssteigerungen als signifikant zu behandeln, ist dies eine große Sache.

Wenn Sie die Community Edition verwenden, erhalten Sie immer noch ein besseres Ergebnis als HotSpot, aber es ist nicht ganz so gut wie die Enterprise Edition.

Twitter ist ein Unternehmen, das GraalVM heute in der Produktion einsetzt, und sie sagen, dass es sich für sie in Bezug auf das eingesparte echte Geld auszahlt. Twitter verwendet GraalVM, um Scala-Anwendungen auszuführen. GraalVM arbeitet auf der Ebene des JVM-Bytecodes, sodass es für jede JVM-Sprache funktioniert.

Dies ist die erste Möglichkeit, GraalVM zu verwenden - einfach als besserer JIT-Compiler für Ihre vorhandenen Java-Anwendungen.

! 2. Java mit geringem Platzbedarf und schnellem Start

Die Java-Plattform ist besonders stark für Prozesse mit langer Laufzeit und Spitzenleistung. Prozesse mit kurzer Laufzeit können jedoch unter einer längeren Startzeit und einer relativ hohen Speichernutzung leiden.

Wenn wir zum Beispiel dieselbe Anwendung mit einer viel kleineren Eingabe ausführen - etwa 1 KB statt 150 MB -, scheint es unangemessen lange zu dauern und mit 70 MB ziemlich viel Speicher für eine so kleine Datei . Wir verwenden -l, um den verwendeten Speicher sowie die verwendete Zeit zu drucken.

%%prettify 
{{{
$ make small.txt
$ / usr / bin / time -l java TopTen small.txt
      # -v unter Linux statt -l
sed = 6
sitzen = 6
amet = 6
Mauris = 3
volutpat = 3
Lebenslauf = 3
Farbe = 3
libero = 3
tempor = 2
Suscipit = 2
        0,17 real 0,28 Benutzer 0,04 sys
  70737920 maximale Größe des residenten Sets
...
}}}
/%


GraalVM bietet uns ein Tool, das dieses Problem löst. Wir haben gesagt, dass GraalVM wie eine Compiler-Bibliothek ist und auf viele verschiedene Arten verwendet werden kann. Eine davon besteht darin, vorab ein natives ausführbares Image zu kompilieren, anstatt es zur Laufzeit just-in-time zu kompilieren. Dies ähnelt der Funktionsweise eines herkömmlichen Compilers wie gcc.

%%prettify 
{{{
$ native-image --no-server --no-fallback TopTen
[topten: 37970] Klassenliste: 1.801,57 ms
[topten: 37970] (Kappe): 1.289,45 ms
[topten: 37970] Setup: 3.087,67 ms
[topten: 37970] (Typfluss): 6.704,85 ms
[topten: 37970] (Objekte): 6.448,88 ms
[topten: 37970] (Funktionen): 820,90 ms
[topten: 37970] Analyse: 14.271,88 ms
[topten: 37970] (Clinit): 257,25 ms
[topten: 37970] Universum: 766,11 ms
[topten: 37970] (Analyse): 1.365,29 ms
[topten: 37970] (inline): 3.829,55 ms
[topten: 37970] (kompilieren): 34.674,51 ms
[topten: 37970] kompilieren: 41.412,71 ms
[topten: 37970] Bild: 2.741,41 ms
[topten: 37970] write: 619.13 ms
[topten: 37970] [total]: 64.891,52 ms
}}}
/%


Dieser Befehl erzeugt eine native ausführbare Datei namens topten. Diese ausführbare Datei ist kein Starter für die JVM, sie stellt keine Verbindung zur JVM her und bündelt die JVM in keiner Weise. native-image kompiliert wirklich Ihren Java-Code und alle von Ihnen verwendeten Java-Bibliotheken bis hin zu einfachem Maschinencode. Für Laufzeitkomponenten wie den Garbage Collector führen wir unsere eigene neue VM namens SubstrateVM aus, die wie GraalVM auch in Java geschrieben ist.

Wenn wir uns die Bibliotheken ansehen, die topten verwendet, können Sie sehen, dass es sich nur um Standardsystembibliotheken handelt. Wir könnten auch nur diese eine Datei auf ein System verschieben, auf dem noch nie eine JVM installiert war, und sie dort ausführen, um zu überprüfen, ob keine JVM oder andere Dateien verwendet werden. Es ist auch ziemlich klein - diese ausführbare Datei ist weniger als 8 MB groß.

%%prettify 
{{{
$ otool -L topten # ldd topten unter Linux
topten:
  libSystem.B.dylib (aktuelle Version 1252.250.1)
  CoreFoundation (aktuelle Version 1575.12.0)
  /usr/lib/libz.1.dylib (Kompatibilitätsversion 1.0.0, aktuelle Version 1.2.11)
$ du -h topten
7,5 M Topten
}}}
/%


Wenn wir die ausführbare Datei ausführen, können wir feststellen, dass sie um eine Größenordnung schneller startet und etwa eine Größenordnung weniger Speicher benötigt als das gleiche Programm auf der JVM. Es ist so schnell, dass Sie die Zeit, die Sie bei der Verwendung in der Befehlszeile benötigen, nicht bemerken. Sie spüren nicht die Pause, die Sie immer erhalten, wenn Sie einen Kurzlaufbefehl mit der JVM ausführen.

%%prettify 
{{{
$ / usr / bin / time -l ./topten small.txt
sed = 6
sitzen = 6
amet = 6
Mauris = 3
volutpat = 3
Lebenslauf = 3
Farbe = 3
libero = 3
tempor = 2
Suscipit = 2
        0,02 real 0,00 Benutzer 0,00 sys
   3158016 maximale Größe des residenten Sets
...
}}}
/%


Das native Bild-Tool weist einige Einschränkungen auf, z. B. dass alle Klassen während der Kompilierung verfügbar sein müssen, und einige Einschränkungen in Bezug auf die Reflexion. Es hat einige zusätzliche Vorteile gegenüber der Basiskompilierung, da statische Initialisierer während der Kompilierung ausgeführt werden, sodass Sie den Arbeitsaufwand bei jedem Laden einer Anwendung reduzieren können.

Dies ist eine zweite Möglichkeit, GraalVM zu verwenden - eine Möglichkeit, Ihre vorhandenen Java-Programme mit geringem Platzbedarf und schnellem Start zu verteilen und auszuführen. Es befreit Sie auch von Konfigurationsproblemen wie dem Finden der richtigen JAR-Dateien zur Laufzeit und ermöglicht Ihnen kleinere Docker-Images.

! 3. Kombinieren Sie JavaScript, Java, Ruby und R.

GraalVM enthält neben Java auch neue Implementierungen von JavaScript, Ruby, R und Python. Diese werden mit einem neuen Sprachimplementierungsframework namens Truffle geschrieben, das es ermöglicht, Sprachinterpreter zu implementieren, die sowohl einfach als auch leistungsstark sind. Wenn Sie einen Sprachinterpreter mit Truffle schreiben, verwendet Truffle automatisch GraalVM in Ihrem Namen, um Ihnen einen JIT-Compiler für Ihre Sprache zu geben. GraalVM ist also nicht nur ein JIT-Compiler und ein früherer nativer Compiler für Java, sondern kann auch ein JIT-Compiler für JavaScript, Ruby, R und Python sein.

Die Sprachen in GraalVM sollen Ersatz für Ihre vorhandenen Sprachen sein. Zum Beispiel können wir ein Node.js-Modul installieren:

%%prettify 
{{{
$ npm Farbe installieren
...
+ color@3.1.1
6 Pakete von 6 Mitwirkenden hinzugefügt und 7 Pakete in 6.931s geprüft
}}}
/%


Mit diesem Modul können wir ein kleines Programm color.js schreiben, um eine RGB-HTML-Farbe in HSL zu konvertieren:

%%prettify 
{{{
var Color = require ('color'); process.argv.slice (2) .forEach (function (val) {
  console.log (Farbe (val) .hsl (). string ());
});
}}}
/%


Dann können wir das auf die übliche Weise ausführen:

%%prettify 
{{{
$ node color.js '# 42aaf4'
hsl (204,89999999999998, 89%, 60,8%)
}}}
/%


Die Sprachen in GraalVM arbeiten zusammen - es gibt eine API, mit der Sie Code aus einer Sprache in einer anderen ausführen können. Auf diese Weise können Sie polyglotte Programme schreiben - Programme, die in mehr als einer Sprache geschrieben sind.

Möglicherweise möchten Sie dies tun, weil Sie den Großteil Ihrer Anwendung in einer Sprache schreiben möchten, aber es gibt eine Bibliothek im Ökosystem einer anderen Sprache, die Sie verwenden möchten. Angenommen, wir möchten unsere Anwendung zum Konvertieren eines CSS-Farbnamens in hexadezimal in Node.js schreiben, möchten jedoch stattdessen eine Ruby-Farbbibliothek für die Konvertierung verwenden.

Wir geben Ruby-Code an, der als Zeichenfolge ausgeführt werden soll. Beachten Sie jedoch, dass wir nicht viel darin tun. Wir benötigen lediglich die Bibliotheken und geben dann ein Ruby-Objekt zurück. Die Verwendung dieses Objekts aus Ruby besteht normalerweise darin, Color :: RGB.by_name (name) .html zu sagen. Wenn Sie sich ansehen, wie color_rgb weiter unten von JavaScript verwendet wird, können Sie sehen, dass wir diese Methoden tatsächlich aus JavaScript aufrufen, obwohl es sich um Ruby-Objekte und -Methoden handelt. Wir übergeben ihnen eine JavaScript-Zeichenfolge und verketten das Ergebnis. Dies ist eine Ruby-Zeichenfolge mit anderen JavaScript-Zeichenfolgen.

Wir werden sowohl unsere Ruby- als auch unsere JavaScript-Abhängigkeiten installieren.

%%prettify 
{{{
$ gem install color
Abrufen: Farbe-1.8.gem (100%)
Color-1.8 erfolgreich installiert
1 Juwel installiert $ npm install express
+ express@4.17.0
50 Pakete von 37 Mitwirkenden hinzugefügt und 143 Pakete in 22.431s geprüft
}}}
/%


Wir müssen dann den Knoten mit einigen Optionen ausführen: --polyglot, um zu sagen, dass wir Zugriff auf andere Sprachen wünschen, und --jvm, da das native Bild des Knotens standardmäßig nicht mehr als JavaScript enthält.

%%prettify 
{{{
$ node --polyglot --jvm color-server.js
Serving unter http: // localhost: 8080
}}}
/%

Öffnen Sie dann wie gewohnt http: // localhost: 8080 / css / aquamarine oder einen anderen Farbnamen in Ihrem Browser.

[{Image src='https://miro.medium.com/max/700/1*FFrMNcdEuhIgiHz7gp54Ig.png' width='..' height='..' align='left|center|right' style='..' class='..' }]

Bild für Beitrag

Versuchen wir ein größeres Beispiel mit mehr Sprachen und Modulen.

JavaScript bietet keine großartige Lösung für beliebig große Ganzzahlen. Ich habe mehrere Module wie Big-Integer gefunden, aber diese sind alle ineffizient, da sie Komponenten der Zahl als JavaScript-Gleitkommazahlen speichern. Die BigInteger-Klasse von Java ist effizienter. Verwenden Sie diese Option stattdessen, um eine beliebig große Ganzzahlarithmetik auszuführen.

JavaScript bietet auch keine integrierte Unterstützung für das Zeichnen von Diagrammen, wobei R eine hervorragende Unterstützung dafür bietet. Verwenden Sie das svg-Modul von R, um ein 3D-Streudiagramm einer trigonometrischen Funktion zu zeichnen.

In beiden Fällen können wir die Polyglot-API von GraalVM verwenden und die Ergebnisse dieser anderen Sprachen einfach in JavaScript zusammenstellen.

Öffnen Sie http: // localhost: 3000 / in Ihrem Browser, um das Ergebnis anzuzeigen.


[{Image src='https://miro.medium.com/max/700/1*NPuHZJZouIOMaVSjey9xUg.png' width='..' height='..' align='left|center|right' style='..' class='..' }]


Bild für Beitrag

Dies ist das dritte, was wir mit GraalVM tun können - Programme ausführen, die in mehreren Sprachen geschrieben sind, und Module aus diesen Sprachen zusammen verwenden. Wir betrachten dies als eine Art Kommerzialisierung von Sprachen und Modulen - Sie können jede Sprache verwenden, die Ihrer Meinung nach für Ihr Problem am besten geeignet ist, und jede Bibliothek, die Sie möchten, unabhängig davon, aus welcher Sprache sie stammt.

! 4. Führen Sie Muttersprachen in der JVM aus

Eine andere Sprache, die GraalVM unterstützt, ist C. GraalVM kann C-Code genauso ausführen wie Sprachen wie JavaScript und Ruby.

Was GraalVM tatsächlich unterstützt, ist die Ausführung der Ausgabe der LLVM-Toolchain - LLVM-Bitcode - anstatt C direkt zu unterstützen. Dies bedeutet, dass Sie Ihr vorhandenes Tool mit C und anderen Sprachen verwenden können, die LLVM ausgeben können, z. B. C ++, Fortran und möglicherweise andere Sprachen in der Zukunft. Um die Demo zu vereinfachen, verwende ich eine spezielle Einzeldateiversion von gzip, die von Stephen McCamant verwaltet wird. Der Einfachheit halber sind nur der gzip-Quellcode und die Autoconf-Konfiguration in einer Datei zusammengefasst. Ich musste auch ein paar Dinge patchen, damit es unter macOS und mit clang funktioniert, aber nicht, um es unter GraalVM zum Laufen zu bringen.

Dann können wir mit Standard-Clang (dem LLVM C-Compiler) kompilieren, und wir möchten, dass es mit LLVM-Bitcode kompiliert wird, nicht mit nativer Assembly, da GraalVM genau das ausführen kann. Ich benutze Clang 4.0.1.

%%prettify 
{{{
$ clang -c -emit-llvm gzip.c
}}}
/%


Und dann führen wir dies direkt mit GraalVM mit dem Befehl lli (LLVM-Bitcode-Interpreter) aus. Versuchen wir, eine Datei mit meinem System gzip zu komprimieren und dann mit gzip zu dekomprimieren, das auf GraalVM ausgeführt wird.

%%prettify 
{{{
$ cat small.txt
Lorem ipsum dolor sitzen amet ...
$ gzip small.txt
$ lli gzip.bc -d small.txt.gz
$ cat small.txt
Lorem ipsum dolor sitzen amet ...

}}}
/%

Alternativ kann C / C ++ - Code mithilfe des mit GraalVM gelieferten Clangs zu LLVM-Bitcode kompiliert werden. Dazu sollten Sie eine vorgefertigte LLVM-Toolchain-Unterstützung aktivieren und die Umgebungsvariable LLVM_TOOLCHAIN ​​auf das Verzeichnis verweisen, das eine Reihe von Build-Tools enthält, z. B. einen C-Compiler und einen Linker, mit denen ein natives Projekt in Bitcode kompiliert werden kann.

%%prettify 
{{{
$ gu install llvm-toolchain
$ export LLVM_TOOLCHAIN ​​= $ (lli --print-toolchain-path)
}}}
/%


Anschließend können Sie den Quellcode von gzip.c zu einer ausführbaren Datei mit eingebettetem LLVM-Bitcode kompilieren und wie folgt ausführen:

%%prettify 
{{{
$ $ LLVM_TOOLCHAIN ​​/ clang gzip.c -o gzip
$ gzip small.txt
$ lli gzip -d small.txt.gz
$ cat small.txt
Lorem ipsum dolor sitzen amet ...
}}}
/%


Die Implementierungen von Ruby und Python in GraalVM verwenden diese Technik, um C-Erweiterungen für diese Sprachen auszuführen. Dies bedeutet, dass Sie C-Erweiterungen innerhalb der VM ausführen können, und es ermöglicht uns, eine hohe Leistung aufrechtzuerhalten, auch wenn diese älteren nativen Erweiterungsschnittstellen unterstützt werden.

Dies ist eine vierte Möglichkeit, die Sie mit GraalVM ausführen können. Führen Sie Programme aus, die in Muttersprachen wie C und C ++ geschrieben sind, und führen Sie C-Erweiterungen für Sprachen wie Python und Ruby aus, was vorhandene JVM-Implementierungen wie JRuby nicht können.

! 5. Tools, die in allen Sprachen funktionieren

Wenn Sie in Java programmieren, sind Sie wahrscheinlich an sehr hochwertige Tools wie IDEs, Debugger und Profiler gewöhnt. Nicht alle Sprachen verfügen über diese Art von Tools, aber Sie erhalten sie, wenn Sie eine Sprache in GraalVM verwenden.

Alle GraalVM-Sprachen (außer Java im Moment) werden unter Verwendung des gemeinsamen Truffle-Frameworks implementiert. Auf diese Weise können wir Funktionen wie Debugger einmal implementieren und für alle Sprachen verfügbar machen.

Um dies zu versuchen, schreiben wir ein grundlegendes FizzBuzz-Programm, da es Dinge auf dem Bildschirm druckt und klare Verzweigungen aufweist, die nur bei einigen Iterationen verwendet werden, sodass wir einige Haltepunkte einfacher festlegen können. Wir beginnen mit einer JavaScript-Implementierung.

Wir können dieses JavaScript-Programm wie gewohnt mit GraalVM und der ausführbaren Datei js ausführen.

%%prettify 
{{{
$ js fizzbuzz.js
1
2
Fizz
4
Summen
Fizz
...
}}}
/%


Wir können das Programm auch mit der Flagge --inspect ausführen. Dadurch erhalten wir einen Link zum Öffnen in Chrome und das Programm wird im Debugger angehalten.

%%prettify 
{{{
$ js --inspekt fizzbuzz.js
Debugger überwacht Port 9229.
Öffnen Sie zum Starten des Debuggens die folgende URL in Chrome:
    chrome-devtools: //devtools/bundled/inspector.html? ws = 127.0.0.1: 9229 / 6c478d4e-1350b196b409
...

}}}
/%

Wir können dann einen Haltepunkt in der FizzBuzz-Zeile festlegen und dann die Ausführung fortsetzen. Wenn es kaputt geht, sehen wir den Wert von n und können erneut fortfahren oder den Rest der Debugging-Oberfläche erkunden.
Bild für Beitrag
Bild für Beitrag

Der Chrome-Debugger wird normalerweise mit JavaScript verwendet, aber JavaScript in GraalVM hat nichts Besonderes. Dieses Flag ist auch verfügbar und funktioniert in unseren Implementierungen von Python, Ruby und R. Ich werde Ihnen nicht die Quelle jedes Programms zeigen, aber Sie führen sie auf genau dieselbe Weise aus und erhalten für jedes Programm dieselbe Chrome-Debugger-Oberfläche.

$ graalpython --inspect fizzbuzz.py

[{Image src='https://miro.medium.com/max/700/1*kQoJRkHNZtZ-XiEer4HLwg.png' width='..' height='..' align='left|center|right' style='..' class='..' }]

Bild für Beitrag

$ ruby ​​--inspect fizzbuzz.rb

[{Image src='https://miro.medium.com/max/700/1*F072cZoIA3oaoBA1OzCOEQ.png' width='..' height='..' align='left|center|right' style='..' class='..' }]

Bild für Beitrag

$ Rscript --inspect fizzbuzz.r

[{Image src='https://miro.medium.com/max/700/1*c2oldXo8fZCMVDZJXu56DQ.png' width='..' height='..' align='left|center|right' style='..' class='..' }]

Bild für Beitrag

Ein weiteres Tool, mit dem Sie möglicherweise bereits aus Java vertraut sind, ist VisualVM. Sie erhalten eine Benutzeroberfläche, über die Sie eine Verbindung zu einer laufenden JVM auf Ihrem Computer oder über ein Netzwerk herstellen können, um verschiedene Aspekte zu überprüfen, z. B. die Verwendung von Speicher und Threads.

GraalVM enthält VisualVM mit dem Standardbefehl jvisualvm.

$ jvisualvm &> / dev / null &

Wenn wir es ausführen, während wir unsere Java TopTen-Anwendung von zuvor ausführen, können wir die Speichernutzung im Laufe der Zeit beobachten oder einen Heap-Dump erstellen und untersuchen, welche Art von Objekten Speicher in unserem Heap verwenden.

$ java TopTen large.txt

[{Image src='https://miro.medium.com/max/700/1*nb6YQ7Yoa-ZfeZIIMKpT8Q.png' width='..' height='..' align='left|center|right' style='..' class='..' }]

Bild für Beitrag

Ich habe dieses Ruby-Programm geschrieben, um im Laufe der Zeit Müll zu erzeugen.

Wenn Sie eine Standard-JVM-Sprache wie JRuby mit VisualVM ausführen, werden Sie enttäuscht sein, dass Sie die zugrunde liegenden Java-Objekte und keine Informationen zu den Objekten Ihrer Sprache sehen.

Wenn wir stattdessen die GraalVM-Version von Ruby verwenden, erkennt VisualVM die Ruby-Objekte selbst. Wir müssen den Befehl --jvm verwenden, um VisualVM zu verwenden, da er die native Version von Ruby nicht unterstützt.

$ ruby ​​--jvm render.rb

Wir können denselben Heap-View-Dump der zugrunde liegenden Java-Objekte sehen, wenn wir möchten, oder unter Zusammenfassung können wir Ruby-Heap auswählen und stattdessen die richtigen Ruby-Objekte anzeigen.

[{Image src='https://miro.medium.com/max/700/1*C8eLLZkW1zjVLBMRpm-p5A.png' width='..' height='..' align='left|center|right' style='..' class='..' }]

Bild für Beitrag

Das Trüffel-Framework ist eine Art Nexus für Sprachen und Werkzeuge. Wenn Sie Ihre Sprachen mit Truffle programmieren und Ihre Tools wie diesen Debugger mit der Tool-API von Truffle programmieren, funktioniert jedes Tool mit jeder Sprache, und Sie müssen das Tool nur einmal schreiben.

Die fünfte Möglichkeit, GraalVM zu verwenden, besteht darin, qualitativ hochwertige Tools für Sprachen zu erhalten, die nicht immer die Unterstützung haben, maßgeschneiderte Tools wie den Chrome Debugger oder VisualVM zu erstellen.

! 6. Erweitern Sie eine JVM-basierte Anwendung

Diese Sprachen und Tools können nicht nur als eigenständige Sprachimplementierungen und zusammen in einem polyglotten Anwendungsfall verwendet werden, sondern auch in Ihre Java-Anwendung eingebettet werden. Mit einer neuen org.graalvm.polyglot-API können Sie Code in anderen Sprachen laden, ausführen und Werte daraus verwenden.

Wenn Sie die Befehle javac und java von GraalVM verwenden, befinden sich die Importe org.graalvm ... bereits in Ihrem Klassenpfad, sodass Sie diese ohne zusätzliche Flags kompilieren und ausführen können.

%%prettify 
{{{
$ javac ExtendJava.java
$ java ExtendJava '14 + 2 '
16
$ java ExtendJava -js 'Math.sqrt (14)'
3.7416573867739413
$ java ExtendJava -python '[2 ** n für n im Bereich (0, 8)]'
[1, 2, 4, 8, 16, 32, 64, 128]
$ java ExtendJava -ruby '[4, 2, 3] .sort'
[2, 3, 4]
}}}
/%


Diese Versionen der Sprachen sind dieselben leistungsstarken Polyglot-Versionen, die Sie durch die Verwendung von Befehlen wie node und ruby ​​wie die ausführbaren GraalVM-Dateien erhalten.

Dies ist eine sechste Möglichkeit, GraalVM als einzelne Schnittstelle zu verwenden, um viele verschiedene Sprachen in Ihre Java-Anwendung einzubetten. Mit der Polyglot-API können Sie Objekte in Gastsprache als Java-Schnittstellen und andere ausgefeilte Interoperabilität verwenden.

! 7. Erweitern Sie eine native Anwendung

GraalVM enthält bereits eine native Bibliothek, die wie folgt aufgebaut ist. Mit dieser Bibliothek können Sie Code ausführen, der in einer beliebigen GraalVM-Sprache aus nativen Anwendungen geschrieben wurde. JavaScript-Laufzeiten wie V8 und Python-Interpreter wie CPython können häufig eingebettet werden, sodass sie als Bibliothek in eine andere Anwendung verknüpft werden können. Mit GraalVM können Sie jede Sprache in einem eingebetteten Kontext verwenden, indem Sie eine Verknüpfung zu dieser einen polyglotten Einbettungsbibliothek herstellen.

Die Bibliothek wird bereits erstellt, wenn Sie GraalVM erhalten, enthält jedoch standardmäßig nur die integrierte Sprache JavaScript. Mit dem folgenden Befehl können Sie die Polyglot-Bibliothek neu erstellen, um andere Sprachen einzuschließen. Sie müssen jedoch Oracle GraalVM Enterprise Edition Native Image Early Adopter auf Basis von JDK8 für MacOS (19.3.0) von OTN herunterladen. Die Neuerstellung dauert einige Minuten. Sie können also nur mit JavaScript experimentieren, wenn Sie mitmachen. Sie müssen nicht neu erstellen, wenn Sie nur JavaScript möchten.

%%prettify 
{{{
$ gu install --force --file native-image-installable-svm-svmee-java8-darwin-amd64-19.3.0.jar
$ gu Rebuild-Images libpolyglot

}}}
/%

Wir können ein einfaches C-Programm schreiben, das Befehle in jeder GraalVM-Sprache ausführt, die über die Befehlszeile übergeben wird. Wir werden das Äquivalent unseres ExtendJava-Beispiels von oben ausführen, jedoch mit C als Hostsprache.

Wir können dies dann mit unserem System C-Compiler kompilieren und ausführen und eine Verknüpfung zur nativen Polyglot-Bibliothek in GraalVM herstellen. Auch hier ist keine JVM erforderlich.

%%prettify 
{{{
$ clang -L $ GRAALVM_HOME / jre / lib / polyglot -I $ {GRAALVM_HOME} / jre / lib / polyglot -lpolyglot -o verlängernc -O1 verlängernc.c -pfad $ GRAALVM_HOME
$ otool -L extensc
verlängern:
  @ rpath / jre / lib / polyglot / libpolyglot.dylib (Kompatibilitätsversion 0.0.0, aktuelle Version 0.0.0)
  /usr/lib/libSystem.B.dylib (Kompatibilitätsversion 1.0.0, aktuelle Version 1252.250.1)

$ ./extendc '14 + 2 '
16
$ ./extendc -js 'Math.sqrt (14)'
3.7416573867739413
$ ./extendc -python '[2 ** n für n im Bereich (0, 8)]'
[1, 2, 4, 8, 16, 32, 64, 128]
$ ./extendc -ruby '(0 ... 8) .map {| n | 2 ** n} '
[1, 2, 4, 8, 16, 32, 64, 128]

}}}
/%

Dies ist eine siebte Möglichkeit, die Sie mit GraalVM ausführen können. Verwenden Sie eine einzelne Bibliothek in Ihrer nativen Anwendung, um eine beliebige GraalVM-Sprache einzubetten.

! 8. Java-Code als native Bibliothek

Java verfügt über ein großartiges Ökosystem mit vielen Bibliotheken von sehr hoher Qualität, die in anderen Ökosystemen, einschließlich nativer Anwendungen sowie anderer verwalteter Sprachen, häufig nicht verfügbar sind. Wenn Sie eine Java-Bibliothek aus einer nativen Anwendung verwenden möchten, können Sie die JVM einbetten, dies wird jedoch sehr schnell sehr umfangreich und kompliziert.

Mit GraalVM können Sie eine Java-Bibliothek von der Stange oder eine von Ihnen selbst geschriebene Bibliothek in eine eigenständige native Bibliothek kompilieren, um sie aus anderen Muttersprachen zu verwenden. Wie bei unserer nativen Kompilierung zuvor ist für die Ausführung keine JVM erforderlich.

Ich habe eine Anwendung geschrieben, die die hervorragende Apache SIS-Geodatenbibliothek verwendet, um den Großkreisabstand zwischen zwei Punkten auf der Erde zu berechnen. Ich habe SIS 0.8 verwendet, das ich separat von http://sis.apache.org/ heruntergeladen und das Glas aus extrahiert habe.

Wir können dies wie gewohnt kompilieren und dann die Entfernung zwischen London (51.507222 Breitengrad, -0.1275 Breitengrad) und New York (40.7127, -74.0059) berechnen.

%%prettify 
{{{
$ javac -cp sis.jar -parameters Distance.java
$ java -cp sis.jar:. Entfernung 51.507222 -0.1275 40.7127 -74.0059
5570,25 km
}}}
/%


Wir können das zu einer nativen ausführbaren Datei kompilieren, wie wir es mit unserem Topten-Programm getan haben.

%%prettify 
{{{
$ native-image --no-server --no-fallback -cp sis.jar:. Entfernung
...
$ ./distance 51.507222 -0.1275 40.7127 -74.0059
5570,25 km
}}}
/%


Wir können dies auch als native gemeinsam genutzte Bibliothek anstelle einer ausführbaren Datei erstellen. Dazu deklarieren wir eine oder mehrere Methoden als @CEntryPoint.

Wir müssen unsere javac-Befehlszeile nicht ändern, da GraalVM diese neuen APIs automatisch in den Klassenpfad einfügt. Wir können dann zu einer gemeinsam genutzten Bibliothek und einer automatisch generierten Header-Datei kompilieren.

%%prettify 
{{{
$ native-image --no-server -cp sis.jar:. --shared -H: Name = libdistance
$ otool -L libdistance.dylib # .so unter Linux
libdistance.dylib:
  ... / graalvm-ten-things / libdistance.dylib (Kompatibilitätsversion 0.0.0, aktuelle Version 0.0.0)
/usr/lib/libSystem.B.dylib (Kompatibilitätsversion 1.0.0, aktuelle Version 1252.250.1)
CoreFoundation (Kompatibilitätsversion 150.0.0, aktuelle Version 1575.17.0)
/usr/lib/libz.1.dylib (Kompatibilitätsversion 1.0.0, aktuelle Version 1.2.11)
$ du -h libdistance.dylib
1,8 M libdistance.dylib
}}}
/%


Wir können dann ein kleines C-Programm schreiben, um die Bibliothek zu benutzen. Die Schnittstelle zu unserer nativen Bibliothek hat eine kleine Zeremonie - da die VM einen Heap, Threads, einen Garbage Collector und andere Dienste verwalten muss, müssen wir eine Instanz des Systems erstellen und sie über unseren Hauptthread informieren.

Wir kompilieren dies mit unseren Standardsystemtools und können unsere ausführbare Datei ausführen (setzen Sie LD_LIBRARY_PATH =. Unter Linux).

%%prettify 
{{{
$ clang -I. -L. -entfernung.c -o entfernung
$ otool -L Abstand
Entfernung:
... / graalvm-blog-post / libdistance.dylib (Kompatibilitätsversion 0.0.0, aktuelle Version 0.0.0)
libSystem.B.dylib (Kompatibilitätsversion 1.0.0, aktuelle Version 1252.250.1)
$ ./distance 51.507222 -0.1275 40.7127 -74.0059
5570,25 km
}}}
/%


Dies ist eine achte Sache, die wir mit GraalVM machen können - kompilieren Sie Java-Code in eine native Bibliothek, die wir dann in nativen Anwendungen verwenden können, ohne eine vollständige JVM zu verwenden.

! 

2210/5000
9. Polyglot in der Datenbank

Eine Anwendung der Polyglot-Bibliothek zum Einbetten von Sprachen befindet sich in der Oracle-Datenbank. Wir haben damit die Oracle Database Multilingual Engine (MLE) erstellt, die die Verwendung von GraalVM-Sprachen und -Modulen aus SQL unterstützt.

Angenommen, wir haben bereits ein Frontend in JavaScript geschrieben und führen eine Validierung der E-Mail-Adressen mithilfe des JavaScript-Modulvalidators durch. Wenn wir eine Logik für dieselbe Anwendung in der in SQL oder PLSQL geschriebenen Datenbank haben, möchten wir in der Lage sein, genau denselben Validator zu verwenden, damit die Ergebnisse gleich sind.

Sie können das MLE als Docker-Image von https://oracle.github.io/oracle-db-mle/releases/0.2.7/docker/ herunterladen. Laden Sie es dann in Docker.

%%prettify 
{{{
$ docker load --input mle-docker-0.2.7.tar.gz

}}}
/%

Wir möchten das Image ausführen und dann, wenn es vollständig geladen ist, was einige Minuten dauern kann, ein Bash-Terminal darin ausführen.

%%prettify 
{{{
$ docker run mle-docker-0.2.7
$ docker ps
$ docker exec -ti <container_id> bash -li
}}}
/%


Wenn wir das interaktive SQL-Tool sqlplus in diesem Bash-Terminal ausführen können, um eine Verbindung zur Datenbank herzustellen, ist es betriebsbereit.

%%prettify 
{{{
$ sqlplus scott / tiger @ localhost: 1521 / ORCLCDB
}}}
/%


Jetzt, noch im Bash-Terminal, das in Docker ausgeführt wird, installieren wir dieses Validierungsmodul und führen dann einen Befehl dbjs aus, um es in der Datenbank bereitzustellen. Dann führen wir wieder sqlplus aus.

%%prettify 
{{{
$ npm Install Validator
$ npm install @ types / validator
$ dbjs implementieren -u scott -p tiger -c localhost: 1521 / ORCLCDB-Validator
$ sqlplus scott / tiger @ localhost: 1521 / ORCLCDB
}}}
/%


Wir können jetzt das Validator-Modul als Teil eines SQL-Ausdrucks verwenden.

%%prettify 
{{{
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
}}}
/%


Dies ist unsere neunte Sache, die Sie mit GraalVM tun können - führen Sie GraalVM-Sprachen in der Oracle-Datenbank aus, damit Sie dieselbe Logik von Ihren Frontends oder Backends in Ihrer Datenbanklogik verwenden können, anstatt sie immer aus der Datenbank in eine Datenbank ziehen zu müssen Anwendungsserver.

! 10. Erstellen Sie Ihre eigene Sprache

Oracle Labs und unsere akademischen Mitarbeiter konnten mit einem relativ kleinen Team neue Hochleistungsimplementierungen von JavaScript, R, Ruby, Python und C erstellen, da wir das Truffle-Framework entwickelt haben, um dies zu vereinfachen.

Truffle ist eine Java-Bibliothek, mit der Sie einen AST-Interpreter (Abstract Syntax Tree) für eine Sprache schreiben können. Ein AST-Interpreter ist wahrscheinlich der einfachste Weg, eine Sprache zu implementieren, da er direkt mit der Ausgabe des Parsers arbeitet und keinen Bytecode oder herkömmliche Compilertechniken enthält, aber häufig langsam ist. Wir haben es daher mit einer Technik kombiniert, die als Teilbewertung bezeichnet wird und es Truffle ermöglicht, den GraalVM-Compiler zu verwenden, um automatisch eine Just-in-Time-Kompilierung für Ihre Sprache bereitzustellen, die nur auf Ihrem AST-Interpreter basiert.

Mit Truffle können Sie Ihre eigene neue Programmiersprache implementieren, eine Hochleistungsimplementierung einer vorhandenen Programmiersprache erstellen oder eine domänenspezifische Sprache implementieren. Wir sprechen in unserem Projekt viel über die Details von Trüffel und Graal, aber wir vergessen oft zu erwähnen, dass Trüffel der einfache Weg ist, eine Sprache zu implementieren. Und Sie erhalten Funktionen wie den Debugger automatisch. Jeder, der nur ein Grundstudium zur Implementierung von Programmiersprachen absolviert hat, sollte über die erforderlichen Grundkenntnisse verfügen. Oracle Labs implementierte eine Basisversion von Ruby schneller als alle vorherigen Bemühungen mit nur einem Praktikanten über einige Monate.

Wir haben hier keinen Platz, um eine vollständige Sprache anzuzeigen, auch keine winzige, aber SimpleLanguage ist ein ausführbares Tutorial zum Erstellen einer eigenen Sprache mit Truffle, das auf einer vereinfachten Sprache im JavaScript-Stil basiert. Siehe zum Beispiel die Implementierung der if-Anweisung.

Andere Sprachen, die von Personen außerhalb von Oracle Labs mit Truffle geschrieben wurden, umfassen eine Smalltalk-Variante, eine Newspeak-Variante und eine Lisp-Variante. Das Lisp-Beispiel enthält ein Tutorial, dem Sie folgen können.

! Fazit

GraalVM ermöglicht eine Vielzahl neuer Funktionen - eine Plattform, auf der Sie leistungsfähigere Sprachen und Tools erstellen und in mehr Umgebungen integrieren können. Hier können Sie die gewünschte Sprache und Module auswählen, unabhängig davon, wo das Programm ausgeführt wird oder welche Sprachen Sie bereits verwenden.

Um GraalVM zu testen, gehen Sie zu https://www.graalvm.org/. Dort finden Sie Links zu Downloads und Dokumentationen sowie weitere Beispiele, wie wir sie in diesem Blogbeitrag gezeigt haben.

Befolgen Sie die Anweisungen hier und passen Sie sie an, um zu sehen, was Sie sonst noch tun können. Lassen Sie uns wissen, wie Sie in Ihrer Anwendung mit GraalVM experimentieren, und senden Sie uns Feedback an ChrisGSeaton oder Shelajev.

GraalVM-Teamblog - https://www.graalvm.org \\
Vielen Dank an Oleg Šelajev, Olya Gupalo und Doug Simon. \\
Fazit