
Dari penerjemah: GraalVM adalah teknologi baru yang menarik, tetapi di Habré tidak ada banyak artikel yang dapat menunjukkan contoh-contoh kemampuan Graal. Artikel di bawah ini bukan hanya daftar apa yang dapat dilakukan GraalVM, tetapi juga kelas master kecil yang mirip dengan yang dilakukan Chris Seaton dan Oleg Shelaev di Oracle CodeOne 2018. Setelah penulis, saya mendorong Anda untuk mencoba membuat contoh dari artikel, itu benar-benar menarik
Ada banyak hal berbeda di GraalVM , dan jika Anda mendengar nama ini sebelumnya, atau bahkan melihat laporan, masih ada banyak hal yang mungkin belum Anda ketahui, tetapi yang dapat dilakukan GraalVM. Pada artikel ini, kita akan melihat berbagai fitur yang disediakan GraalVM dan menunjukkan apa yang dapat Anda lakukan dengannya.
- Eksekusi cepat Java
- Kurangi waktu mulai dan penggunaan memori untuk Java
- Menggabungkan JavaScript, Java, Ruby, dan R
- Eksekusi program yang ditulis dalam bahasa platform-spesifik
- Alat umum untuk semua bahasa pemrograman
- Suplemen Aplikasi JVM
- Aplikasi Ketergantungan Platform
- Kode Java sebagai pustaka khusus platform
- Dukungan untuk beberapa bahasa pemrograman dalam database
- Membuat bahasa pemrograman untuk GraalVM
Anda dapat melakukan semua yang ditampilkan dalam artikel ini menggunakan GraalVM 1.0.0 RC1, yang tersedia melalui tautan dari situs web GraalVM . Saya menggunakan MacOS Enterprise Edition, tetapi kode yang ditulis di sini akan berfungsi di Linux dan GraalVM Community Edition.
Saat Anda membaca artikel, jalankan program yang dijelaskan di dalamnya! Kode dapat diunduh dari GitHub .
Instalasi
Setelah mengunduh dari http://graalvm.org/downloads, saya menambahkan path ke executable GraalVM dalam $PATH
. Secara default, ini menambahkan dukungan untuk eksekusi Java dan 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 hadir dengan dukungan JavaScript bawaan dan berisi manajer paket bernama gu
yang menambahkan kemampuan untuk menginstal dukungan untuk bahasa selain Java dan JavaScript. Saya juga menginstal Ruby, Python dan R, mereka diunduh dari GitHub.
$ gu install -c org.graalvm.ruby $ gu install -c org.graalvm.python $ gu install -c org.graalvm.R
Sekarang, jika Anda menjalankan perintah java
atau js
, Anda akan melihat versi GraalVM dari mesin ini.
$ 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. Eksekusi Java cepat
"Graal" di GraalVM adalah nama dari kompiler. Dia sendiri diciptakan untuk memerintah semua ! Ini berarti bahwa ini adalah salah satu implementasi kompiler yang ditulis dalam bentuk perpustakaan yang dapat digunakan untuk banyak hal yang berbeda. Sebagai contoh, kami menggunakan Graal untuk mengkompilasi sebelumnya dan tepat waktu untuk mengkompilasi kode yang ditulis dalam bahasa pemrograman yang berbeda, termasuk untuk arsitektur prosesor yang berbeda.
Cara pertama dan termudah untuk menggunakan Graal adalah menggunakannya sebagai kompiler Java JIT.
Sebagai contoh, kita akan menggunakan program yang menghasilkan 10 kata paling umum dalam sebuah dokumen. Program ini menggunakan kemampuan bahasa Jawa modern, seperti Streaming dan koleksi.
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 termasuk kompiler javac
, tetapi tidak ada perbedaan untuk demo ini apakah akan menggunakannya atau kompiler standar. Oleh karena itu, Anda dapat menggunakan kompiler javac
standar jika Anda mau.
$ javac TopTen.java
Jika kita menjalankan perintah java
, yang termasuk dalam GraalVM, maka kompiler Grait JIT akan digunakan secara otomatis - tidak diperlukan langkah-langkah tambahan. Saya akan menggunakan perintah time
untuk mendapatkan data nyata tentang waktu yang dihabiskan untuk menjalankan program dari awal sampai akhir, alih-alih menggunakan microbenchmark yang kompleks. Sejumlah besar input juga akan digunakan sehingga tidak ada sindiran tentang beberapa detik yang disimpan di sini atau di sana. Ukuran file large.txt
adalah 150 MB.
$ 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 ditulis dalam Java, bukan C ++, seperti kebanyakan kompiler JIT lainnya untuk Java. Kami berpikir bahwa ini memungkinkan kami untuk memperbaikinya lebih cepat daripada kompiler yang ada, menambahkan optimisasi kuat baru (seperti, misalnya, analisis pelarian parsial) yang tidak tersedia dalam kompiler JIT standar untuk HotSpot.
Dan ini dapat membuat program Java Anda lebih cepat.
Untuk tujuan perbandingan, untuk menjalankan program tanpa kompiler Grait JIT, saya akan menggunakan -XX:-UseJVMCICompiler
. JVMCI adalah antarmuka antara Graal dan JVM. Anda juga dapat menjalankan contoh pada JVM standar dan membandingkan hasilnya.
$ 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
Tes ini menunjukkan bahwa Graal menjalankan program Java kami dalam waktu sekitar tiga perempat waktu yang dibutuhkan untuk menjalankannya dengan kompiler HotSpot standar. Di mana kami percaya bahwa meningkatkan produktivitas dengan satuan persen adalah pencapaian yang signifikan, 25% adalah masalah besar.
Twitter adalah satu-satunya perusahaan saat ini yang menggunakan Graal di server "pertempuran" , dan mereka mengatakan itu dibenarkan untuk mereka, dalam hal menghemat uang nyata. Twitter menggunakan Graal untuk menjalankan aplikasi yang ditulis dalam Scala - Graal bekerja pada level bytecode JVM, yaitu berlaku untuk bahasa JVM apa pun.
Ini adalah kasus penggunaan pertama untuk GraalVM - cukup mengganti kompiler JIT dengan versi yang lebih baik untuk aplikasi Java yang ada.
2. Kurangi waktu mulai dan penggunaan memori untuk Java
Kekuatan platform Java terutama terlihat ketika bekerja dengan proses yang berjalan lama dan beban puncak. Proses jangka pendek, sebaliknya, menderita waktu startup yang lama dan penggunaan memori yang relatif tinggi.
Sebagai contoh, jika kita menjalankan aplikasi dari bagian sebelumnya, mengumpankannya dengan jumlah input data yang jauh lebih kecil - sekitar 1Kb dan bukannya 150MB, maka tampaknya itu akan memakan waktu terlalu lama dan cukup banyak memori - sekitar 60MB, untuk memproses file sekecil itu. . Kami menggunakan opsi -l
untuk mencetak jumlah memori yang digunakan selain waktu eksekusi.
$ 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 memberi kita alat yang memecahkan masalah ini. Kami mengatakan bahwa Graal adalah perpustakaan kompiler dan dapat digunakan dengan berbagai cara. Salah satunya adalah mengkompilasi di muka menjadi image yang dapat dieksekusi yang bergantung pada platform, alih-alih mengkompilasi just-in-time pada saat run time. Ini mirip dengan cara kerja kompiler biasa, seperti 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
Perintah ini menciptakan topten
platform- topten
disebut topten
. File ini tidak memulai JVM, tidak tertaut ke JVM, dan tidak termasuk JVM dengan cara apa pun. Perintah native-image
benar-benar mengkompilasi kode Java Anda dan perpustakaan Java yang Anda gunakan menjadi kode mesin lengkap. Untuk komponen runtime seperti pengumpul sampah, kami meluncurkan VM baru kami sendiri yang disebut SubstrateVM, yang, seperti Graal, juga ditulis dalam Java.
Jika Anda melihat dependensi yang menggunakan topten
, Anda akan melihat bahwa ini hanya pustaka sistem standar. Kami hanya dapat mentransfer file yang satu ini ke sistem di mana JVM belum pernah diinstal dan menjalankannya di sana untuk memverifikasi bahwa itu tidak menggunakan JVM atau file lain. Topten
juga cukup kecil - kode yang dapat dieksekusi memakan waktu kurang dari 6 MB.
$ otool -L topten # ldd topten on Linux topten: .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h topten 5.7M topten
Jika kita menjalankan executable ini, kita akan melihat bahwa itu memulai tentang urutan besarnya lebih cepat dan menggunakan sekitar urutan besarnya lebih sedikit memori daripada program yang sama berjalan di bawah JVM. Peluncuran ini sangat cepat sehingga Anda tidak akan memperhatikan berapa lama. Jika Anda menggunakan baris perintah, Anda tidak akan merasakan jeda yang biasanya hadir ketika Anda menjalankan program kecil, berumur pendek di bawah 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
Utilitas native-image
memiliki beberapa keterbatasan . Jadi, pada waktu kompilasi Anda harus memiliki semua kelas hadir, ada juga pembatasan penggunaan API Refleksi. Tetapi ada beberapa keuntungan tambahan atas kompilasi dasar, seperti pelaksanaan initialisator statis pada waktu kompilasi. Dengan demikian, jumlah pekerjaan yang dilakukan setiap kali aplikasi diunduh berkurang.
Ini adalah aplikasi kedua GraalVM - distribusi dan eksekusi program Java yang ada, dengan awal yang cepat dan konsumsi memori yang lebih sedikit. Metode ini memperbaiki masalah konfigurasi seperti menemukan tabung yang tepat saat runtime, dan juga memungkinkan Anda membuat gambar buruh pelabuhan yang lebih kecil.
3. Menggabungkan JavaScript, Java, Ruby, dan R
Bersama dengan Java, GraalVM mencakup implementasi baru JavaScript, Ruby, R, dan mesin Python. Mereka ditulis menggunakan kerangka kerja baru yang disebut Truffle . Kerangka kerja ini memungkinkan untuk membuat juru bahasa yang sederhana dan berkinerja tinggi. Ketika Anda menulis juru bahasa menggunakan Truffle, itu akan secara otomatis menggunakan Graal untuk memberikan kompilasi JIT untuk bahasa Anda. Jadi, Graal tidak hanya kompiler JIT dan kompiler AOT untuk Java, itu juga bisa menjadi kompiler JIT untuk JavaScript, Ruby, R dan Python.
Dukungan untuk bahasa pihak ketiga di GraalVM bertujuan untuk menjadi pengganti yang transparan untuk mesin yang ada untuk pelaksanaan berbagai bahasa. Sebagai contoh, kita dapat menginstal modul "warna" untuk Node.js:
$ npm install --global color ... + color@3.0.0 added 6 packages in 14.156s
Kemudian tulis sebuah program menggunakan modul ini untuk mengubah warna RGB HTML ke HSL:
var Color = require('color'); process.argv.slice(2).forEach(function (val) { print(Color(val).hsl().string()); });
Dan jalankan dengan cara biasa:
$ node color.js '#42aaf4' hsl(204.89999999999998, 89%, 60.8%)
Mesin eksekusi berbagai bahasa di GraalVM bekerja bersama - ada API yang memungkinkan Anda menjalankan kode dari satu bahasa dalam program yang ditulis dalam bahasa lain. Dan ini memungkinkan Anda untuk menulis program multibahasa - program yang ditulis dalam lebih dari satu bahasa pemrograman.
Ini mungkin diperlukan jika Anda menulis sebagian besar program Anda dalam satu bahasa, tetapi ingin menggunakan perpustakaan yang ditulis dalam bahasa pemrograman lain. Sebagai contoh, misalkan kita perlu menulis aplikasi untuk mengonversi nama warna dari CSS ke representasi numeriknya di Node.js, tetapi kami ingin menggunakan pustaka warna Ruby alih-alih menulis konversi sendiri.
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') });
Dalam kode ini, kami menulis bahwa kami perlu mengeksekusi kode Ruby sebagai string, tetapi perhatikan bahwa kami tidak melakukan banyak hal di sini - kami hanya menghubungkan pustaka dan kemudian mengembalikan objek Ruby. Di Ruby, kita akan menggunakannya seperti ini: Color::RGB.by_name (name).html
. Jika Anda melihat bagaimana color_rgb
digunakan nanti dalam JavaScript, Anda akan melihat bahwa kami benar-benar memanggil metode yang sama dari JavaScript, meskipun ini adalah objek dan metode Ruby. Dan kami meneruskannya sebagai string JavaScript dan menggabungkan hasilnya, yang merupakan string Ruby, dengan string JavaScript.
Instal kedua dependensi - Ruby dan 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
Maka Anda perlu memulai node
dengan beberapa opsi tambahan: --polyglot
, untuk mengatakan bahwa kami memerlukan akses ke bahasa lain dan --jvm
, karena gambar node
dapat dieksekusi secara default tidak menyertakan apa pun selain JavaScript.
$ node --polyglot --jvm color-server.js serving at http://localhost:8080
Dan kemudian pergi ke URL http: // localhost: 8080 / css / orange (atau warna lain), seperti biasa, di browser Anda.

Mari kita coba membuat contoh yang lebih serius, yang menggunakan lebih banyak bahasa dan modul.
JavaScript tidak mendukung bilangan bulat yang sangat besar. Saya menemukan beberapa modul seperti big-integer , tetapi semuanya tidak efisien karena menyimpan komponen suatu angka sebagai angka titik apung JavaScript. Kelas BigInteger
di Jawa lebih efisien, mari kita gunakan untuk melakukan beberapa operasi aritmatika dengan bilangan bulat besar.
JavaScript juga tidak memiliki dukungan bawaan untuk menggambar grafik, sementara R dengan baik menggambar grafik. Mari kita gunakan modul svg
dari R untuk menggambar sebidang sebaran fungsi trigonometri dalam ruang 3D.
Dalam kedua kasus, kami akan menggunakan API untuk mendukung multibahasa dari GraalVM (selanjutnya disebut sebagai Polyglot API) dan kami hanya dapat memasukkan hasil pelaksanaan program dalam bahasa lain ke dalam 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> '
Buka http: // localhost: 3000 / di browser Anda untuk melihat hasilnya:

Ini adalah hal ketiga yang dapat kita lakukan dengan GraalVM - menjalankan program yang ditulis dalam beberapa bahasa dan menggunakan modul dari bahasa ini bersama dalam satu program. Kami menyajikan ini sebagai cara untuk menyatukan lingkungan runtime dan pustaka - Anda dapat menggunakan bahasa pemrograman yang menurut Anda paling cocok untuk menyelesaikan tugas saat ini dan pustaka apa pun yang Anda inginkan, terlepas dari bahasa pemrograman yang digunakan.
Bahasa lain yang didukung GraalVM adalah C. GraalVM dapat mengeksekusi kode C dengan cara yang sama seperti mengeksekusi program yang ditulis dalam JavaScript dan Ruby.
Apa yang sebenarnya didukung GraalVM adalah eksekusi kode yang dihasilkan dari eksekusi utilitas LLVM, mis. bitcode, bukan dukungan langsung untuk C. Ini berarti Anda dapat menggunakan alat yang ada untuk bahasa C dan lainnya yang mendukung LLVM, seperti C ++, Fortran dan, berpotensi, lebih banyak bahasa di masa depan. Demi kesederhanaan demonstrasi, saya menjalankan versi khusus gzip , yang dirakit dalam satu file ( Stephen McCamant mendukung versi ini). Ini hanya kode sumber gzip
dan konfigurasi autoconf
digabungkan menjadi satu file untuk kesederhanaan. Saya harus menambal beberapa hal untuk membuatnya bekerja pada macOS dan dengan dentang, tapi saya tidak melakukan apa pun secara khusus untuk mendukung GraalVM.
Kami mengkompilasi gzip menggunakan clang
standar (kompiler LLVM untuk C) dan ingin itu membuat kami menjadi bitcode LLVM, dan bukan membangun platform-spesifik, karena GraalVM tidak akan meluncurkannya. Saya menggunakan clang
4.0.1.
$ clang -c -emit-llvm gzip.c
Dan kemudian jalankan hasilnya, langsung menggunakan perintah lli (LLVM bitcode interpreter) dari GraalVM. Mari kita coba kompres file menggunakan pengarsip sistem gzip saya, dan kemudian unzip menggunakan gzip yang berjalan di bawah 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...
Implementasi Ruby dan Python di GraalVM menggunakan teknik yang sama untuk menjalankan ekstensi yang ditulis dalam C untuk bahasa-bahasa ini. Ini berarti bahwa Anda dapat menjalankan ekstensi ini di dalam VM dan ini memungkinkan kami untuk mempertahankan kecepatan eksekusi yang tinggi bahkan jika kami menggunakan antarmuka ekstensi khusus platform yang sudah kedaluwarsa.
Ini adalah cara keempat untuk menggunakan GraalVM - menjalankan program yang ditulis dalam bahasa platform khusus, seperti C atau C ++, serta meluncurkan ekstensi ke bahasa seperti Python atau Ruby, yang tidak dapat membuat implementasi JVM dari bahasa ini, seperti JRuby.
5. Alat umum untuk semua bahasa pemrograman
Jika Anda memprogram di Jawa, maka Anda mungkin menggunakan alat yang sangat berkualitas tinggi seperti IDE, debugger, dan profiler. Tidak semua bahasa memiliki toolkit ini, tetapi Anda bisa mendapatkannya jika menggunakan bahasa yang didukung oleh GraalVM.
Dukungan untuk semua bahasa di GraalVM (kecuali Java, saat ini) diimplementasikan menggunakan kerangka kerja umum - Truffle. Ini memungkinkan kami membuat fungsionalitas, misalnya, debugger, sekali dan menggunakannya untuk semua bahasa.
Untuk mencoba ini, kami akan menulis program yang paling sederhana - FizzBuzz , karena ini visual (ia mencetak sesuatu di layar) dan memiliki cabang yang jelas yang hanya digunakan dalam beberapa iterasi. Dengan demikian, akan lebih mudah bagi kita untuk mengatur breakpoint. Mari kita mulai dengan implementasi 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)); }
Kami memulai program seperti biasa, menggunakan utilitas js
, di bawah GraalVM.
$ js fizzbuzz.js 1 2 Fizz 4 Buzz Fizz
Kita juga dapat menjalankan program dengan flag --inspect
. Ini akan memberi kami tautan yang dapat Anda buka di Chrome dan menghentikan program di debugger.
$ 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
Anda dapat mengatur breakpoint dalam kode FizzBuzz dan kemudian melanjutkan eksekusi. Ketika program menghentikan eksekusi, kita akan melihat nilai variabel n
di debugger dan kita dapat melanjutkan eksekusi program atau mempelajari antarmuka debugger.

Debugger di Chrome biasanya digunakan untuk JavaScript, tetapi untuk GraalVM di JavaScript tidak ada yang berbeda dari bahasa lain. Bendera --inspect
juga tersedia dan berfungsi dalam implementasi Python, Ruby, dan R. Saya tidak akan menunjukkan kepada Anda sumber dari setiap program, tetapi mereka menjalankan cara yang sama dan Anda mendapatkan debugger yang sama di Chrome untuk masing-masingnya.
$ graalpython --jvm --inspect fizzbuzz.py

$ ruby --inspect fizzbuzz.rb

$ Rscript --inspect fizzbuzz.r

Alat lain yang mungkin Anda kenal dari Jawa adalah VisualVM. Ini menyediakan antarmuka pengguna di mana Anda dapat bergabung dengan JVM yang berjalan pada mesin lokal Anda atau melalui jaringan untuk memeriksa berbagai aspek pelaksanaan program, seperti penggunaan memori atau eksekusi thread.
GraalVM menyertakan VisualVM sebagai utilitas jvisualvm
standar.
$ jvisualvm &> /dev/null &
Jika kita menjalankan VisualVM ketika program Java TopTen
, maka kita dapat mengamati penggunaan memori atau, misalnya, mengambil snapshot dari isi memori dan melihat jenis objek yang kita gunakan memori pada heap.
$ java TopTen large.txt

Saya menulis program ini di Ruby untuk menghasilkan beberapa sampah di memori saat runtime.
require 'erb' x = 42 template = ERB.new <<-EOF The value of x is: <%= x %> EOF loop do puts template.result(binding) end
Jika Anda menjalankan implementasi standar Ruby pada JVM - JRuby, Anda akan kecewa dengan VisualVM karena Anda hanya akan melihat objek Java internal alih-alih objek dalam bahasa Anda.
Jika Anda menggunakan versi Ruby untuk GraalVM, maka VisualVM mengenali objek Ruby. Kita perlu menggunakan opsi --jvm
untuk menggunakan VisualVM, sebagai itu tidak mendukung versi asli 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 , .
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.
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 , .
Kesimpulan
GraalVM — , , . , , , , .
GraalVM, http://www.graalvm.org/ . , , .
, , . , GraalVM @ChrisGSeaton @shelajev .
: Oleg Šelajev , Olya Gupalo Doug Simon