Bytecode im Browser: Mit WebAssembly und Rust zur Web-Anwendung
Am Beispiel eines Chatsystems demonstrieren die Autoren die Programmierung eines browserbasierten Chatclients und -servers mit Rust und Wasm.
- Dr. Jens Breitbart
- Dr. Stefan Lankes
WebAssembly (Wasm) ist ein offener Standard für Bytecode, der das Ausführen von Programmen im Webbrowser ermöglicht. Die gängigen Browser wie Firefox, Chrome, Safari und Edge unterstützen Wasm bereits. Das WebAssembly-Projekt geht aus Mozillas asm.js und dem Portable Native Client (PNaCl) hervor. Beide Projekte schufen die Voraussetzungen, um vorkompilierten C/C++-Code durch den Browser für das Host-System zu kompilieren und anschließend nativ im Browser auszuführen. Im Vergleich zu JavaScript lässt sich dadurch eine höhere Performance erzielen, während gleichzeitig wichtige Security-Funktionen des Browsers wie das Sandboxing aktiv bleiben – und Nutzer von potenziell höherer Sicherheit profitieren.
Die Idee, vorkompilierten Bytecode auszuliefern, ist nicht neu. Sie kam schon in den Neunzehnneunziger Jahren mit Java zum Einsatz. Vorkompilierter Java-Code stand Nutzern damals als Java-Bytecode zur VerfĂĽgung. Beim Programmstart musste dieser interpretiert oder durch einen Just-in-Time-(JIT)-Compiler ĂĽbersetzt werden und lieĂź sich anschlieĂźend ausfĂĽhren.
Java- und WebAssembly-Bytecode unterscheiden sich allerdings deutlich. Java-Bytecode bietet eine höhere Abstraktionsebene und enthält unter anderen Typinformationen – verlangt aber Garbage Collection, da Objekte nicht explizit freigegeben werden. WebAssembly hingegen lässt sich eher mit klassischem Assembler vergleichen und enthält keine Informationen über Objekte. Es verwundert daher kaum, dass eine typische Java-VM deutlich komplexer ausfällt als das entsprechende WebAssembly-Gegenstück.
WebAssembly lässt sich aufgrund seiner Ähnlichkeit mit Assembler recht einfach als weiteres Backend in einen Compiler integrieren. Beispielsweise kann die Compiler-Infrastruktur LLVM WebAssembly erzeugen. Daher lässt sich mit clang
aus C/C++ oder mit rustc
aus Rust WebAssembly generieren. Auch mit dem Compiler Emscripten lässt sich C-Code über das LLVM-Backend im Browser zur Ausführung bringen.
Alle weiteren Beispiele im Rahmen dieses Artikels verwenden Rust. Die Programmiersprache geht ursprünglich auf Mozilla zurück, daher sind unter anderen Teile des Firefox-Browsers in Rust geschrieben. Da Mozilla auch nach dem Wechsel von Teilen des Wasm-Teams zu Fastly zu den engagierten Förderern von WebAssembly gehört, fällt die WebAssembly-Unterstützung von Rust umfangreich aus.
Beispiel 1: Was ist Bytecode?
Bytecode bezeichnet eine Menge an Instruktionen für eine virtuelle Maschine. Sie sind im Allgemeinen unabhängig von konkreter Hardware und dem verwendeten Betriebssystem. Bytecode lässt sich durch das Kompilieren des Quellcodes erzeugen. Prominentes Beispiel ist Java-Bytecode, der sich mit einer Java Virtual Machine (JVM) auf verschiedenen Betriebssystemen und unterschiedlicher Hardware ausführen lässt. Dabei unterscheiden sich je nach Plattform zwar die JVMs, der Code hingegen ist immer gleich. Als Vorteil gegenüber der Interpretation des Quellcodes zur Laufzeit verspricht Bytecode eine schnellere Ausführung.