Myślisz, że znalezienie trufli jest trudne? Spróbuj zrozumieć Truffle w GraalVM!
W tej lekkostrawnej prezentacji zamierzam uprościć to, co skomplikowane, i wyjaśnić rolę Truffle w ekosystemie GraalVM. Kontynuując kulinarną analogię, wyobraź sobie Truffle jako tajemniczy składnik, który wyciąga prawdziwy aromat GraalVM – wspiera wiele języków i zwiększa wydajność, tak jak prawdziwe trufle dodają daniu smak.
Przebijemy się przez techniczny żargon i wyjaśnimy, co naprawdę oznacza "framework implementacji języka". Dowiesz się, jak działa Truffle, dlaczego jest ważne, a nawet spróbujemy napisać jakiś kawałek prostego języka – zgodnie z zasadą "słowa są tanie, pokaż mi kod"
1 of 164
Download to read offline
More Related Content
Kopiąc Trufle - Odkrywanie tajemnic najmniej zrozumiałego elementu GraalVM
38. Project CRaC
HotSpot Analysis
public static int add(int a, int b) {
return a + b;
}
public static int add(int a, int b) {
return a + b;
}
public static int add(int a, int b) {
return a + b;
}
public static int add(int a, int b) {
return a + b;
}
public static int add(int a, int b) {
return a + b;
}
public static int add(int a, int b) {
return a + b;
}
45. C1 - Client Compiler
Client Compiler, zwany również C1, to rodzaj
kompilatora JIT zoptymalizowanego pod kątem
szybszego czasu startu. Stara się optymalizować
i kompilować kod tak szybko, jak to możliwe.
47. C2 - Client Compiler
Kompilator serwera, zwany również C2, to rodzaj
kompilatora JIT zoptymalizowanego pod kątem
lepszej ogólnej wydajności.
C2 obserwuje i analizuje kod przez dłuższy czas
w porównaniu do C1. Pozwala to C2 na
dokonanie lepszych optymalizacji w
skompilowanym kodzie.
48. C2 - Client Compiler
Kompilator serwera, zwany również C2, to rodzaj
kompilatora JIT zoptymalizowanego pod kątem
lepszej ogólnej wydajności.
C2 obserwuje i analizuje kod przez dłuższy czas
w porównaniu do C1. Pozwala to C2 na
dokonanie lepszych optymalizacji w
skompilowanym kodzie.
53. Optymalizacja dynamiczna
Kompilator JIT może rekompilować części kodu
w trakcie działania programu dzięki pro
fi
lingu.
Pozwala to na optymalizacje oparte na
rzeczywistych danych z czasu wykonania, które
kompilatory statyczne nie są w stanie
uwzględnić.
54. Tiered Compilation
Nasz Kod Interpreter C1 C2
Code
Cache
Deoptimization
Zoptymalizowany
kod
Jeszcze bardziej
zoptymalizowany
kod
Ups…
Level 0
Pro
fi
ling Pro
fi
ling
Level 1
Level 2
Level 3 Level 4
57. public class DeoptimizationExample {
public static void main(String[] args) {
NumberAdder adder = new SimpleAdder();
for (int i = 0; i < 10000; i++) {
if (i == 5000) {
adder = new LoggingAdder();
}
adder.addRandomNumber(10);
}
}
}
interface NumberAdder {
void addRandomNumber(int base);
}
class SimpleAdder implements NumberAdder {
public void addRandomNumber(int base) {
double result = Math.random() + base;
}
}
class LoggingAdder implements NumberAdder {
public void addRandomNumber(int base) {
double result = Math.random() + base;
System.out.println("Computed value: " + result);
}
}
58. public class DeoptimizationExample {
public static void main(String[] args) {
NumberAdder adder = new SimpleAdder();
for (int i = 0; i < 10000; i++) {
if (i == 5000) {
adder = new LoggingAdder();
}
adder.addRandomNumber(10);
}
}
}
interface NumberAdder {
void addRandomNumber(int base);
}
class SimpleAdder implements NumberAdder {
public void addRandomNumber(int base) {
double result = Math.random() + base;
}
}
class LoggingAdder implements NumberAdder {
public void addRandomNumber(int base) {
double result = Math.random() + base;
System.out.println("Computed value: " + result);
}
}
59. public class DeoptimizationExample {
public static void main(String[] args) {
NumberAdder adder = new SimpleAdder();
for (int i = 0; i < 10000; i++) {
if (i == 5000) {
adder = new LoggingAdder();
}
adder.addRandomNumber(10);
}
}
}
interface NumberAdder {
void addRandomNumber(int base);
}
class SimpleAdder implements NumberAdder {
public void addRandomNumber(int base) {
double result = Math.random() + base;
}
}
class LoggingAdder implements NumberAdder {
public void addRandomNumber(int base) {
double result = Math.random() + base;
System.out.println("Computed value: " + result);
}
}
60. Tiered Compilation
Nasz Kod Interpreter C1 C2
Code
Cache
Deoptimization
Zoptymalizowany
kod
Jeszcze bardziej
zoptymalizowany
kod
Ups…
Level 0
Pro
fi
ling Pro
fi
ling
Level 1
Level 2
Level 3 Level 4
64. GraalVM
GraalVM is a high-performance JDK
distribution that compiles your Java
applications ahead of time into standalone
binaries. These binaries start instantly, provide
peak performance with no warmup, and use
fewer resources.
85. Project CRaC
Substrate VM
Compiled Code 🚀
GraalVM in Ahead-of-Time (AoT) Compilation Mode
Graal Compiler
public static int add(int a, int b) {
return a + b;
}
112. Dynamic Typing
Monomor
fi
zm, w kontekście optymalizacji
silników dynamicznych, odnosi się do sytuacji, w
której funkcja jest konsekwentnie wywoływana z
argumentami tego samego typu.
113. Dynamic Typing
Polimor
fi
zmem: Funkcja jest wywoływana z
argumentami różnych typów. Wymaga to od
silnika obsługi wielu przypadków i może
prowadzić do mniej efektywnego kodu.
Megamor
fi
zmem: Funkcja jest wywoływana z
wieloma różnymi typami argumentów, co czyni
niemal niemożliwą optymalizację przez silnik.
123. import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeInfo;
@TypeSystemReference(MyTypeSystem.class) // Define the types recognized in your language
@NodeInfo(shortName = "add")
public abstract class AddNode extends Node {
abstract Object execute(Object a, Object b);
@Specialization
protected int addIntegers(int a, int b) {
return a + b;
}
@Specialization
protected double addDoubles(double a, double b) {
return a + b;
}
// Can add more specializations (e.g., for adding strings, booleans, etc.)
}