GraalVM의 Polyglot inception왜?왜냐하면 얘가 재밌어요.🏄
GraalVM이라고 들어봤어요?만약 네가 없다면, 너는 마땅히 가서 보아야 한다.이것은 감동적인 기술이다. 너는 알다시피, 이런 기술은 여러 언어의 개발자로 하여금 사용에 몰입하게 할 수 있다😉
웹 사이트에서:
GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Groovy, Kotlin, Clojure, and LLVM-based languages such as C and C++.
GraalVM이 그 중 하나입니다.Oracle에서 개발한 다중 언어 가상 시스템으로, 다중 언어 기능 외에도 상당한 성능과 적은 메모리 사용량을 가진 것으로 증명되었다.이것은 본 컴퓨터의 이미지 구축을 지원하고, 일부 현대 자바 마이크로서비스 프레임워크(예를 들어 Micronaut과 Quarkus)는 GraalVM을 지원한다. 왜냐하면 이것은 더욱 빠른 시작 속도와 더 작은 설치 면적을 제공하기 때문에 마이크로서비스 구조의 이상적인 선택이다.
그러면 GraalVM의 기능은 무엇입니까?빨리 봅시다.
GraalVM 기능
Drop in JDK replacement- 일부 기준 테스트는 GraalVM이 다른 JDK 공급업체보다 빠르고 메모리 소모가 적다는 것을 보여 줍니다. 저는 개인적으로 어떤 기준 테스트도 실행하지 않았습니다.
Drop in NodeJS replacement- NodeJS
Java(모든 JVM 언어), JavaScript, Ruby, Python, R, C/C++/Rust(LLVM) 및 언어 상호 운용성
Polyglot capabilities 타사 언어 지원
Truffle 언어 구현 프레임워크 GraalVM 설치
시작하기 전에 GraalVM을 설정합니다.SDKMAN을 사용했습니다. 수동으로 설치하고 싶으면 에 따라 조작할 수 있습니다.
sdk list java
# you can use a newer version if available
sdk install java 19.3.1.r11-grl
sdk use java 19.3.1.r11-grl
# Check everything
java -version
node -v
lli --version
GraalVM이 설치되고 java
, node
및 lli
컨텍스트로 설정됩니다.참고: 새 터미널 세션을 시작하면 sdk use java 19.3.1.r11-grl
을 다시 실행해야 합니다.gu install llvm-toolchain
export LLVM_TOOLCHAIN=\$(lli --print-toolchain-path)
gu install python
gu install ruby
curl https://sh.rustup.rs -sSf | sh
자, 우리 출발 준비합시다!SDKMAN 설치
재밌게 놀래요.
다국어 개발자로서 GraalVM은 저에게 매우 흥미롭습니다. 왜냐하면 저는 제가 좋아하는 여러 언어를 함께 사용하고 모든 언어 중 가장 좋은 부분을 이용할 수 있기 때문입니다.GraalVM이 제공하는 다중 언어 기능을 살펴보겠습니다. Python, Ruby, R 및 Rust에 대한 지원은 아직 실험 단계이기 때문에 거리가 다를 수 있습니다.오늘은 Java, JavaScript, Ruby, Rust, Python, C++를 사용하여 프로그램을 구축합니다.
I wanted to use Rust and Go as well. While Rust mostly works via the GraalVM lli
command line, it has a lot of limitations when embedded in polyglot mode. After a lot of fiddling around, I did manage to get it working. For Golang, it might be possible with this Go LLVM compiler as shown here, but it's having its own set of issues as well when I tried. So I have given up on Golang for now. Let me know if any of you got it working.
우리는 간단한 (어리석은) 것이 있을 것이다😉) Java로 작성된 응용 프로그램, Java에서 단계별로 다른 언어를 조합하는 방법
I wanted to use Rust and Go as well. While Rust mostly works via the GraalVM lli
command line, it has a lot of limitations when embedded in polyglot mode. After a lot of fiddling around, I did manage to get it working. For Golang, it might be possible with this Go LLVM compiler as shown here, but it's having its own set of issues as well when I tried. So I have given up on Golang for now. Let me know if any of you got it working.
이것 1단계: Java
자바 패키지
Polyglot.java
부터 시작하겠습니다.import java.io.*;
import org.graalvm.polyglot.*;
class Polyglot {
// We create a polyglot context to evaluate source files
static Context polyglotCtx = Context.newBuilder().allowAllAccess(true).build();
// Utility method to load and evaluate a source file
static Value loadSource(String language, String fileName) throws IOException {
File file = new File(fileName);
Source source = Source.newBuilder(language, file).build();
return polyglotCtx.eval(source);
}
// Utility method to convert arrays between languages
static int[] getIntArrayFromValue(Value val) {
int[] out = new int[(int) val.getArraySize()];
if (val.hasArrayElements()) {
for (int i = 0; i < val.getArraySize(); i++) {
out[i] = val.getArrayElement(i).asInt();
}
}
return out;
}
public static void main(String[] args) throws IOException {
int[] input = new int[] { 4, 2, 8, 5, 20, 1, 40, 13, 23 };
/* PYTHON: Get the Fibonacci numbers from the array */
loadSource("python", "pythonpart.py");
Value getFibonacciNumbersFn = polyglotCtx.getBindings("python").getMember("getFibonacciNumbers");
int[] fibNumbers = getIntArrayFromValue(getFibonacciNumbersFn.execute(input));
/* JAVASCRIPT: Find cube of numbers in the output array */
loadSource("js", "jspart.js");
Value findCubeOfNumbersFn = polyglotCtx.getBindings("js").getMember("findCubeOfNumbers");
int[] sqrNumbers = getIntArrayFromValue(findCubeOfNumbersFn.execute(fibNumbers));
/* C++: Get the sum of the numbers in the output array */
loadSource("llvm", "cpppart");
Value getSumOfArrayFn = polyglotCtx.getBindings("llvm").getMember("getSumOfArray");
int sum = getSumOfArrayFn.execute(sqrNumbers, sqrNumbers.length).asInt();
/* Rust: Find the cube root of sum */
Value cubeRootFn = loadSource("llvm", "rustpart.bc").getMember("cube_root");
// println! macro does not work from Rust when embedded, some issue with mangling
System.out.println("Rust => Find cube root of the number");
Double cubeRoot = cubeRootFn.execute(sum).asDouble();
/* RUBY: Find factorial of the number */
Value factorialFn = loadSource("ruby", "rubypart.rb");
long out = factorialFn.execute(cubeRoot).asLong();
System.out.println("Sum: " + sum);
System.out.println("Cube Root: " + cubeRoot);
System.out.println("Factorial: " + out);
}
}
실용 함수는 코드를 간소화하기 위해서입니다. 이제 함수를 구성하는 모든 절차를 살펴보겠습니다.2단계: Python
우리는 파일
getFibonacciNumbers
의 pythonpart.py
함수를 실행하고 입력 그룹에 전달하고 있습니다./* PYTHON: Get the Fibonacci numbers from the array */
loadSource("python", "pythonpart.py");
Value getFibonacciNumbersFn = polyglotCtx.getBindings("python").getMember("getFibonacciNumbers");
int[] fibNumbers = getIntArrayFromValue(getFibonacciNumbersFn.execute(input));
pythonpart.py
을 봅시다. 이것은 표준적인python 프로그램으로 하나의 그룹을 가져와 그 중에서 피보나치 수를 필터한 후에 결과 그룹으로 되돌아옵니다.import math
def isPerfectSquare(num):
n = int(math.sqrt(num))
return (n * n == num)
# Function to check if the number is in Fibonacci or not
def getFibonacciNumbers(array):
print("Python => Filtering Fibonacci number from the array");
out = []
n = len(array)
count = 0
for i in range(n):
if (isPerfectSquare(5 * array[i] * array[i] + 4) or
isPerfectSquare(5 * array[i] * array[i] - 4)):
out.append(array[i]);
count = count + 1
if (count == 0):
print("None present");
return out
3단계: JavaScript
우리는 파일
findCubeOfNumbers
의 jspart.js
함수를 실행하고 Python 함수의 결과를 전달하고 있습니다./* JAVASCRIPT: Find cube of numbers in the output array */
loadSource("js", "jspart.js");
Value findCubeOfNumbersFn = polyglotCtx.getBindings("js").getMember("findCubeOfNumbers");
int[] sqrNumbers = getIntArrayFromValue(findCubeOfNumbersFn.execute(fibNumbers));
jspart.js
을 봅시다. 이것은 표준 자바스크립트 함수입니다. 이것은 하나의 수조를 받아들여 요소를 비추고 수조를 되돌려줍니다.그러나 우리는 Array.prototype.map.call
이 아니라 array.map
을 호출해야 한다. 왜냐하면 자바가 전달하는 수조는 표준적인 JS수조가 아니기 때문이다.function findCubeOfNumbers(array) {
console.log("JS => Getting cube of numbers in the array");
return Array.prototype.map.call(array, (it) => Math.pow(it, 3));
}
4단계: C++
getSumOfArray
바이너리 파일의 cpppart
함수를 실행하고 있습니다.여기서 JS 함수의 결과와 배열의 길이를 전달합니다.우리는 파이썬, 루비, 자바스크립트와 달리 컴파일된 바이너리 파일을 사용해야 한다. 후자는 해석 언어이다./* C++: Get the sum of the numbers in the output array */
loadSource("llvm", "cpppart");
Value getSumOfArrayFn = polyglotCtx.getBindings("llvm").getMember("getSumOfArray");
int sum = getSumOfArrayFn.execute(sqrNumbers, sqrNumbers.length).asInt();
바이너리 파일의 소스 코드는 cpppart.cpp
파일에 있습니다.다음 공식을 사용하여 컴파일하기export LLVM_TOOLCHAIN=$(lli --print-toolchain-path)
$LLVM_TOOLCHAIN/clang++ -shared cpppart.cpp -lpolyglot-mock -o cpppart
함수를 내보내는 데 사용되는 표준 C++ 프로그램인 cpppart.cpp
을 살펴보자.그것은 수조와 그 길이를 매개 변수로 하고 숫자를 되돌려준다#include<iostream>
using namespace std;
// Function to find the sum of integer array
// extern "C" is required to suppress mangling
extern "C" int getSumOfArray(int array[], int size) {
printf("C++ => Find sum of numbers in an array\n");
int i, sum = 0;
for(i = 0; i < size; i++) {
sum += array[i];
}
return sum;
}
단계 5: 녹슨
cube_root
함수를 실행하고 있습니다. 이 함수는 파일 rustpart.bc
에 있으며 rustpart.rs
으로 컴파일되었습니다.여기서 C++ 함수의 결과를 전달합니다./* Rust: Find the cube root of sum */
Value cubeRootFn = loadSource("llvm", "rustpart.bc").getMember("cube_root");
// println! macro does not work from Rust when embedded, some issue with mangling
System.out.println("Rust => Find cube root of the number");
Double cubeRoot = cubeRootFn.execute(sum).asDouble();
rustpart.rs
을 봅시다. 이것은 표준적인 Rust 함수입니다. 숫자를 취하고 입방근을 찾아 되돌려줍니다.그러나 우리는 #[no_mangle]
의 주석을 지정해야 한다. 분명히 우리는 어떤 판자 상자도 사용할 수 없다.원본 매개 변수/출력이 있는 Simples 함수는 작동할 수 있을 것 같지만, 더 복잡한 함수는 삽입할 때 작용하지 않습니다.#[no_mangle]
fn cube_root(arg: f64) -> f64 {
arg.cbrt()
}
fn main(){}
우리는 rustc
로고가 있는 --emit=llvm-bc
컴파일러를 사용하여 Rust 소스 코드를 이진 코드로 컴파일합니다rustc --emit=llvm-bc rustpart.rs
6단계: 루비
우리는 파일
factorial
의 rubypart.rb
함수를 실행하고 있습니다.여기서 Rust 함수의 결과를 전달합니다./* RUBY: Find factorial of the number */
Value factorialFn = loadSource("ruby", "rubypart.rb");
long out = factorialFn.execute(cubeRoot).asLong();
rubypart.rb
을 봅시다. 이것은 표준적인 Ruby lambda 함수입니다. 숫자를 받아들여 곱셈으로 돌아갑니다.factorial = -> (num) {
puts "Ruby => Find factorial of the number"
(1..num).inject {|product, num| product * num }
}
마지막으로 Java로 출력을 인쇄합니다.실행 프로그램
이 프로그램을 실행하기 위해서는 먼저 C++, Rust 및 Java 파일을 컴파일한 다음 GraalVM에서 제공하는 JVM을 사용하여 실행해야 합니다.
run.sh
으로 저장하고 실행할 수 있는 단계는 다음과 같습니다.export LLVM_TOOLCHAIN=$(lli --print-toolchain-path)
$LLVM_TOOLCHAIN/clang++ -shared cpppart.cpp -lpolyglot-mock -o cpppart || exit
rustc --emit=llvm-bc rustpart.rs || exit
javac Polyglot.java && java Polyglot
다음과 같은 출력이 생성됩니다.결론
이거 재밌지 않아요?그럼, 이런 다중 언어 능력이 유용합니까?이것은 상황에 따라 결정됩니다. GraalVM의 다국어 기능은 아직 생산 준비가 되지 않았지만 여전히 유용합니다. 왜냐하면 진정한 언어 상호작용성을 위해 문을 열었기 때문입니다. 프로그램의 모든 언어를 사용할 수 있는 라이브러리를 상상해 보세요. 이것은 많은 C, Ruby, R,GraalVM이 있는 JS와 Java 라이브러리는 지원이 향상됨에 따라 한 언어에 국한된 제한에서 벗어날 수 있습니다.예를 들어 루비와 같은 언어에 대해 GraalVM은 표준 CRuby나 JRuby보다 훨씬 빠른 것 같다. 이것은 프로그램에 여러 언어를 삽입할 때 비용을 너무 걱정할 필요가 없다는 것을 의미하기 때문이다.
GraalVM은 제가 최근에 만났던 가장 혁명적인 기술 중 하나입니다. 저는 Polyglot 언어 지원이 곧 생산에 들어갈 수 있고 원본 이미지 기능까지 합치면 진정한polyglot 응용 프로그램의 강력한 플랫폼이 될 수 있기를 바랍니다.
만약 당신이 이 문장을 좋아한다면, 좋아하거나 평론을 남겨 주세요.
너는 나를 따라갈 수 있다.
표지 이미지 신용: 각 프로젝트의 공식 로고를 바탕으로 한다.
Reference
이 문제에 관하여(GraalVM의 Polyglot inception왜?왜냐하면 얘가 재밌어요.🏄), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/deepu105/polyglot-inception-with-graalvm-why-because-it-s-fun-aa
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(GraalVM의 Polyglot inception왜?왜냐하면 얘가 재밌어요.🏄), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/deepu105/polyglot-inception-with-graalvm-why-because-it-s-fun-aa텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)