Die Grenzen von WebAssembly und die Bedeutung von Tree-Shaking
-
Trotz viel Aufmerksamkeit und hoher Erwartungen war WebAssembly im Web nur begrenzt erfolgreich
- Es gibt Erfolgsbeispiele wie Photoshop, insgesamt ist die Zahl der Projekte mit WebAssembly jedoch nicht groß
- Besonders für Apps, die stark auf das DOM setzen, ist WebAssembly nicht gut geeignet
- Einer der Hauptgründe ist der Unterschied zwischen den Programmiermodellen von JavaScript und WebAssembly
-
WebAssembly war außerhalb von Sprachen wie C oder Rust bislang kaum erfolgreich
- Sprachen wie C# haben den Nachteil, dass eine Runtime samt Garbage Collector mitgeliefert werden muss
- Allerdings werden bald neue WebAssembly-Features eingeführt, die Referenztypen und Garbage Collection unterstützen, wodurch sich die Lage voraussichtlich verbessern wird
Die Fähigkeit des Compilers zur Code-Optimierung ist der Schlüssel zum Erfolg von WebAssembly
-
Damit WebAssembly im Web erfolgreich sein kann, muss der Compiler kleinen und effizienten Code erzeugen können
- Es ist wichtig, eine kleine Dateigröße im Bereich weniger Kilobyte zu halten
- Andernfalls bleibt nur, sich auf Hype oder auf eine bestimmte Nutzerbasis zu stützen
-
In der JavaScript-Welt wird die Codegröße bereits mit Bundlern und ähnlichen Tools optimiert
- Tree-Shaking ist eine Technik, bei der nur die im Programm tatsächlich verwendeten Funktionen und Datentypen einbezogen werden
-
Tree-Shaking ist zwar aus gartenbaulicher wie auch algorithmischer Sicht eine unpassende Metapher, dennoch ist der Begriff weit verbreitet
Der Stand von Tree-Shaking in anderen Sprachen
-
In Sprachen mit schwergewichtiger Runtime wie Go oder Python ist Tree-Shaking bisher noch nicht gut optimiert
- Selbst das einfachste Go-Programm wird beim Kompilieren zu WebAssembly größer als 2 MB
- Auch bei Python mit Pyodide müssen Dateien von etwa 20 MB heruntergeladen werden
-
In Server-Umgebungen ist eine große Binärgröße kein großes Problem
- Für eingeschränkte Umgebungen wie Mobile werden daher gesondert schlanke Toolchains wie MicroPython oder TinyGo entwickelt
-
Sprachimplementierungen für das Web können gar nicht anders, als sich von bestehenden Implementierungen zu unterscheiden
- Schon die Interaktion mit dem DOM ist eine besondere Umgebung
- Im Fall von ClojureScript werden die Unterschiede zu Clojure in einer eigenen Dokumentation festgehalten
Diskussion über Tree-Shaking-Algorithmen
-
Der vom Autor entwickelte Hoot-Scheme-Compiler erzeugt derzeit Wasm-Code mit einer Größe von etwa 70 KB
- Nur Funktionsdefinitionen (Prozeduren) einzubeziehen, ist vergleichsweise einfach
- Allerdings gibt es einige schwierige Punkte wie die folgenden
-
Im Auswertungsmodell von
letrec*sind Bindungen rekursiv und zugleich geordnet, was die Analyse für den Compiler erschwert- Bei Record-Typen sorgen vtable-Callbacks dafür, dass viel Code erhalten bleibt
-
Wenn man stark polymorphe Funktionen wie
displayverwendet, wird viel zusammenhängender Code mit einbezogen- Es ist besser, konkrete Funktionen wie
write-stringzu verwenden
- Es ist besser, konkrete Funktionen wie
-
Für optimales Tree-Shaking ist Flow Analysis erforderlich
- Wenn bekannt ist, dass an
displaykein Bitvektor-Argument übergeben wird, kann zugehöriger Code entfernt werden
- Wenn bekannt ist, dass an
-
In Python ist es wegen dynamischem Dispatch und dynamischen Features wie
__getattr__noch schwieriger- Auch die Modulstruktur von Python ist ein Faktor, der Tree-Shaking komplizierter macht
Zusammenfassung
- Durch die Unterstützung von GC wird DOM-Programmierung in WebAssembly auch mit anderen Sprachen als JavaScript möglich
- Um die Größe der erzeugten Artefakte ausreichend klein zu halten, sind jedoch erhebliche Investitionen in die Toolchains der jeweiligen Sprachen nötig
- Erforderlich sind die Entwicklung separater Toolchains mit Tree-Shaking-Algorithmen sowie die Optimierung der Standardbibliothek
Meinung von GN⁺
-
Mit der GC-Unterstützung in WebAssembly wird es zwar möglich, im Web verschiedene Sprachen einzusetzen, doch es scheint viele Schwierigkeiten zu geben, bestehende Toolchains unverändert zu übernehmen. Es sieht so aus, als müssten sprachspezifische Implementierungen und Optimierungstechniken entwickelt werden, die auf die Web-Umgebung zugeschnitten sind.
-
Damit Tree-Shaking in dynamisch typisierten Sprachen gut funktioniert, scheint statische Analyse unverzichtbar zu sein. Bei Sprachen wie Python dürfte das wegen der vielen dynamischen Features jedoch nicht einfach sein. Eine Möglichkeit wäre vielleicht sogar, von Anfang an eine neue Sprache zu entwerfen, die für statische Analyse besser geeignet ist.
-
Experimentelle Projekte wie Hoot oder TinyGo könnten gute Referenzen sein. Für den Einsatz in realen Produkten dürfte es aber noch zu früh sein. Vermutlich bleibt nichts anderes übrig, als schrittweise Verbesserungen vorzunehmen.
-
Für Projekte, bei denen Leistung nicht hochsensibel ist und schnelle Entwicklung wichtiger ist, könnte sich etwas wie Pyodide anbieten. Bei Produkten, die großen Wert auf User Experience legen, scheint JavaScript derzeit aber die beste Wahl zu sein.
-
Man könnte auch darüber nachdenken, WebAssembly selbst mit Funktionen wie Tree-Shaking auszustatten. Das wäre jedoch wohl nicht einfach, da die Anforderungen je nach Sprache unterschiedlich sind. Und wenn eine Sprache erscheint, die Tree-Shaking besonders gut unterstützt, könnte es sogar vorteilhafter sein, direkt in dieser Sprache zu programmieren. Es bleibt spannend, wie sich die Rollenverteilung zwischen WebAssembly und Programmiersprachen entwickeln wird.
1 Kommentare
Hacker-News-Kommentare
Zusammengefasst ergibt sich Folgendes:
floatVecstattHashMaptalc)randundfxhashwerden verwendet)mainaus traversiert, und nur erreichbarer Code wird in die finale Binärdatei aufgenommen.