WebAssembly ist ein binäres Befehlsformat und eine virtuelle Maschine, die Webbrowser-Anwendungen eine nahezu native Leistung verleiht und es Entwicklern ermöglicht, Hochgeschwindigkeits-Webanwendungen in der Sprache ihrer Wahl zu erstellen. [...]
Seit zwei Jahrzehnten gibt es nur eine Programmiersprache, die nativ in einem Webbrowser verwendet werden kann: JavaScript. Das langsame Sterben von binären Plug-ins von Drittanbietern hat andere Sprachen wie Java und Flash ActionScript als erstklassige Bürger für die Webentwicklung verdrängt. Andere Websprachen, wie CoffeeScript, werden lediglich zu JavaScript kompiliert.
Aber jetzt gibt es eine neue Möglichkeit: WebAssembly, oder kurz Wasm. WebAssembly ist ein kleines, schnelles Binärformat, das eine nahezu native Leistung für Webanwendungen verspricht. Außerdem ist WebAssembly so konzipiert, dass es als Kompilierungsziel für jede beliebige Sprache dienen kann – JavaScript ist nur eine davon.
Da nun jeder größere Browser WebAssembly unterstützt, ist es an der Zeit, ernsthaft über das Schreiben von clientseitigen Anwendungen für das Web nachzudenken, die als WebAssembly kompiliert werden können.
Es ist erwähnenswert, dass WebAssembly-Anwendungen nicht dazu gedacht sind, JavaScript-Anwendungen zu ersetzen – zumindest noch nicht. Betrachten Sie WebAssembly vielmehr als Ergänzung zu JavaScript. Während JavaScript flexibel und dynamisch typisiert ist und über von Menschen lesbaren Quellcode bereitgestellt wird, ist WebAssembly schnell, stark typisiert und wird über ein kompaktes Binärformat bereitgestellt.
Entwickler sollten WebAssembly für leistungsintensive Anwendungsfälle wie Spiele, Musikstreaming, Videobearbeitung und CAD-Anwendungen in Betracht ziehen. Viele Webdienste, wie z. B. Google Earth, haben diesen Schritt bereits vollzogen. Figma, eine Anwendung für kollaboratives Zeichnen und Diagramme, wandte sich ebenfalls an WebAssembly [engl.], um die Ladezeiten und die Ausführungsgeschwindigkeit zu verringern, selbst als WebAssembly noch relativ neu war.
So funktioniert WebAssembly
WebAssembly, das vom W3C entwickelt wurde, ist nach den Worten seiner Schöpfer ein „Kompilierungsziel“. Die Entwickler schreiben WebAssembly nicht direkt, sondern in einer Sprache ihrer Wahl, die dann in WebAssembly-Bytecode kompiliert wird. Der Bytecode wird dann auf dem Client – in der Regel in einem Webbrowser – ausgeführt, wo er in nativen Maschinencode übersetzt und mit hoher Geschwindigkeit ausgeführt wird.
WebAssembly-Code soll schneller geladen, geparst und ausgeführt werden als JavaScript. Wenn WebAssembly von einem Webbrowser verwendet wird, muss das Wasm-Modul noch heruntergeladen und eingerichtet werden. Bei größeren Wasm-Projekten können diese Module mehrere Megabyte groß sein, so dass diese Verzögerungen erheblich sein können. Aber alles andere ist gleich, WebAssembly läuft schneller.
WebAssembly bietet außerdem ein Sandbox-Ausführungsmodell, das auf denselben Sicherheitsmodellen basiert, die jetzt auch für JavaScript gelten. Wasm-Anwendungen können auf nichts außerhalb der Sandbox direkt zugreifen, auch nicht auf das DOM der Webseite, auf der sie ausgeführt werden. Alle Interaktionen mit dem Rest des Rechners müssen ABIs wie das WebAssembly System Interface (WASI) verwenden. WASI bietet einen kontrollierten Zugriff auf Dateien, Netzwerke, die Systemuhr und andere Systemdienste, die häufig in Programmen benötigt werden.
Derzeit ist die Ausführung von WebAssembly in Webbrowsern der häufigste Anwendungsfall, aber WebAssembly soll mehr sein als eine webbasierte Lösung. Das Wasmer-Projekt [engl.] führt WebAssembly-Anwendungen serverseitig aus, ganz ähnlich wie die Node.js-Laufzeitumgebung JavaScript außerhalb des Browsers ausführt.
WebAssembly Anwendungsfälle
Der grundlegendste Anwendungsfall für WebAssembly ist das Schreiben von Software innerhalb des Browsers. Die Komponenten, die in WebAssembly kompiliert werden, können in einer beliebigen Sprache geschrieben werden; die endgültige WebAssembly-Nutzlast wird dann über JavaScript an den Client übermittelt.
WebAssembly wurde mit Blick auf eine Reihe von leistungsintensiven, browserbasierten Anwendungsfällen entwickelt: Spiele, Musikstreaming, Videobearbeitung, CAD, Verschlüsselung und Bilderkennung, um nur einige zu nennen.
Generell ist es sinnvoll, sich auf diese drei Bereiche zu konzentrieren, wenn Sie Ihren speziellen WebAssembly-Anwendungsfall bestimmen:
- Leistungsstarker Code, der bereits in einer zielführenden Sprache vorliegt. Wenn Sie z. B. eine Hochgeschwindigkeits-Mathematikfunktion bereits in C geschrieben haben und diese in eine Webanwendung integrieren möchten, können Sie sie als WebAssembly-Modul bereitstellen. Die weniger leistungsrelevanten, benutzerseitigen Teile der Anwendung können in JavaScript bleiben.
- Leistungsstarker Code, der von Grund auf neu geschrieben werden muss, wo JavaScript nicht ideal ist. Früher konnte man asm.js verwenden, um solchen Code zu schreiben. Das ist immer noch möglich, aber WebAssembly wird als bessere langfristige Lösung positioniert.
- Portierung einer Desktop-Anwendung auf eine Web-Umgebung. Viele der Technologie-Demos für asm.js und WebAssembly fallen in diese Kategorie. WebAssembly kann ein Substrat für Anwendungen bieten, die anspruchsvoller sind als nur eine über HTML präsentierte grafische Benutzeroberfläche. Zwei Beispiele hierfür sind die Demos von WebDSP und Windows 2000 im Browser.
Wenn Sie eine bestehende JavaScript-Anwendung haben, die nicht an die Leistungsgrenzen stößt, sollten Sie sie in diesem Stadium der WebAssembly-Entwicklung am besten in Ruhe lassen. Wenn Sie die Anwendung jedoch schneller machen müssen, kann WebAssembly helfen.
WebAssembly-Sprachunterstützung
WebAssembly ist nicht dafür gedacht, direkt geschrieben zu werden. Wie der Name schon andeutet, ist es eher eine Assembler-Sprache, etwas, das von der Maschine verarbeitet werden kann, als eine menschenfreundliche Hochsprachenprogrammierung. WebAssembly ist näher an der Zwischendarstellung (IR), die von der LLVM-Sprachcompiler-Infrastruktur erzeugt wird, als an C oder Java.
Daher umfassen die meisten Szenarien für die Arbeit mit WebAssembly das Schreiben von Code in einer höheren Programmiersprache und dessen Umwandlung in WebAssembly. Dies kann auf eine von drei grundlegenden Arten geschehen:
- Direkte Kompilierung. Der Quelltext wird über die eigene Compiler-Toolchain der Sprache in WebAssembly übersetzt. Rust, C/C++, Kotlin/Native und D verfügen nun alle über native Möglichkeiten, Wasm aus Compilern zu emittieren, die diese Sprachen unterstützen.
- Tools von Drittanbietern. Die Sprache hat keine native Wasm-Unterstützung in ihrer Toolchain, aber ein Dienstprogramm eines Drittanbieters kann zur Konvertierung nach Wasm verwendet werden. Java, Lua und die .Net-Sprachfamilie verfügen alle über eine derartige Unterstützung.
- WebAssembly-basierter Interpreter. Hier wird die Sprache selbst nicht in WebAssembly übersetzt, sondern ein Interpreter für die Sprache, der in WebAssembly geschrieben ist, führt den in der Sprache geschriebenen Code aus. Dies ist der umständlichste Ansatz, da der Interpreter mehrere Megabyte Code umfassen kann, aber er ermöglicht es, dass vorhandener Code, der in der Sprache geschrieben wurde, nahezu unverändert ausgeführt werden kann. Python (z. B. über PyScript) und Ruby verfügen beide über Interpreter, die in Wasm übertragen werden.
WebAssembly-Funktionen
WebAssembly befindet sich noch in der Anfangsphase. Die WebAssembly-Toolchain und -Implementierung sind nach wie vor eher ein Proof-of-Concept als eine Produktionstechnologie. Dennoch haben die Verwalter von WebAssembly das Ziel, WebAssembly durch eine Reihe von Initiativen nützlicher zu machen:
Threading
Native Unterstützung für Threading ist in Sprachen wie Rust und C++ üblich. Das Fehlen von Threading-Unterstützung in WebAssembly bedeutet, dass ganze Klassen von Software, die auf WebAssembly ausgerichtet sind, nicht in diesen Sprachen geschrieben werden können. Der Vorschlag, WebAssembly Threading hinzuzufügen, verwendet das C++-Threading-Modell als eine seiner Inspirationen.
Massenspeicheroperationen und SIMD
Massenspeicheroperationen und SIMD-Parallelität (Single Instruction, Multiple Data) sind ein Muss für Anwendungen, die große Datenmengen verarbeiten und eine native CPU-Beschleunigung benötigen, um nicht zu ersticken, wie z. B. maschinelles Lernen oder wissenschaftliche Anwendungen. Es liegen Vorschläge auf dem Tisch, WebAssembly diese Fähigkeiten über neue Operatoren hinzuzufügen.
High-level Sprachen Konstrukte
Viele andere Funktionen, die für WebAssembly in Betracht gezogen werden, lassen sich direkt auf High-Level-Konstrukte in anderen Sprachen übertragen.
- Ausnahmen können in WebAssembly emuliert werden, aber nicht nativ über den Befehlssatz von WebAssembly implementiert werden. Der vorgeschlagene Plan für Ausnahmen umfasst Ausnahmeprimitive, die mit dem C++-Ausnahmemodell kompatibel sind, das wiederum von anderen Sprachen verwendet werden könnte, die nach WebAssembly kompiliert werden.
- Referenztypen erleichtern die Weitergabe von Objekten, die als Referenzen für die Host-Umgebung verwendet werden. Dadurch wären die Garbage Collection und eine Reihe anderer Funktionen auf hoher Ebene in WebAssembly leichter zu implementieren.
- Tail-Calls, ein in vielen Sprachen verwendetes Entwurfsmuster.
- Funktionen, die mehrere Werte zurückgeben, z. B. über Tupel in Python oder C#.
- Vorzeichenerweiterungsoperatoren, eine nützliche Low-Level-Mathematikoperation. (LLVM unterstützt diese ebenfalls.)
Tools zur Fehlersuche und Profilerstellung
Eines der größten Probleme mit transpiliertem JavaScript war die Schwierigkeit beim Debugging und der Profilerstellung, da es nicht möglich war, den transpilierten Code mit dem Quellcode zu korrelieren. Bei WebAssembly gibt es ein ähnliches Problem, das auf ähnliche Weise angegangen wird (Unterstützung von Source-Maps). Siehe die Projektnotiz zur geplanten Tooling-Unterstützung [engl.].
*Serdar Yegulalp ist Senior-Autor bei InfoWorld und konzentriert sich auf maschinelles Lernen, Containerisierung, Devops, das Python-Ökosystem und regelmäßige Reviews.
Be the first to comment