Polyglot Programming dan GraalVM

Posted in: Software Engineering  
Tags: Terminology   Polyglot   Python   GraalVM   R  
Author: | | 6 minutes reading time

Pernahkah mendengar istilah polyglot programming? Istilah ini sudah menjadi istilah yang umum dan barangkali banyak didengar oleh para developer yang sehari-hari memang berkutat dengan bahasa pemrograman dan peranti pengembangan. Polyglot programming merupakan penggunaan lebih dari satu bahasa pemrograman untuk menyelesaikan suatu masalah pemrograman. Kategori polyglot programming antara lain adalah:

  1. Penggunaan binding yang dibuat menggunakan suatu bahasa pemrograman tertentu (biasanya bahasa pemrograman aras sistem — atau aras rendah seperti C/C++, Assembly, Rust) ke suatu bahasa yang berada pada aras tinggi seperti Ruby, Python, dan lain-lain. Cara ini biasanya ditempuh untuk optimasi atau memang memerlukan function / procedure / library yang tidak ada di bahasa yang bersangkutan. Contoh: wxPython merupakan binding wxwidgets untuk Python untuk keperluan pembuatan aplikasi GUI.
  2. Fasilitas untuk mengeksekusi script / source code pada suatu bahasa tertentu. Contoh dari hal ini adalah Julia yang memungkinkan mengeksekusi source code Python sehingga memungkinkan akses terhadap banyak pustaka Python. Eksekusi ini biasanya dilakukan pada execution context yang berbeda.
  3. Penggunaan virtual machine bytecode yang bisa di-share oleh berbagai bahasa yang mendukung virtual machine tersebut. Contoh dari hal ini adalah JVM (Java Virtual Machine) yang secara default memerlukan bahasa pemrograman Java untuk menghasilkan bytecode .class. File-file bytecode tersebut bisa dibaca dan digunakan oleh bahasa lainnya yang dibuat pada JVM (misalnya Kotlin, Scala, Eta, Frege, dan lain-lain). Contoh lainnya ada pada CLR di dunia .NET yang bisa digunakan oleh berbagai bahasa seperti C#, F#, dan lain-lain. Jadi, dengan cara ini, bytecode merupakan tujuan akhir dan antar bahasa pemrograman bisa terjadi interoperabilitas karena memang berjalan pada VM yang sama dan bisa mengenali bytecode tersebut: source code harus dikompilasi terlebih dahulu untuk menghasilkan bytecode yang bisa memungkinkan interoperabilitas (sebagai contoh, Kotlin bisa mengakses berbagai file .jar di repo Maven yang dihasilkan oleh Java).

GraalVM merupakan hasil riset dari Oracle (berbasis JDK) yang bertujuan untuk memungkinkan menggunakan berbagai bahasa dalam satu execution context di atas VM tanpa melalui proses kompilasi ke bytecode. Jadi, bisa saja menggunakan Python (salah satu bahasa yang didukung oleh GraalVM) dan source code Python kita mengakses pustaka standar di NodeJS. Lebih lanjut, hasil dari source code bisa dikompilasi menjadi native images yang mempunyai waktu eksekusi lebih cepat daripada bytecode VM. Menarik? mari kita coba.

Saat ini GraalVM semakin mature dan saat tulisan ini dibuat, GraalVM memasuki versi 22.3.1. Instalasi GraalVM sangat mudah, hanya perlu mengambil binary di https://github.com/graalvm/graalvm-ce-builds/releases dan kemudian mengekstrak serta menambahkan path bin ke dalam env variable PATH (contoh berikut menggunakan fish):

set -x PATH /opt/software/graalvm/graalvm/bin $PATH

Anda bisa mengambil sesuai versi JDK yang anda pilih (saat ini: 11, 17, dan 19). Setelah itu, beberapa executable file untuk beberapa bahasa pemrograman / tools sudah tersedia. Default bahasa pemrograman yang tersedia adalah Java dan JavaScript. Selain itu, bisa digunakan gu (GraalVM Component Updater) untuk menginstall bahasa pemrograman lain (misalnya Python).

$ gu list
ComponentId              Version             Component name                Stability                     Origin 
---------------------------------------------------------------------------------------------------------------------------------
graalvm                  22.3.1              GraalVM Core                  Supported                     
$ gu available
Downloading: Component catalog from www.graalvm.org
ComponentId              Version             Component name                Stability                     Origin 
---------------------------------------------------------------------------------------------------------------------------------
espresso                 22.3.1              Java on Truffle               Supported                     github.com
espresso-llvm            22.3.1              Java on Truffle LLVM Java librSupported                     github.com
js                       22.3.1              Graal.js                      Supported                     github.com
llvm                     22.3.1              LLVM Runtime Core             Supported                     github.com
llvm-toolchain           22.3.1              LLVM.org toolchain            Supported                     github.com
native-image             22.3.1              Native Image                  Early adopter                 github.com
native-image-llvm-backend22.3.1              Native Image LLVM Backend     Early adopter (experimental)  github.com
nodejs                   22.3.1              Graal.nodejs                  Supported                     github.com
python                   22.3.1              GraalVM Python                Experimental                  github.com
R                        22.3.1              FastR                         Experimental                  github.com
ruby                     22.3.1              TruffleRuby                   Experimental                  github.com
visualvm                 22.3.1              VisualVM                      Experimental                  github.com
wasm                     22.3.1              GraalWasm                     Experimental                  github.com

Berikut adalah versi GraalVM dengan menggunakan JDK 11:

$ java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment GraalVM CE 22.3.1 (build 11.0.18+10-jvmci-22.3-b13)
OpenJDK 64-Bit Server VM GraalVM CE 22.3.1 (build 11.0.18+10-jvmci-22.3-b13, mixed mode, sharing)
$ javac -version
javac 11.0.18
$

Mari install js, python, dan nodejs:

$ gu install js nodejs python
Downloading: Component catalog from www.graalvm.org
Processing Component: Graal.js
Processing Component: Graal.nodejs
Processing Component: GraalVM Python
Processing Component: Graal.js
Processing Component: LLVM.org toolchain
Processing Component: LLVM Runtime Core
Additional Components are required:
    Graal.js (org.graalvm.js, version 22.3.1), required by: Graal.nodejs (org.graalvm.nodejs)
    LLVM.org toolchain (org.graalvm.llvm-toolchain, version 22.3.1), required by: GraalVM Python (org.graalvm.python)
    LLVM Runtime Core (org.graalvm.llvm, version 22.3.1), required by: GraalVM Python (org.graalvm.python)
Downloading: Component js: Graal.js from github.com
Downloading: Component nodejs: Graal.nodejs from github.com
Downloading: Component python: GraalVM Python from github.com
Downloading: Component org.graalvm.llvm-toolchain: LLVM.org toolchain from github.com
Downloading: Component org.graalvm.llvm: LLVM Runtime Core from github.com
Installing new component: LLVM Runtime Core (org.graalvm.llvm, version 22.3.1)
Installing new component: LLVM.org toolchain (org.graalvm.llvm-toolchain, version 22.3.1)
Installing new component: Graal.js (org.graalvm.js, version 22.3.1)
Installing new component: Graal.nodejs (org.graalvm.nodejs, version 22.3.1)
Installing new component: GraalVM Python (org.graalvm.python, version 22.3.1)
$ gu list
ComponentId              Version             Component name                Stability                     Origin 
---------------------------------------------------------------------------------------------------------------------------------
graalvm                  22.3.1              GraalVM Core                  Supported                     
js                       22.3.1              Graal.js                      Supported                     github.com
llvm                     22.3.1              LLVM Runtime Core             Supported                     github.com
llvm-toolchain           22.3.1              LLVM.org toolchain            Supported                     github.com
nodejs                   22.3.1              Graal.nodejs                  Supported                     github.com
python                   22.3.1              GraalVM Python                Experimental                  github.com
$

Hasil instalasi adalah sebagai berikut:

$ js --version
GraalVM JavaScript (GraalVM CE Native 22.3.1)
$ node -v
v16.18.1
$ python --version
GraalVM Python 3.8.5 (GraalVM CE Native 22.3.1)
$

Catatan: python juga bisa dieksekusi menggunakan graalpy

Mari kita coba Python.

$ graalpy 
Python 3.8.5 (Thu Jan 19 19:16:44 UTC 2023)
[Graal, GraalVM CE, Java 11.0.18] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.platform
'linux'
>>> import os
>>> os.name
'posix'
>>> sys.platform
'linux'
>>> sys.copyright
'Copyright (c) Oracle and/or its affiliates. Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.'
>>> import platform
>>> platform.python_version()
'3.8.5'
>>> 

Sekarang mari mencoba Python dan R pada satu source code. Install R dengan perintah gu berikut:

$ gu install R
Downloading: Component catalog from www.graalvm.org
Processing Component: FastR
Downloading: Component R: FastR from github.com
Installing new component: FastR (org.graalvm.R, version 22.3.1)
NOTES:
---------------
FastR should work out of the box on most Linux distributions and recent MacOS versions. Run the following script to check FastR requirements and create a personal R packages library directory: 
    /home/bpdp/software/java-dev-tools/graalvm-ce-java11-22.3.1/languages/R/bin/configure_fastr

The R component comes without native image by default. If you wish to build the native image, which provides faster startup, but slightly slower peak performance, then run the following:
    gu rebuild-images R

The native image is then used by default. Pass '--jvm' flag to the R or Rscript launcher to use JVM instead of the native image. Note that the native image is not stable yet and is intended for evaluation and experiments for curious users. Some features may not work in the native image mode. Most notably, the --polyglot switch works only in JVM mode (when --jvm is used).

See http://www.graalvm.org/docs/reference-manual/languages/r for more.

$

Kita akan mencoba menggabungkan source code Python dengan R. Buat file testgraal.py yang memanfaatkan R sebagai berikut:

import polyglot
array = polyglot.eval(language="R", string="c(1,2,42,4)")
print(array[2])

Setelah itu jalankan:

$ graalpy --polyglot --jvm testgraal.py 
42.0
$

Tentu jika sudah melibatkan banyak libraries, ada kemungkinan proses dan source code akan lebih kompleks. Hal ini tentu tidak mudah, tapi pada fase ini, kita sudah mengetahui bahwa kita bisa menggunakan lebih dari satu bahasa pemrograman pada satu masalah pemrograman.

The next adventure should be exciting. Happy hacking!