Ten things you can do with GraalVM

Ten things you can do with GraalVM  
From the translator: GraalVM is a new, interesting technology, but on Habré there are not many articles on it that could show examples of the possibilities of Graal. The article below is not just a listing of what GraalVM can do, but also a small workshop similar to the one that Chris Seaton and Oleg Shelayev conducted on Oracle CodeOne 2018. Following the author, I urge you - try to make examples from the article, this is really interesting.
 
In GraalVM there are many different things, and if you heard this name before, or even saw reports, there are still many things that you probably don’t know yet, but which GraalVM can do. In this article we will look at the various possibilities that GraalVM provides and show what can be done with their help.
 
 
Fast execution of Java 3r3493.  
Reduced start time and memory consumption for Java
 
Combining jаvascript, java, ruby ​​and r 3r349.  
Execution of programs written in platform-dependent languages ​​3r3493.  
Common tools for all programming languages ​​3r3499.  
JVM application supplement 3r3499.  
Addition of platform-dependent applications
 
Java code as a platform-dependent library
 
Support for multiple programming languages ​​in the database 3r3493.  
Create programming languages ​​for GraalVM
 
GitHub .
 
Installation
 
After downloading from http://graalvm.org/downloads I added the path to the GraalVM executables in r3r31307. $ PATH . By default, this adds support for running Java and jаvascript.
 
3r31312. $ git clone https://github.com/chrisseaton/graalvm-ten-things.git
$ cd foo
$ tar -zxf graalvm-ee-???-rc1-macos-amd64.tar.gz
# or graalvm-ee-???-rc1-linux-amd64.tar.gz on Linux
$ export PATH = graalvm-???-rc1 /Contents /Home /bin: $ PATH
# or PATH = graalvm-???-rc1 /bin: $ PATH on Linux

 
GraalVM comes with built-in jаvascript support and contains a package manager called gu 3r31321. , adding the ability to install support for languages ​​other than Java and jаvascript. I additionally installed Ruby, Python and R, they are downloaded from GitHub.
 
3r31312. $ gu install -c org.graalvm.ruby
$ gu install -c org.graalvm.python
$ gu install -c org.graalvm.R

 

Now, if you run the command java or js , then you will see the GraalVM versions of these engines.


 
3r31312. $ java -version
java version "???_161" 3r3-31407. Java (TM) SE Runtime Environment (build ???_161-b12)
GraalVM ???-rc1 (build ???-b01-internal-jvmci-0.4? mixed mode)
$ js --version
Graal jаvascript 1.0 (GraalVM ???-rc1)

 
3r3124. 1. Fast execution of Java 3r31368.
 

“Graal” in GraalVM is the name of the compiler. He alone is created to rule all ! This means that this is a single compiler implementation written in the form of a library that can be used for a large number of different things. For example, we use Graal for compilation as ahead-of-time and just-in-time to compile code written in different programming languages, including for different processor architectures.


 

The first and easiest way to use Graal is to use it as a Java JIT compiler.


 

As an example, we will use a program that gives out the 10 most frequently encountered words in a document. The program uses the capabilities of the modern Java language, such as Streams and collections.


 
3r31312. 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) {3r-31407. Arrays.stream (args) 3r3-31407. .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 () 3r3-31407. .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 fileLines (String path) {
try {
return Files.lines (Paths.get (path));
} catch (IOException e) {3r3-331407. throw new RuntimeException (e);
}
}
}

 

GraalVM includes the compiler javac , but for this demo there is no difference, use it or the standard compiler. Therefore you can use the standard compiler. javac , if you want to.


 
3r31312. $ javac TopTen.java
 

If we run the command java , which is included in GraalVM, the Graal JIT compiler will be used automatically - no need to do any additional actions. I will use the command time in order to obtain real data on the time that was spent on executing the program from the beginning to the end, instead of deploying a complex microbenchmark. There will also be used a large amount of input data so that there are no insinuations about the saved couple of seconds here or there. The file size is 3r330317. large.txt

- 150 MB.
 
3r31312. $ make large.txt
$ time java TopTen large.txt
sed = 502701
ut = 392657
in = 377651
et = 352641 3r3-331407. id = 317627
eu = 317627
eget = 302621
vel = 300120
a = 287615
sit = 282613
real 0m???s
user 0m???s
sys 0m???s

 

Graal is written in Java, not C ++, like most other JIT compilers for Java. We think that this allows us to improve it faster than existing compilers, complementing new powerful optimizations (such as, for example, partial escape analysis) that are not available in the standard JIT compiler for HotSpot.
 
And it can make your java programs much faster.


 

For comparison purposes, in order to run programs without the Graal JIT compiler, I will use the flag. -XX: -UseJVMCICompiler . JVMCI is the interface between Graal and JVM. You can also run an example on a standard JVM and compare the results.


 
3r31312. $ time java -XX: -UseJVMCICompiler TopTen large.txt
sed = 502701
ut = 392657
in = 377651
et = 352641 3r3-331407. id = 317627
eu = 317627
eget = 302621
vel = 300120
a = 287615
sit = 282613
real 0m???s
user 0m???s
sys 0m???s

 

This test shows that Graal runs our Java program in about three-quarters of the time it takes to run it with the standard HotSpot compiler. Where we believe that a few percent improvement in productivity is a significant achievement, 25% is a big deal.


 

Twitter is the only company today that is uses Graal on “combat” servers 3r3r131397. and they say that this is justified for them, in terms of saving real money. Twitter uses Graal to execute applications written in Scala - Graal runs at the JVM bytecode level, i.e. applicable to any JVM language.


 

This is the first use of GraalVM — simply replacing the JIT compiler with a better version for your existing Java applications.


 

2. Reducing start time and memory consumption for Java 3r313368.
 

The strengths of the Java platform are particularly evident when dealing with long-running processes and peak loads. In contrast, short-lived processes suffer from a long start-up time and relatively large memory usage.


 

For example, if we run the application from the previous section, submitting to it a much smaller amount of input data — about 1 KB instead of 150 MB — then it seems to take an unreasonably long time and quite a lot of memory — about 60 MB, in order to process such a small file . Use parameter -l 3r332311. to print out the amount of memory used in addition to the execution time.


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

 

GraalVM gives us a tool that solves this problem. We said that Graal is a compiler library and it can be used in many different ways. One of them is a compilation ahead-of-time in a platform-dependent executable image, instead of compiling just-in-time at runtime. This is similar to how a regular compiler works, for example gcc .


 
3r31312. $ native-image --no-server TopTen
classlist: ???? ms
(cap): ???? ms
setup: ???? ms
(typeflow): ???? ms
(objects): ???? ms 3r3-31407. (features): ??? ms
analysis: ???? ms
universe: ??? ms
(parse): ??? ms
(inline): ??? ms
(compile): 1???? ms
compile: 1???? ms
image: ???? ms
write: ???? ms
[total]: 3???? ms

 

This command creates a platform-dependent executable file called 3r3-31307. topten . This file does not launch the JVM, it is not linked to the JVM and it generally does not include the JVM in any way. Team native-image truly compiles your Java code and the Java libraries you use into fully-fledged machine code. For runtime components, such as the garbage collector, we run our own new VM, called SubstrateVM, which, like Graal, is also written in Java.


 

If you look at the dependencies that uses. topten , you will see that these are only standard system libraries. We can only transfer this one file to a system on which the JVM has never been installed and run it there to check that it does not use the JVM or any other files. Topten also small enough - the executable code takes up less than 6 MB.


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

 

If we run this executable file, we will see that it runs about an order of magnitude faster and uses about an order of magnitude less memory than the same program running under the JVM. The launch is so fast that you won't notice how long it took. If you use the command line, you will not feel the pause that is usually present when you run a small, short-lived program under the JVM


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

 

In the utility native-image There are some restrictions . So, at compile time you should have all the classes, there are also limitations in using the Reflection API. But there are some additional advantages over basic compilation, such as running static initializers at compile time. In this way, the amount of work performed each time an application is loaded is reduced.


 

This is the second application of GraalVM - distribution and execution of existing Java programs, with a quick start and less memory consumption. This method eliminates configuration problems such as finding the right jar at runtime, and also allows you to create smaller Docker images.


 
3r3013. 3. The combination of jаvascript, Java, Ruby and R 3r31368.
 

Along with Java, GraalVM includes new implementations of jаvascript, Ruby, R, and Python engines. They are written using the new framework, which is called Truffle 3r313391. . This framework makes it possible to create interpreters of languages ​​that are both simple and high-performing. When you write an interpreter of a language using Truffle, it will automatically use Graal to provide JIT compilation for your language. Thus, Graal is not only a JIT compiler and an AOT compiler for Java, it can also be a JIT compiler for jаvascript, Ruby, R and Python.


 

Support for third-party languages ​​in GraalVM aims to be a transparent replacement for existing engines of different languages. For example, we can install the “color” module for Node.js:


 
3r31312. $ npm install - global color
+ [email protected]???
added 6 packages in ???s

 

Then write a program using this module to convert RGB HTML colors to HSL:


 
3r31312. 3r3675. var Color = require ('color');
process.argv.slice (2) .forEach (function (val) {3r3-331407. print (Color (val) .hsl (). string ()); 3r3-331407.});
 

And run it in the usual way:


 
3r31312. $ node color.js '# 42aaf4'
hsl (???? 89%, 60.8%) 3r3?331.
 

The performance engines of different languages ​​in GraalVM work together - there is an API that allows you to run code from one language in a program written in another language. And it allows you to write multilingual programs - programs written in more than one programming language.


 

This may be necessary if you write most of your program in one language, but would like to use a library written in another programming language. For example, imagine that we need to write an application to convert the color name from CSS into its numeric representation in Node.js, but we want to use the Ruby color library instead of writing the conversion ourselves.


 
3r31312. 3r3675. var express = require ('express');
var app = express ();
color_rgb = Polyglot.eval ('ruby', `
require 'color'
Color :: RGB
`);
app.get ('/css /: name', function (req, res) {3r3-31407. color = color_rgb.by_name (req.params.name) .html ()
res.send ('

' + color + '

'); 3r331407.});
app.listen (808? function () {3r34031407. console.log ('serving at http: //localhost: 8080')
});

 

In this code, we wrote that we needed to execute Ruby code as a string, but note that we didn’t do much here - we just connected the libraries and then returned the Ruby object. In Ruby, we would use it like this: Color :: RGB.by_name (name) .html . If you look at how color_rgb used further in jаvascript, you will see that we actually call the same methods from jаvascript, although these are Ruby objects and methods. And we pass them as jаvascript strings and connect the result, which is a Ruby string, with a jаvascript string.


 

Install both dependencies - Ruby and jаvascript.


 
3r31312. $ gem install color
Fetching: color-1.8.gem (100%)
Successfully installed color-???r3r31407. 1 gem installed
$ npm install express
+ [email protected]??? 3-3331407. updated 1 package in ???s

 

Then you need to run node with a couple of additional options: --polyglot , to say that we need access to other languages ​​and --jvm because the executable image is node the default does not include anything except jаvascript.


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

 

And then go to URL 3r32424. http: //localhost: 8080 /css /orange (or some other color), as usual, in your browser.
 
3r33528.
 
Let's try to make a more serious example that uses more languages ​​and modules.


 

jаvascript does not support very large integers. I found several modules like 3r33535. big-integer , but they are all ineffective, because store the components of the number as jаvascript floating point numbers. Class BigInteger Java is more efficient; let's use it to do several arithmetic operations with large integers.


 

There is also no built-in support for drawing graphs in jаvascript, while R perfectly draws graphics. Let's use the module. svg from R to draw a scatter plot of the trigonometric function in 3D space.


 

In both cases, we will use the API to support multilingualism from GraalVM (hereinafter referred to as Polyglot API) and we can simply insert the results of executing programs in other languages ​​into jаvascript.


 
3r31312. 3r3675. const express = require ('express')
const app = express ()
const BigInteger = Java.type ('java.math.BigInteger')
app.get ('/', function (req, res) {3r3-331407. var text = 'Hello World from Graal.js! 3r31387.' 3r3-31407. 3r3-331407. //Using Java standard library classes
text + = BigInteger.valueOf (10) .pow (100) 3r3-31407. .Add (BigInteger.valueOf (43)). ToString () + '
'
3r3-331407. //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 ")) 3r331407. GrDevices ::: svg.off ()
`);
res.send (text)
})
app.listen (300? function () {3r3-31407. console.log ('Example app listening on port 3000!')
}) 3r3-331321.
 

Open http: //localhost: 3000 / in your browser to see the result:
 
3r3-3593.
 
This is the third thing we can do with GraalVM — run programs written in several languages ​​and use the modules from these languages ​​together in one program. We present this as a way to unify runtimes and libraries — you can use the programming language that you think is best suited for solving the current problem and any library you want, regardless of what programming language it is written in.


 
3r3599. 4. Execution of programs written in platform-dependent languages ​​3r3131368.
 

Another language that GraalVM supports is C. GraalVM can execute C code in the same way that it executes programs written in jаvascript and Ruby.


 

What GraalVM actually supports is the launch of code resulting from the execution of the LLVM utilities, i.e. bitcode, not direct C support. This means that you can use existing tools for the C language and others that support LLVM, such as C ++, Fortran, and potentially more languages ​​in the future. For ease of demonstration, I run a special version of 3r3608. gzip which is compiled into a single file (this version supports 3r3-3610. Stephen McCamant ). This is just source code gzip and configuration 3r3-31307. autoconf combined into one file for simplicity. I had to patch a couple of things to make it work on macOS and with clang, but I didn't do anything specifically to support GraalVM.


 

We compile gzip using the standard clang (LLVM compiler for C) and we want it to make us a LLVM bitcode, and not a platform-dependent build, because GraalVM will not launch it. I am using r3r31307. clang ???.


 
3r31312. $ clang -c -emit-llvm gzip.c
 

And then run the result, directly using the lli command (interpreter of the LLVM bitcode) from GraalVM. Let's try to compress the file using my gzip system archiver, and then unzip it using gzip running under GraalVM.


 
3r31312. $ 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

 

Implementations of Ruby and Python in GraalVM use the same technique to run extensions written in C for these languages. This means that you can run these extensions inside a VM and this allows us to maintain high execution speed, even if we use outdated platform-specific extension interfaces.


 

This is the fourth way to use GraalVM — launch programs written in platform-dependent languages, such as C or C ++, as well as launching extensions to languages ​​such as Python or Ruby that the JVM implementations of these languages, such as JRuby, are not able to do.


 
3r3656. 5. Common tools for all programming languages ​​3r31368.
 

If you are programming in Java, then you probably use very high-quality tools such as IDE, debuggers, and profilers. Not all languages ​​have such a set of tools, but you can get such a set if you use languages ​​that are supported by GraalVM.


 

Support for all languages ​​in GraalVM (except Java, currently) is implemented using a common framework - Truffle. This allows us to make functionality, for example, a debugger, once and use it for all languages.


 

To try this, we will write the simplest program - 3r3131390. FizzBuzz , because it is visual (prints something on the screen) and there are clear branches in it that are used only in some iterations. Thus, it will be easier for us to set breakpoints. Let's start with jаvascript implementation.


 
3r31312. 3r3675. function fizzbuzz (n) {3r3-331407. if ((n% 3 == 0) && (n% 5 == 0)) {3r31407. return 'FizzBuzz';
} else if (n% 3 == 0) {3r3-331407. return 'Fizz';
} else if (n% 5 == 0) {3r3-331407. return 'Buzz';
} else {
return n;
}
}
for (var n = 1; n 3r3-33688. print (fizzbuzz (n));
} 3r3-331321. 3r3-331322.
 

We start the program as usual, using the utility js under GraalVM.


 
3r31312. $ js fizzbuzz.js
1
2
Fizz
4
Buzz
Fizz 3r332311.
 

We can also run a program with the flag - inspect . This will give us a link that you can open in Chrome and stop the program in the debugger.


 
3r31312. $ 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 = ???.1: 9229 /6c478d4e-1350b196b409

 

You can put a breakpoint in code FizzBuzz and then continue execution. When the program aborts, we will see the value of the variable 3r3-331307. n

in the debugger and we can continue the program execution or study the debugger interface.
 
3r3734.
 
Chrome debugger is usually used for jаvascript, but for GraalVM in jаvascript there is nothing different from other languages. Flag - inspect it is also available and works in the implementation of Python, Ruby and R. I will not show you the source code of each program, but they run the same way and you get the same debugger in Chrome for each of them.
 
3r31312. $ graalpython --jvm --inspect fizzbuzz.py
 

3r33737.


 
3r31312. $ ruby ​​- inspect fizzbuzz.rb
 

3r33737.


 
3r31312. $ Rscript - inspect fizzbuzz.r
 

 
Another tool that you probably know from Java is VisualVM. It provides a user interface, using which you can join a running JVM on your local machine or via the network to inspect various aspects of program execution, such as memory usage or execution threads.


 

GraalVM includes VisualVM as a standard 3r3-331307 utility. jvisualvm .


 
3r31312. $ jvisualvm &> /dev /null &
 

If we run VisualVM while the Java program is running TopTen , then we will be able to observe the memory usage or, for example, take a snapshot of the memory contents and see what types of objects we use memory in the heap.


 
3r31312. $ java TopTen large.txt
 

3r3802.
 
I wrote this program in Ruby to generate some garbage in memory at runtime.


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

 

If you run the standard Ruby implementation on the JVM - JRuby, then you will be disappointed with VisualVM, because you will see only internal Java objects instead of objects in your language.


 

If you are using the Ruby version for GraalVM, then VisualVM recognizes Ruby objects. We need to use parameter --jvm to use VisualVM because it does not support native versions of Ruby.


 
3r31312. $ ruby ​​- jvm render.rb
 

You can, if necessary, look at the snapshot of the heap with internal Java objects, as we saw earlier, or, on the Summary tab, you can select the Ruby Heap and look at the real Ruby objects instead.
 
3r33844.
 
The Truffle framework is something like Nexus 3r31397. for 3r33849. languages ​​and tools 3r3131397. . If you create your own language engine using Truffle and you make your own tools such as the debugger, taking into account the Truffle API for the toolkit, then each such tool will work for any language based on Truffle, and you will need to write it only time.


 

So, the fifth application of GraalVM is a platform for creating high-quality tools for programming languages ​​that do not always have good tools. With Truffle and GraalVM, you can use other development tools, such as the debugger in Chrome or VisualVM.


 
3r33858. 6. Supplement JVM applications 3r3r1368.
 

In addition to independent execution, as well as joint, in multilingual programs, support for other languages ​​can be added to a Java application. New API in the package. org.graalvm.polyglot Allows you to load and run code written in other languages ​​and use values ​​from them.


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

 

If the commands used are 3r3-31307. javac and java from the GraalVM distribution, then imports. org.graalvm. * will already be in your classpath i.e. it will be possible to compile and run the code without any additional flags.


 
3r31312. $ javac ExtendJava.java
$ java ExtendJava '14 + 2 '
16 3r31407. $ java ExtendJava -js 'Math.sqrt (14)'
???r3-331407. $ 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]

 

The engines used for executing commands in different languages ​​are the same high-performance multilanguage versions that are launched using the commands node or ruby performed by GraalVM.


 

This is the sixth way to use GraalVM - as a single interface for embedding code in other programming languages ​​into your Java application. The Polyglot API allows you to take the objects of the “guest” language and use them as Java interfaces, and also provides more complex ways to interact.


 
3r33939. 7. Addition of platform-dependent applications
 

GraalVM already includes one library, compiled in the manner indicated in the header - a library that allows you to run code in any language supported by GraalVM from platform-specific applications. For example, a jаvascript engine like V? a Python-CPython interpreter is often embedded in other programs, i.e. They can be linked to another application as a library. GraalVM allows you to use any language in the embedded context in the same way — by linking to your Polyglot library.


 

When you install GraalVM, this library is compiled and present there, but by default it only includes native support for jаvascript. You can rebuild the Polyglot library to enable other languages ​​using the command:


 
3r31312. $ graalvm-???-rc1 /Contents /Home /jre /lib /svm /bin /rebuild-images libpolyglot
 

Create a simple C program that executes commands written in any language supported by GraalVM, which are transmitted on the command line. We are going to make the equivalent of our program ExtendJava from the previous section, but using C as the main language.


 
3r3953. 3r3954. The code in C is 3r33955. 3r3r6956. 3r31312. 3r31176. #include
#include
#include
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 errorn");
return 1;
}
poly_context context = NULL;
if (poly_create_context (thread, NULL, ? & context)! = poly_ok) {
fprintf (stderr, "initialization errorn");
return 1;
}
char * language = "js";
for (int n = 1; n < argc; n++) {
if (argv[n] [0]== '-') {3r31407. language = & argv[n] [total]w. if (poly_context_eval (thread, context, language, "unicalc", argv[n], & result)! = poly_ok) {3r3-331407. fprintf (stderr, "eval errorn"); 3rr31407. return 1; buffer[1024]; 3r3-31407. size_t length;
if (poly_value_to_string_utf8 (thread, result, buffer, sizeof (buffer), & length)! = poly_ok) {
fprintf (strr, which can be used for a programmer, for a file, for a file, for a file, for example, for a file, for a file, for a file, for a file, for a text file, for text files return 1; 3r3-31407.} 3r3-331407. 3r3-331407. buffer[length]= 'other managed programming languages. If you want to use the Java library from a platform-specific application, then you can embed the JVM into this application, but this will pretty quickly make it large and complex.
 

GraalVM allows you to take a Java library, ready-made or self-written, and compile it into a separate platform-specific library, then re-use it in other programs for this platform. As in the case of compilation, which was discussed earlier, Java libraries compiled in this way do not require a JVM.


 

I wrote an application that uses the excellent Apache SIS library for working with geo-data to calculate the shortest distance (3r31063. Orthodromy 3r31397.) Between two points on Earth. I used SIS 0.? which I downloaded separately from http://sis.apache.org/ and pulled out of it jar.


 
3r31312. import org.apache.sis.distance.DistanceUtils;
public class Distance {
public static void main (String[]args) {3r-31407. 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);
}
}

 

We compile it in the usual way and use it to get the distance between London and New York


 
3r31312. $ javac -cp sis.jar -parameters Distance.java
$ java -cp sis.jar: Distance ???-???.7127 -???-3331407. ??? km

 

We can compile this into an executable file, as we did for program 3r3-31307. topten .


 
3r31312. $ native-image --no-server -cp sis.jar :. Distance
$ ./distance ???-???.7127 -???-3331407. ??? km

 

And we can build it as a library, not an executable file. To do this, we declare one or more methods as 3r3-331307. @CEntryPoint


 
3r31312.
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);
}
}

 

We do not need to change the command javac because GraalVM automatically puts the required API into 3r331307. classpath . Compile the code in the shared library and the automatically generated header file.


 
3r31312. $ 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

 

Now we will write a small C program that will use this library. To use the interface of our library, you need to do a small ceremony: since the VM needs to manage the heap, the threads, the garbage collector, and other services, you need to create an instance of the system and tell our main thread about this.


 
3r31312. 3r31176. #include
#include
#include
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 errorn");
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 kmn", distance (thread, a_lat, a_long, b_lat, b_long));
return 0;
}
 

We compile it using standard system tools, and we can run our executable file (you need to install 3r3-331307. LD_LIBRARY_PARTH =. 3r3-331321. On Linux) 3r3131398.
 
3r31312. $ clang -I. -L. -ldistance distance.c -o distance
$ otool -L distance
distance:
/libdistance.dylib
/libSystem.B.dylib
$ ./distance ???-???.7127 -???-3331407. ??? km

 

This is the eighth way GraalVM is used to compile java code into a platform-specific library, which can then be used in applications without using JVM


 
3r31228. 9. Support for multiple programming languages ​​in the database 3r31368.
 

One of the applications for the Polyglot library is the use of an Oracle database. We used the library to create the Oracle Database Multilingual Engine (MLE), which includes support for the execution of languages ​​on GraalVM and SQL modules.


 

For example, you have a front-end already written in jаvascript and we validate email addresses using the jаvascript module. validator . If we have some logic for the same application in the database, then it is probably written in SQL or PL /SQL. And we would like to use exactly the same validator to ensure the consistency of the results.


 

Download the MLE as a Docker image from here:


 

3r31247. https://oracle.github.io/oracle-db-mle/releases/???/docker/


 

Then we upload the image to Docker Daemon.


 
3r31312. $ docker load --input mle-docker-???.tar.gz
 

Start the image using Docker, and then when the download is finished (it may take a few minutes), start the Bash terminal inside the image.


 
3r31312. $ docker run mle-docker-???
$ docker ps
$ docker exec -ti bash -li

 

If we can run sqlplus (interactive SQL tool), in the Bash terminal to join the database, this means that the database is up and running.


 
3r31312. $ sqlplus scott /tiger @ localhost: 1521 /ORCLCDB
 

If all goes well, exit sqlplus . Now, in the Bash terminal in Docker, we will install the validator module and then run the command dbjs to load this module into the database. Then run sqlplus again.


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

 

After installation, we can use the functions from the module. validator as part of the SQL statement.


 
3r31312. SQL> select validator.isEmail ('[email protected] ') from dual;
VALIDATOR.ISEMAIL ('[email protected]')
-------------------------------------------
1
SQL> select validator.isEmail ('hello.world') from dual;
VALIDATOR.ISEMAIL ('HELLO.WORLD')
--------------------------------
0

 
And this is the ninth thing you can do with GraalVM — run the languages ​​supported by GraalVM within the Oracle database. Thus, you can use logic from the front-end or back-end, but inside the database, instead of always pulling data for processing from the database to the application server.
 
10. Creating programming languages ​​for GraalVM
 
Oracle Labs and our colleagues from the academic environment were able to create new high-performance implementations of jаvascript, R, Ruby, Python, and C with a relatively small team, because we developed the Truffle framework, which makes it easier to create languages ​​for GraalVM.
 
Truffle is a java library that helps to write the
interpreter. abstract syntax tree
(AST). The AST interpreter is probably the easiest way to implement a language, because it works directly with the output of the parser and does not include bytecode interpretation or compilation, but this approach is often rather slow. We combined this with a technique called partial computing, which allows Truffle to use Graal to automatically compile the JIT language, based solely on the output of your AST interpreter.
 
You can use Truffle to create your own programming language for GraalVM, or a high-performance version of an existing programming language, or DSL. We talk a lot about the details of Truffle and Graal in our project, but we often forget to mention that Truffle is a really simple way to implement a programming language for GraalVM. And after creation you will have such things as, for example, a debugger, automatically. Anyone who has just completed an elementary course in programming languages ​​will have the necessary skill set for this job. Oracle labs made the basic version of Ruby faster than all previous projects, with just one trainee in just a few months.
 
We do not have much space here to fully show the creation of a language, even the most microscopic, but SimpleLanguage - This is a truffle tutorial on creating your own language, based on a simple jаvascript language. In order to understand how this works, you can, for example, see the implementation of the if statement .
 
Other languages ​​written using Truffle by people outside of Oracle Labs include version 3r31356. SmallTalk
, 3r31358. Newspeak
and Lisp . In the example for Lisp there is tutorial which can also be studied and performed from it.
 
Conclusion 3r31368.
 
GraalVM includes a large variety of new functionality - it is a platform on the basis of which you can build programming languages ​​and tools, and use them in more environments. This allows you to choose the language and modules you need, regardless of the environment in which the program is running or the language you are currently using.
 
To try GraalVM, go to http://www.graalvm.org/3r31397. . There are links to downloads and documentation, and more examples similar to those shown in this article.
 
Try to make those examples that we talked about here and try to play with them with them and see what else you can do. Let us know how the GraalVM experiments were performed in your application and send us feedback on 3r31382. @ChrisGSeaton or @shelajev .
 
Thanks: 3r31391. Oleg Šelajev , Olya Gupalo and
Doug Simon 3r31397.
3r31399. 3r31400.
+ 0 -

Add comment