Veröffentlicht: 29. Januar 2025
WebAssembly Garbage Collection (WasmGC)
Es gibt zwei Arten von Programmiersprachen: Programmiersprachen mit Garbage Collection und Programmiersprachen, die eine manuelle Speicherverwaltung erfordern. Beispiele für Ersteres sind unter anderem Kotlin, PHP oder Java. Beispiele für Letzteres sind C, C++ oder Rust. In der Regel haben Programmiersprachen der höheren Ebenen die automatische Speicherbereinigung als Standardfunktion.
Vereinfacht ausgedrückt ist die Garbage Collection der Versuch, Arbeitsspeicher zurückzugewinnen, der vom Programm zugewiesen wurde, aber nicht mehr referenziert wird. Dieser Speicher wird als „Garbage“ bezeichnet. Es gibt viele Strategien zur Implementierung der Garbage Collection. Eine der am einfachsten zu verstehenden Methoden ist das Referenzzählen, bei dem die Anzahl der Verweise auf Objekte im Arbeitsspeicher gezählt wird.
Es mag sich anfühlen, als wäre es der Anfang, aber Programmiersprachen werden in anderen Programmiersprachen implementiert. Die PHP-Laufzeit wird beispielsweise hauptsächlich in C implementiert. Wenn Entwickler eine Sprache wie PHP in Wasm kompilieren möchten, müssen sie in der Regel alle Teile kompilieren, z. B. den Parser der Sprache, die Bibliotheksunterstützung, die Garbage Collection und andere wichtige Komponenten.
Wasm wird im Browser im Kontext der Hostsprache JavaScript ausgeführt. In Chrome werden JavaScript und Wasm in V8 ausgeführt, der Open-Source-JavaScript-Engine von Google. Außerdem hat V8 bereits einen Garbage Collector. Das bedeutet, dass Entwickler, die beispielsweise PHP verwenden, das in Wasm kompiliert wurde, eine Garbage-Collection-Implementierung der portierten Sprache (PHP) an den Browser senden, der bereits einen Garbage Collector hat. Das ist so verschwenderisch, wie es klingt. Hier kommt WasmGC ins Spiel.
Weitere Informationen zu WasmGC finden Sie im Artikel WebAssembly Garbage Collection (WasmGC) jetzt standardmäßig in Chrome aktiviert. Wenn Sie sich eingehender mit dem Thema befassen möchten, lesen Sie den V8-Blogpost A new way to bring garbage collected programming languages efficiently to WebAssembly (Eine neue Möglichkeit, Garbage-Collected-Programmiersprachen effizient in WebAssembly zu implementieren).
Wasm-Optimierungen für Tail-Calls
Ein Aufruf befindet sich in Tail-Position, wenn es sich um die letzte Anweisung handelt, die ausgeführt wird, bevor von der aktuellen Funktion zurückgekehrt wird. Compiler können solche Aufrufe optimieren, indem sie den Frame des Aufrufers verwerfen und den Aufruf durch einen Sprung ersetzen. Das ist besonders bei rekursiven Funktionen nützlich. Hier ist beispielsweise eine C-Funktion, die die Elemente einer Liste summiert:
int sum(List* list, int acc) {
if (list == nullptr) return acc;
return sum(list->next, acc + list->val);
}
Bei einem regulären Aufruf wird dadurch O(n) Speicherplatz belegt: Jedes Element der Liste fügt dem Aufrufstapel einen neuen Frame hinzu. Bei einer ausreichend langen Liste kann der Stack sehr schnell überlaufen. Durch Ersetzen des Aufrufs durch einen Sprung wandelt die Optimierung von Tail Calls diese rekursive Funktion effektiv in eine Schleife um, die O(1) Stapelspeicherplatz belegt:
int sum(List* list, int acc) {
while (list != nullptr) {
acc = acc + list->val;
list = list->next;
}
return acc;
}
Diese Optimierung ist besonders wichtig für funktionale Sprachen. Sie basieren stark auf rekursiven Funktionen und reine Sprachen wie Haskell bieten nicht einmal Schleifensteuerungsstrukturen. Bei jeder Art von benutzerdefinierter Iteration wird in der Regel Rekursion verwendet. Ohne Optimierung von Tail Calls würde es bei jedem nicht trivialen Programm sehr schnell zu einem Stack-Overflow kommen, da der Stack-Speicherplatz sonst schnell aufgebraucht wäre.
Ursprünglich erlaubte WebAssembly keine solchen Optimierungen von Rücksprunganrufen. Das hat sich mit dem Vorschlag zur Erweiterung von Rücksprunganrufen geändert. Weitere Informationen finden Sie im V8-Blog im Artikel WebAssembly-Tail-Calls.
Ergebnisse
Da WasmGC und Tail Call-Optimierungen jetzt standardmäßig verfügbar sind, können mehr Apps diese Funktionen für eine bessere Leistung nutzen. So wurde beispielsweise in Google Tabellen der Berechnungsworker auf WasmGC umgestellt.