Compiler
Es übersetzt den gesamten Quellcode in einer Programmiersprache in Maschinencode (z. B. eine .exe-Datei), bevor das Programm ausgeführt wird.
Das bedeutet, dass das Programm nach der Kompilierung eigenständig läuft, ohne dass der Quellcode mehr benötigt wird.
| Compiler | Interpreter | |
|---|---|---|
| Wann | vorab alles in Maschinencode | zur Laufzeit, Stück für Stück |
| Tempo | ✅ sehr schnell ausführbar | ❌ langsamer |
| Portabilität | ❌ pro Plattform eigene Datei | ✅ läuft überall mit passendem Interpreter |
| Typisch | C, C++, C# | Python, PHP, JavaScript |
Quellcode → Compiler → Java-Bytecode (Befehlssatz der JVM) → Interpreter übersetzt zur Laufzeit. So bekommt man Portabilität und Teile des Effizienzgewinns.
Compiler-Phasen (vereinfacht)
Ein Compiler führt mehrere Transformations-Phasen durch:
test.c ──Präprozessor──► test.i ──Compiler──► test.s ──Assembler──► test.o ──Linker──► test
(C-Code) (Assembler) (Objektcode) (ausführbar)
(Header, Makros (bereinigte (maschinennahe (nicht verlinkt) (gelinkt)
weg, Includes Version) Mnemoniken)
aufgelöst)
- Präprozessor:
#include,#defineersetzen, Kommentare entfernen → reiner C-Code. - Compiler (Lexing/Parsing/Codegen): Überprüfung, Optimierung, Assembler-Code.
- Assembler: Maschinencode für Befehle, aber Adressen noch relativ.
- Linker:
test.o+ Bibliotheken zusammenschweißen → absolute Adressen.
Compiler-Optimierungen
Nach Parsing, aber vor Codegen, können viele Optimierungen passieren:
| Optimierung | Effekt |
|---|---|
| Constant Folding | int x = 5 + 3; → int x = 8; |
| Dead Code Elimination | Unreachable Statements entfernen |
| Loop Unrolling | Schleife 4× hintereinander, statt in Schleife |
| Inlining | Kleine Funktionen in Aufrufer einbauen |
| Common Subexpression Elimination | x = a+b; y = a+b; → x = y = a+b; |
→ Das ist der Grund, warum -O2 oder -O3 Flags Compiler viel langsamer machen, aber schnelleren Code erzeugen.
JIT vs. AOT (Just-In-Time vs. Ahead-Of-Time)
| AOT (Ahead-Of-Time) | JIT (Just-In-Time) | |
|---|---|---|
| Wenn | vor dem Start alles compilieren | während Laufzeit compilieren |
| Speed | startup-schnell, Laufzeit nur Maschinencode | langsamer Start (Kompilation), dann optimiert |
| Optimierungen | statisch (ohne Runtime-Infos) | dynamisch (kennt echte Laufzeit-Muster) |
| Beispiele | C/C++, Go, Rust | Java (hotspot JIT), JavaScript (V8) |
| Hybrid | — | Tiered JIT: Schnell als Bytecode starten, währenddessen häufige Code-Pfade optimieren |
→ Modernes Java mit JIT kann sogar schneller sein als C, weil der JIT Runtime-Muster sieht (z.B. welche Verzweigung am häufigsten), die ein statischer C-Compiler nicht kennt.