Mozilla: Schnellere Webassembly-Aufrufe über Javascript

Laut Mozilla-Entwickler Benjamin Bouvier funktionieren Webassembly-Aufrufe über Javascript-Code mittlerweile deutlich zügiger. Dafür haben Bouvier und seine Kollegen unter anderem die C++-Zwischenschicht entfernt und zugleich den Speicherbedarf optimiert.

Für eine längere Zeit, schreibt Bouvier in seinem Blogpost, waren Webassembly-Aufrufe mit Javascript überhaupt nicht optimiert und brauchten daher recht viel Zeit. Sie nahmen zunächst einen Umweg über C++, um dann einen in Assembler geschriebenen Interpreter Entry Stub aufzurufen. Dieser “Klebecode” kopierte die C++-Argumente an die Stellen, an denen Wasm-Funktionen sie erwarteten, setzte einen Maschinenstatus, rief die Funktion auf, übernahm dann auch die Fehlerbehandlung und kehrte unter Umständen zum C++-Caller zurück.

Laut Blogpost entpuppte sich die Just-in-Time-Kompilierung dabei als zeitkritischer Teil. Der JIT-Compiler Ionmonkey verwandelte den Code erst in Bytecode. Rief eine derart verwandelte Javascript-Funktion dann WASM-Code auf, führte der Weg des Aufrufs zunächst wieder über C++ bevor er schließlich Webassembly erreichte.

C++ fällt weg

Dieser Umweg über C++ fällt seit dem Anfang Mai veröffentlichten Firefox 60 flach. Der JIT-Compiler macht seitdem keinen Unterschied mehr, ob er eine Javascript- oder eine Webassembly-Funktion aufruft. Für beide Funktionen kommen dieselben Aufrufoptimierungen zum Einsatz.

Verantwortlich dafür ist unter anderem ein neuer Klebecode, der JIT Entry Stub. Dieser wird für jede exportierte Funktion erzeugt. Er konvertiert und entpackt die vom JIT-kompilierten JS-Caller gelesenen Argumente in die passenden primitiven WASM-Typen, setzt einige Maschinenregister, ruft die angepeilte WASM-Funktion auf und konvertiert das Ergebnis in ein Format, das auch der Javascript-Aufrufer versteht.

Weil der Umweg über C++ entfällt, gelingen die Aufrufe nun deutlich fixer, wie auch einige Messungen zeigen, die Bouvier in seinem Blog vorstellt. Ist die Zielfunktion ein Unique WASM Target, ließe sich der Code künftig wohl noch weiter optimieren.

Speicher nach Bedarf

Die Schattenseite der Optimierung nennt Bouvier auch: Sie braucht mehr Speicherplatz, weil für jede erzeugte Funktion eine ziemlich große Menge an Code für den JIT-Compiler anfällt. Das wird vor allem dann zum Problem, wenn der Code so genannte Tables exportiert.

Den vergrößerten Speicherbedarf haben die Entwickler über Lazy-Stub-Generation für bestimmte Funktionen verringert. Grob vereinfacht werden die Stubs nur bei Bedarf erzeugt, was insgesamt deutlich weniger Speicher benötigt. Der Blogpost zeigt die Verbesserung in einem Benchmark, erklärt ausführlich die Details und nennt zudem noch einige weitere Neuerungen für Webassembly, an denen der Entwickler beteiligt ist.

E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben