Diez cosas que puedes hacer con GraalVM


Del traductor: GraalVM es una tecnología nueva e interesante, pero en Habré no hay muchos artículos que puedan mostrar ejemplos de las capacidades de Graal. El siguiente artículo no es solo una lista de lo que GraalVM puede hacer, sino también una pequeña clase magistral similar a la que Chris Seaton y Oleg Shelaev llevaron a cabo en Oracle CodeOne 2018. Siguiendo al autor, le insto a que intente hacer ejemplos del artículo, realmente interesante


Hay muchas cosas diferentes en GraalVM , y si escuchaste este nombre antes, o incluso viste informes, todavía hay muchas cosas que probablemente aún no sabes, pero que GraalVM puede hacer. En este artículo, analizaremos las diversas funciones que ofrece GraalVM y le mostraremos qué puede hacer con ellas.


  1. Ejecución rápida de Java
  2. Disminuya el tiempo de inicio y el uso de memoria para Java
  3. Combinando JavaScript, Java, Ruby y R
  4. Ejecución de programas escritos en lenguajes específicos de plataforma.
  5. Herramientas comunes para todos los lenguajes de programación.
  6. Suplemento de aplicación JVM
  7. Aplicaciones dependientes de la plataforma
  8. Código Java como una biblioteca específica de plataforma
  9. Soporte para múltiples lenguajes de programación en la base de datos.
  10. Crear lenguajes de programación para GraalVM

Puede hacer todo lo que se muestra en este artículo utilizando GraalVM 1.0.0 RC1, que está disponible a través del enlace del sitio web de GraalVM . Utilicé MacOS Enterprise Edition, pero el código aquí funciona en Linux y GraalVM Community Edition.


Cuando leas el artículo, ejecuta los programas que se describen en él. El código se puede descargar desde GitHub .


Instalación


Después de descargar desde http://graalvm.org/downloads, agregué la ruta a los ejecutables de GraalVM en $PATH . Por defecto, esto agrega soporte para la ejecución de Java y 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 viene con soporte de JavaScript incorporado y contiene un administrador de paquetes llamado gu que agrega la capacidad de instalar soporte para lenguajes distintos de Java y JavaScript. También instalé Ruby, Python y R, se descargan de GitHub.


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

Ahora, si ejecuta el comando java o js , verá las versiones GraalVM de estos motores.


 $ 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. Ejecución rápida de Java


"Graal" en GraalVM es el nombre del compilador. ¡Él solo está creado para gobernarlo todo ! Esto significa que esta es una implementación del compilador escrita en forma de una biblioteca que se puede usar para muchas cosas diferentes. Por ejemplo, utilizamos Graal para compilar tanto por adelantado como justo a tiempo para compilar código escrito en diferentes lenguajes de programación, incluso para diferentes arquitecturas de procesador.


La primera y más fácil forma de usar Graal es usarlo como un compilador JIT de Java.


Como ejemplo, utilizaremos un programa que produce 10 de las palabras más comunes en un documento. El programa utiliza las capacidades del lenguaje Java moderno, como Streams y colecciones.


 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 incluye el compilador javac , pero no hay diferencia para esta demostración si usarlo o el compilador estándar. Por lo tanto, puede usar el compilador javac estándar si lo desea.


 $ javac TopTen.java 

Si ejecutamos el comando java , que está incluido en GraalVM, entonces el compilador Grait JIT se usará automáticamente; no se requieren pasos adicionales. Usaré el comando time para obtener datos reales sobre el tiempo que se dedicó a ejecutar el programa de principio a fin, en lugar de implementar un microbench complejo. También se utilizará una gran cantidad de entrada para que no haya insinuaciones sobre el par de segundos guardados aquí o allá. El tamaño del archivo large.txt es de 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 está escrito en Java, no en C ++, como la mayoría de los otros compiladores JIT para Java. Creemos que esto nos permite mejorarlo más rápido que los compiladores existentes, agregando nuevas optimizaciones potentes (como, por ejemplo, análisis de escape parcial) que no están disponibles en el compilador JIT estándar para HotSpot.
Y esto puede hacer que sus programas Java sean mucho más rápidos.


Para fines de comparación, para ejecutar programas sin el compilador Grait JIT, -XX:-UseJVMCICompiler . JVMCI es la interfaz entre Graal y JVM. También puede ejecutar el ejemplo en una JVM estándar y comparar los resultados.


 $ 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 

Esta prueba muestra que Graal ejecuta nuestro programa Java en aproximadamente tres cuartos del tiempo que lleva ejecutarlo con el compilador HotSpot estándar. Donde creemos que mejorar la productividad en unidades de porcentaje es un logro significativo, el 25% es un gran problema.


Twitter es la única compañía hoy en día que usa Graal en servidores de "batalla" , y dicen que está justificado para ellos, en términos de ahorro de dinero real. Twitter usa Graal para ejecutar aplicaciones escritas en Scala: Graal funciona en el nivel JVM de bytecode, es decir. aplicable a cualquier lenguaje JVM.


Este es el primer caso de uso para GraalVM: simplemente reemplaza el compilador JIT con una versión mejor para sus aplicaciones Java existentes.


2. Disminuya el tiempo de inicio y el uso de memoria para Java


Los puntos fuertes de la plataforma Java son especialmente evidentes cuando se trabaja con procesos de larga duración y cargas máximas. Los procesos de corta duración, por el contrario, sufren largos tiempos de inicio y un uso de memoria relativamente alto.


Por ejemplo, si ejecutamos la aplicación de la sección anterior, proporcionándole una cantidad mucho menor de datos de entrada, aproximadamente 1Kb en lugar de 150MB, entonces parece que tomará un tiempo irrazonablemente largo y bastante memoria, aproximadamente 60MB, para procesar un archivo tan pequeño . Utilizamos la opción -l para imprimir la cantidad de memoria utilizada además del tiempo de ejecución.


 $ 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 nos brinda una herramienta que resuelve este problema. Dijimos que Graal es una biblioteca compiladora y se puede usar de muchas maneras diferentes. Uno de ellos está compilando por adelantado en una imagen ejecutable dependiente de la plataforma, en lugar de compilar justo a tiempo en tiempo de ejecución. Esto es similar a cómo funciona un compilador normal, como 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 

Este comando crea un topten plataforma llamado topten . Este archivo no inicia la JVM, no está vinculado a la JVM y no incluye la JVM de ninguna manera. El comando de native-image realmente compila su código Java y las bibliotecas Java que usa en código máquina completo. Para componentes de tiempo de ejecución como el recolector de basura, lanzamos nuestra propia VM nueva llamada SubstrateVM, que, como Graal, también está escrita en Java.


Si observa las dependencias que utiliza topten , verá que estas son solo bibliotecas de sistema estándar. Solo podemos transferir este archivo a un sistema en el que nunca se haya instalado la JVM y ejecutarlo allí para verificar que no utiliza la JVM ni ningún otro archivo. Topten también Topten bastante pequeño: el código ejecutable ocupa menos de 6 MB.


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

Si ejecutamos este ejecutable, veremos que comienza aproximadamente un orden de magnitud más rápido y usa aproximadamente un orden de magnitud menos memoria que el mismo programa que se ejecuta bajo la JVM. El lanzamiento es tan rápido que no notará cuánto tiempo tardó. Si usa la línea de comando, no sentirá la pausa que generalmente está presente cuando ejecuta un programa pequeño y de corta duración bajo 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 

La utilidad de native-image tiene algunas limitaciones . Por lo tanto, en el momento de la compilación debe tener todas las clases presentes, también hay restricciones en el uso de la API de Reflection. Pero hay algunas ventajas adicionales sobre la compilación básica, como la ejecución de inicializadores estáticos en tiempo de compilación. Por lo tanto, se reduce la cantidad de trabajo realizado cada vez que se descarga la aplicación.


Esta es la segunda aplicación de GraalVM: la distribución y ejecución de programas Java existentes, con un inicio rápido y menos consumo de memoria. Este método corrige problemas de configuración, como encontrar el jar correcto en tiempo de ejecución, y también le permite crear imágenes acoplables más pequeñas.


3. Combinando JavaScript, Java, Ruby y R


Junto con Java, GraalVM incluye nuevas implementaciones de motores JavaScript, Ruby, R y Python. Están escritos usando un nuevo marco llamado Truffle . Este marco hace posible crear intérpretes de idiomas que sean simples y de alto rendimiento. Cuando escribe un intérprete de idiomas utilizando Truffle, utilizará automáticamente Graal para proporcionar la compilación JIT para su idioma. Por lo tanto, Graal no solo es un compilador JIT y un compilador AOT para Java, también puede ser un compilador JIT para JavaScript, Ruby, R y Python.


El soporte para idiomas de terceros en GraalVM pretende ser un reemplazo transparente para los motores existentes para la ejecución de varios idiomas. Por ejemplo, podemos instalar el módulo "color" para Node.js:


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

Luego escriba un programa usando este módulo para convertir colores RGB RGB a HSL:


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

Y ejecútelo de la forma habitual:


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

Los motores de ejecución de diferentes idiomas en GraalVM funcionan juntos: hay una API que le permite ejecutar código desde un idioma en un programa escrito en otro idioma. Y esto le permite escribir programas multilingües, programas escritos en más de un lenguaje de programación.


Esto puede ser necesario si escribe la mayor parte de su programa en un idioma, pero le gustaría usar una biblioteca escrita en otro lenguaje de programación. Por ejemplo, supongamos que necesitamos escribir una aplicación para convertir un nombre de color de CSS a su representación numérica en Node.js, pero queremos usar una biblioteca de colores Ruby en lugar de escribir la conversión nosotros mismos.


 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') }); 

En este código, escribimos que necesitamos ejecutar el código Ruby como una cadena, pero tenga en cuenta que no hicimos mucho aquí: solo conectamos las bibliotecas y luego devolvimos el objeto Ruby. En Ruby, lo Color::RGB.by_name (name).html así: Color::RGB.by_name (name).html . Si observa cómo color_rgb usa color_rgb más adelante en JavaScript, verá que en realidad llamamos a los mismos métodos desde JavaScript, aunque estos son objetos y métodos de Ruby. Y los pasamos como cadenas de JavaScript y combinamos el resultado, que es una cadena de Ruby, con una cadena de JavaScript.


Instale ambas dependencias: Ruby y 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 

Luego, debe iniciar el node con un par de opciones adicionales: --polyglot , para decir que necesitamos acceso a otros idiomas y --jvm , porque la imagen ejecutable del node por defecto no incluye nada más que JavaScript.


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

Y luego vaya a la URL http: // localhost: 8080 / css / orange (o algún otro color), como de costumbre, en su navegador.

Intentemos hacer un ejemplo más serio, que usa más idiomas y módulos.


JavaScript no admite enteros muy grandes. Encontré varios módulos como big-integer , pero todos son ineficientes porque almacenar los componentes de un número como números de coma flotante de JavaScript. La clase BigInteger en Java es más eficiente, usémosla para realizar algunas operaciones aritméticas con enteros grandes.


JavaScript tampoco tiene soporte incorporado para dibujar gráficos, mientras que R dibuja gráficos de manera excelente. svg módulo svg de R para dibujar un diagrama de dispersión de una función trigonométrica en el espacio 3D.


En ambos casos, utilizaremos la API para admitir el multilingüismo de GraalVM (en lo sucesivo, la API Polyglot) y simplemente podemos insertar los resultados de la ejecución de programas en otros idiomas 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!') }) 

Abra http: // localhost: 3000 / en su navegador para ver el resultado:

Esto es lo tercero que podemos hacer con GraalVM: ejecutar programas escritos en varios idiomas y usar módulos de estos idiomas en un solo programa. Presentamos esto como una forma de unificar los entornos de ejecución y las bibliotecas: puede usar el lenguaje de programación que considere más adecuado para resolver la tarea actual y cualquier biblioteca que desee, independientemente del lenguaje de programación en el que esté escrito.


4. Ejecución de programas escritos en lenguajes específicos de plataforma.


Otro lenguaje que admite GraalVM es C. GraalVM puede ejecutar código C de la misma manera que ejecuta programas escritos en JavaScript y Ruby.


Lo que GraalVM realmente admite es la ejecución del código resultante de la ejecución de las utilidades LLVM, es decir. código de bits, no soporte directo para C. Esto significa que puede usar las herramientas existentes para el lenguaje C y otras que admitan LLVM, como C ++, Fortran y, potencialmente, más lenguajes en el futuro. Para simplificar la demostración, ejecuto una versión especial de gzip , que se ensambla en un solo archivo ( Stephen McCamant admite esta versión). Esto es solo el código fuente de gzip y la configuración de autoconf combinada en un solo archivo para simplificar. Tuve que parchear un par de cosas para que funcione en macOS y con clang, pero no hice nada específicamente para admitir GraalVM.


Compilamos gzip usando el clang estándar (compilador LLVM para C) y queremos que nos haga un código de bits LLVM, y no una compilación específica de la plataforma, porque GraalVM no lo lanzará. Estoy usando clang 4.0.1.


 $ clang -c -emit-llvm gzip.c 

Y luego ejecute el resultado, directamente usando el comando lli (intérprete de código de bits LLVM) de GraalVM. Intentemos comprimir el archivo usando mi archivador del sistema gzip, y luego descomprímalo usando gzip que se ejecuta bajo 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... 

Las implementaciones de Ruby y Python en GraalVM usan la misma técnica para ejecutar extensiones escritas en C para estos lenguajes. Esto significa que puede ejecutar estas extensiones dentro de la VM y esto nos permite mantener una alta velocidad de ejecución incluso si usamos interfaces de extensión específicas de la plataforma obsoletas.


Esta es la cuarta forma de usar GraalVM: ejecutar programas escritos en lenguajes específicos de plataforma, como C o C ++, así como lanzar extensiones a lenguajes como Python o Ruby, que no pueden realizar implementaciones de JVM de estos lenguajes, como JRuby.


5. Herramientas generales para todos los lenguajes de programación.


Si programa en Java, probablemente esté utilizando herramientas de muy alta calidad como IDEs, depuradores y perfiladores. No todos los idiomas tienen este kit de herramientas, pero puede obtener uno si usa idiomas compatibles con GraalVM.


El soporte para todos los idiomas en GraalVM (excepto Java, en este momento) se implementa utilizando un marco común: Truffle. Esto nos permite crear la funcionalidad, por ejemplo, un depurador, una vez y usarla para todos los idiomas.


Para probar esto, escribiremos el programa más simple: FizzBuzz , porque es visual (imprime algo en la pantalla) y tiene ramas claras que se usan solo en algunas iteraciones. Por lo tanto, será más fácil para nosotros establecer puntos de interrupción. Comencemos con una implementación de 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)); } 

Iniciamos el programa como de costumbre, utilizando la utilidad js , bajo GraalVM.


 $ js fizzbuzz.js 1 2 Fizz 4 Buzz Fizz 

También podemos ejecutar el programa con la bandera --inspect . Esto nos dará un enlace que puede abrir en Chrome y detener el programa en el depurador.


 $ 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 

Puede establecer un punto de interrupción en el código FizzBuzz y luego continuar la ejecución. Cuando el programa interrumpe la ejecución, veremos el valor de la variable n en el depurador y podremos continuar la ejecución del programa o estudiar la interfaz del depurador.

El depurador en Chrome generalmente se usa para JavaScript, pero para GraalVM en JavaScript no hay nada diferente de otros idiomas. El indicador --inspect también --inspect disponible y funciona en las implementaciones de Python, Ruby y R. No mostraré la fuente de cada programa, pero se ejecutan de la misma manera y obtienes el mismo depurador en Chrome para cada uno de ellos.


 $ graalpython --jvm --inspect fizzbuzz.py 


 $ ruby --inspect fizzbuzz.rb 


 $ Rscript --inspect fizzbuzz.r 


Otra herramienta con la que puede estar familiarizado desde Java es VisualVM. Proporciona una interfaz de usuario a través de la cual puede unirse a una JVM en ejecución en su máquina local oa través de una red para inspeccionar varios aspectos de la ejecución del programa, como el uso de memoria o la ejecución de subprocesos.


GraalVM incluye VisualVM como una utilidad estándar de jvisualvm .


 $ jvisualvm &> /dev/null & 

Si ejecutamos VisualVM mientras se TopTen programa Java TopTen , entonces podemos observar el uso de la memoria o, por ejemplo, tomar una instantánea de los contenidos de la memoria y ver qué tipos de objetos usamos en la memoria.


 $ java TopTen large.txt 


Escribí este programa en Ruby para generar basura en la memoria en tiempo de ejecución.


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

Si ejecuta la implementación estándar de Ruby en JVM - JRuby, se sentirá decepcionado con VisualVM porque verá solo objetos Java internos en lugar de objetos en su idioma.


Si usa la versión de Ruby para GraalVM, VisualVM reconoce los objetos de Ruby. Necesitamos usar la opción --jvm para usar VisualVM, como no es compatible con versiones nativas de Ruby.


 $ ruby --jvm render.rb 

Puede, si es necesario, mirar una imagen del montón con objetos Java internos, como vimos anteriormente, o, en la pestaña Resumen, puede seleccionar el Montón Ruby y ver los objetos Ruby reales.

El marco Truffle es algo así como Nexus para idiomas y herramientas . Si crea su propio motor de idiomas con Truffle y crea sus propias herramientas, como un depurador, teniendo en cuenta la API de Truffle para las herramientas, cada herramienta funcionará para cualquier idioma basado en Truffle, y deberá escribir solo una tiempos


, 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 , .


Conclusión


GraalVM — , , . , , , , .


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


, , . , GraalVM @ChrisGSeaton @shelajev .


: Oleg Šelajev , Olya Gupalo Doug Simon

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


All Articles