Webassembly - der JavaScript-Herausforderer

cubido
Montag, 01. Juli 2019

„Webassembly ist ein Bytecode zur Ausführung im Webbrowser“ behauptet Wikipedia nüchtern. Diese Definition ist erst einmal nicht besonders hilfreich. Was genau kann Webassembly und welche Vorteile bringt es? Ein kurzer Überblick in meinem aktuellen Blogbeitrag.

Gemeint ist damit, dass der Quellcode einer höheren Programmiersprache in einen viel einfacheren Code übersetzt werden, dessen einzelne Befehle jeweils mittels weniger Bytes abgebildet werden können. Bekannteste Vertreter sind hier Java oder die Sprachen der .NET Familie (C#, VB.NET etc.).

Bytecode darf jedoch nicht mit Maschinencode verwechselt werden. Während letzterer direkt vom Prozessor ausgeführt werden kann, muss der Bytecode erst noch in einen für den Prozessor verständlichen Code übersetzt werden was normalerweise „just in time“ (JIT) geschieht.

Um Webassembly (kurz WASM) im Browser auszuführen, benötigt man somit Bytecode und daher zwangsläufig entsprechende Tools, welche einen dabei unterstützen, aus Quellcode in z.B. C/C++ selbigen zu generieren. Hierfür exitieren diverse Online-Tools wie z.B WebAssembly studio oder WasmFiddle, welche sich vor allem gut dafür eignen, schnell etwas auszuprobieren ohne eigens Projekte anlegen oder komplexe Toolsets installieren zu  müssen.

Möchte man jedoch ein ernsthaftes Projekt umsetzen, sollte man sich Emscripten einmal genauer ansehen. Hiermit kann man C/C++ Quellcode direkt in Webassembly Module übersetzen. Weiters werden einem auch lästige Routineaufgaben wie das Laden des WASM-Moduls mittels Javascript abgenommen und eine Library für die einfachere Kommunikation mit dem WASM-Modul ist ebenfalls mit an Board. Emscripten hat bereits eine längere Geschichte und wurde ursprünglich dazu verwendet, C/C++ Quellcode in JavaScript zu übersetzen. Diese Funktionalität besteht auch weiterhin und ermöglicht somit auch das Erstellen von Fallback Lösungen für jene Browser, die mit WASM Modulen nichts anzufangen wissen.

Webassembly wird übrigens von nahezu allen gängigen Webbrowsern unterstützt, auch von deren mobilen Ablegern. Leider ist der Internet Explorer hier nicht mit von der Partie. Man sollte jedoch berücksichtigen, dass selbst Microsoft mittlerweile von dessen Nutzung abrät da er technisch veraltet ist und es keinen Support mehr dafür gibt.


Was genau kann Webassembly denn nun?

Die Antwort auf diese Frage ist auf den ersten Blick eher ernüchternd. Webassembly kann vor allem vieles nicht. z.B. kann nicht direkt auf das DOM zugegriffen und somit in keiner Weise etwas im Webbrowser ausgeben werden, nicht einmal eine Ausgabe direkt in die Entwicklerkonsole ist möglich. Wobei man hier berücksichtigen muss, was die Intention hinter Webassembly ist. Man stellt ein in sich abgeschlossenes Modul zur Verfügung welches in einer Sandbox läuft. Die Kommunikation benötigt JavaScript, ebenso der Aufruf von Funktionen des WASM-Moduls. Dieser Mechanismus wird auch als JavaScript Interop bezeichnet. Dabei ist es sowohl möglich, WASM Funktionen mittels JavaScript aufzurufen als auch JavaScript Funktionen aus einem Webassembly Modul heraus aufzurufen. Jene, die sich schon einmal mit JNI (Java Native Interface) beschäftigt haben werden hier eventuell ein kleines Déjà-vu erleben.

Was sind nun die offiziellen Vorteile von Webassembly?

Liest man Artikel über Webassembly so werden zwei Merkmale immer wieder hervorgehoben. Da ist einerseits die hohe Geschwindigkeit und andererseits die native Browserunterstützung welche Webassembly von anderen Technologien unterscheiden sollen. Es ist jedoch angebracht, das einmal kritisch zu hinterfragen.

Bei der Native Browserunterstützung wiederholt sich die Geschichte nämlich und jene die die noch Webbrowser von Mitte der 90er Jahre miterlebt haben können sich vielleicht noch an Java Applets erinnern. Java Applets waren damals eine brandheiße Technologie. Sie waren schnell, man konnte sie in einer höheren Programmiersprache entwickeln, man hatte Grafikausgabe und Java war und ist ein Standard. Der vielleicht größte Vorteil war jedoch, dass Webbrowser wie Netsacpe 3 und 4 sowie der Internet Explorer in der Version 3 eine integriere Java VM hatten welche es ermöglichte, Applets ohne zusätzlich installierte Software auszuführen. Die Native Browserunterstützung ist somit ein alter oder bestenfalls runderneuerter Hut und es bleibt zu hoffen, dass Webassembly nicht früher oder später in eine externe VM oder ein separat deaktivierbares Plugin abgeschoben wird.


Und wie sieht es nun mit der Geschwindigkeit aus?

Über die Geschwindigkeit von Webassembly liest man in diversen Blogbeiträgen abenteuerliche Dinge wie zum Beispiel, dass Webassembly um ein Vielfaches, ja manchmal sogar bis um das zwanzigfache schneller sein soll als JavaScript. Ähnliches wird auch in vielen Tutorial Videos behauptet, ja sogar in kostenpflichtigen Online-Kursen.

Ich möchte dem nicht uneingeschränkt widersprechen aber zumindest darauf hinweisen, dass ich diesen enormen Performancezuwachs in eigenen Tests nicht nachvollziehen konnte.

Mehrere Tests wurden gemacht und dabei die Ausführungszeit durch eine Zeitmessung direkt im Code ermittelt:

  • Primzahlenberechnung:
    Hierfür wurden die ersten tausend Primzahlen ermittelt und dabei ein sehr einfacher Algroithmus ohne besondere Optimierung verwendet. Der C Code ist dabei beinahe unverändert in JavaScript übernommen worden. Je nach Webbrowser war das Unterschied dennoch eher gering und im Durchschnitt kam eine Geschwindigkeitssteigerung um den Faktor 1,8 bei Webassembly zustande.

     const isPrime = num => {
        for(let i = 2; i < num; i++)
          if(num % i === 0) return false;
        return num !== 1 && num !== 0;
      };
      const checkPrimes = num => {
        let count = 0;
        for( let i = 0; i < num; i++ ) {
          if (isPrime(i)) count++;
        }
        return count;
      };

  • Animation mit Kollisionserkennung
    Achthundert kreisförmige Objekte bewegen sich in einem rechteckigen Feld wobei sie sowohl von den Rändern als auch von zahlreichen quadratischen Hindernissen abprallen. Was soll ich sagen? Das Ergebnis war ernüchternd: In sämtlichen getesteten Desktop Browsern (Firefox, Chrome, Edge) war die JavaScript-Variante merkbar performanter als das Webassembly Modul. Hierbei möchte ich noch erwähnen, dass der JavaScript Code objektorientiert ist und diese Variante daher sogar ein Handycap hatte. Prototypes kosten bei der Ausführung noch zusätzliche Performance.

1907_Webassembly_animationkollisionserkennung

Wie man an diesem Screenshot erkennen kann, beansprucht die Grafikausgabe einen deutlich überwiegenden Teil der Ausführungszeit. Das Webassembly Modul kümmert sich hier nur um die Ermittlung der Kollision sowie das Weiterbewegen der Objekte. Gezeichnet wird mittels JavaScript da Grafikausgabe alleine mittels Webassembly nicht möglich ist.


Wozu also das Ganze?

Man stellt sich am Ende zwangsläufig die Frage, warum man den nicht unbeträchtlichen Aufwand in Kauf nehmen sollte den die Verwendung von Webassembly bei der Entwicklung von Browseranwendungen verursacht.

Diese Frage ist relativ einfach zu beantworten: Für neue Projekte ohne bereits bestehende Codebasis lohnt sich der entstehende Zusatzaufwand kaum, es sei denn man kann aufgrund der Anatomie der Anwendung ganz gezielt ein paar Prozent bei der Performance herauskitzeln und diese Verbesserung ist für die Anwendung auch tatsächlich von Bedeutung.

Wo Webassembly hingegen seine eigentliche Stärke ausspielt ist bei der Übersetzung bestehender Software, vor allem solcher die in C/C++ geschrieben wurde. Der aktuell bedeutendste Vertreter dieser Gattung ist das Blazor Projekt von Microsoft. Es ermöglicht das Ausführen von compiliertem C# Code sowie das Anzeigen von MVC-Razor Pages direkt im Browser. Gut, letzteres ist keine Neuigkeit. Aber die Tatsache, dass man clientseitige Events verarbeiten und den dahinterliegenden Code direkt im Browser ausführen kann (so wie man es z.B. von Angular kennt) allerdings schon.

Nicht unerwähnt lassen darf man hier, dass zu diesem Zweck nicht der C# Code zu Webassembly compiliert wird. Viel mehr wurde hier die freie .NET Runtime „Mono“ (welche in C++ geschrieben ist) in ein Webassembly Modul übersetzt.


Fazit und Ausblick

Webassembly ist eine spannende Technologie von der man wohl noch einiges hören wird. Es ist auch zu erwarten, dass sich in Sachen Performance noch eine Menge tun wird, schließlich handelt es sich um eine recht junge Technologie wohingegen JavaScript bereits seit über zwei Jahrzehnten weiterentwickelt und optimiert wird.

Alleine die Tatsache, dass das Blazor Projekt von Microsoft Mitte April 2019 nun offiziell vom experimentellen in den Preview Status übergegangen ist zeigt, dass man auch bei Microsoft auf Webassembly setzt und dieser noch jungen Technologie vertraut.

 

Verfasst von Thomas Polaschek

Weitere Blogbeiträge

zum Thema Development

Updates for innovators: Abonnieren Sie unseren Blog