Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

In diesem Artikel wird ein Beispiel für die Beschleunigung einer Browseranwendung durch Ersetzen von JavaScript-Berechnungen durch WebAssembly erläutert.

WebAssembly – was ist das?

Kurz gesagt handelt es sich hierbei um ein binäres Befehlsformat für eine stapelbasierte virtuelle Maschine. Wasm (Kurzname) wird oft als Programmiersprache bezeichnet, ist es aber nicht. Das Anweisungsformat wird zusammen mit JavaScript im Browser ausgeführt.

Es ist wichtig, dass WebAssembly durch Kompilieren von Quellen in Sprachen wie C/C++, Rust, Go erhalten werden kann. Dabei kommen statistische Typisierung und das sogenannte Flat-Memory-Modell zum Einsatz. Der Code wird, wie oben erwähnt, in einem kompakten Binärformat gespeichert, wodurch er fast so schnell ist wie die Ausführung der Anwendung über die Befehlszeile. Diese Funktionen haben zur wachsenden Popularität von WebAssembly geführt.

Erinnerung: für alle Leser von „Habr“ – ein Rabatt von 10 Rubel bei der Anmeldung zu einem beliebigen Skillbox-Kurs mit dem Aktionscode „Habr“.

Skillbox empfiehlt: Praktischer Kurs „Mobile Developer PRO“.

Derzeit wird Wasm in vielen Anwendungen verwendet, von Spielen wie Doom 3 bis hin zu webportierten Anwendungen wie Autocad und Figma. Wasm wird auch in Bereichen wie Serverless Computing eingesetzt.

Dieser Artikel enthält ein Beispiel für die Verwendung von Wasm zur Beschleunigung eines Analyse-Webdienstes. Aus Gründen der Übersichtlichkeit haben wir eine in C geschriebene Arbeitsanwendung verwendet, die in WebAssembly kompiliert wird. Das Ergebnis wird verwendet, um leistungsschwache Abschnitte von JS zu ersetzen.

Anwendungstransformation

Im Beispiel wird der Browserdienst fastq.bio verwendet, der für Genetiker gedacht ist. Mit dem Tool können Sie die Qualität der DNA-Sequenzierung (Entschlüsselung) bewerten.

Hier ist ein Beispiel der Anwendung in Aktion:

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Es lohnt sich nicht, auf die Details des Prozesses näher einzugehen, da sie für Laien recht komplex sind. Kurz gesagt können Wissenschaftler anhand der obigen Infografik nachvollziehen, ob der DNA-Sequenzierungsprozess reibungslos verlief und welche Probleme aufgetreten sind.

Dieser Dienst bietet Alternativen, Desktop-Programme. Mit fastq.bio können Sie Ihre Arbeit jedoch beschleunigen, indem Sie die Daten visualisieren. In den meisten anderen Fällen müssen Sie in der Lage sein, mit der Befehlszeile zu arbeiten, aber nicht alle Genetiker verfügen über die erforderliche Erfahrung.

Alles funktioniert einfach. Bei der Eingabe handelt es sich um Daten, die in Form einer Textdatei dargestellt werden. Diese Datei wird von speziellen Sequenzierungstools generiert. Die Datei enthält eine Liste der DNA-Sequenzen und einen Qualitätsfaktor für jedes Nukleotid. Das Dateiformat ist .fastq, weshalb der Dienst auch seinen Namen hat.

Implementierung in JavaScript

Der erste Schritt des Benutzers bei der Arbeit mit fastq.bio besteht darin, die entsprechende Datei auszuwählen. Mithilfe des File-Objekts liest die Anwendung eine zufällige Stichprobe von Daten aus einer Datei und verarbeitet diesen Stapel. Die Aufgabe von JavaScript besteht hier darin, einfache String-Operationen auszuführen und Metriken zu berechnen. Eine davon ist die Anzahl der Nukleotide A, C, G und T auf verschiedenen DNA-Fragmenten.

Nach der Berechnung der erforderlichen Indikatoren werden diese mit Plotly.js visualisiert und der Dienst beginnt mit der Arbeit mit einem neuen Datenbeispiel. Das Chunking dient dazu, die Qualität der UX zu verbessern. Wenn Sie mit allen Daten auf einmal arbeiten, friert der Prozess für einige Zeit ein, da die Dateien mit den Sequenzierungsergebnissen Hunderte Gigabyte Dateispeicher beanspruchen. Der Dienst nimmt Datenstücke mit einer Größe von 0,5 bis 1 MB auf und verarbeitet sie Schritt für Schritt, um grafische Daten zu erstellen.

So funktioniert es:

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Das rote Rechteck enthält den String-Transformationsalgorithmus zur Visualisierung. Dies ist der rechenintensivste Teil des Dienstes. Es lohnt sich, es durch Wasm zu ersetzen.

WebAssembly testen

Um die Möglichkeit der Verwendung von Wasm zu bewerten, begann das Projektteam mit der Suche nach vorgefertigten Lösungen für die Erstellung von QC-Metriken (QC – Qualitätskontrolle) basierend auf Fastq-Dateien. Die Suche erfolgte unter in C, C++ oder Rust geschriebenen Tools, sodass eine Portierung des Codes nach WebAssembly möglich war. Darüber hinaus sollte das Tool nicht „roh“ sein, sondern ein bereits von Wissenschaftlern getesteter Dienst erforderlich sein.

Infolgedessen wurde die Wahl zugunsten getroffen seqtk. Die Anwendung ist sehr beliebt, sie ist Open Source, die Quellsprache ist C.

Vor der Umstellung auf Wasm lohnt sich ein Blick auf das Kompilierungsprinzip von seqtk für den Desktop. Laut Makefile benötigen Sie Folgendes:

# Compile to binary
$ gcc seqtk.c 
   -o seqtk 
   -O2 
   -lm 
   -lz

Im Prinzip können Sie seqtk mit Emscripten kompilieren. Wenn es nicht da ist, behelfen wir uns. Docker-Image.

$ docker pull robertaboukhalil/emsdk:1.38.26
$ docker run -dt --name wasm-seqtk robertaboukhalil/emsdk:1.38.26

Falls gewünscht, Sie können es selbst zusammenbauen, aber es braucht Zeit.

Innerhalb eines Containers können Sie emcc problemlos als Alternative zu gcc verwenden:

# Compile to WebAssembly
$ emcc seqtk.c 
    -o seqtk.js 
    -O2 
    -lm 
    -s USE_ZLIB=1 
    -s FORCE_FILESYSTEM=1

Mindeständerungen:

Anstatt in eine Binärdatei auszugeben, verwendet Emscripten .wasm und .js, um die Dateien zu generieren, die zum Ausführen des WebAssemby-Moduls verwendet werden.

Das Flag USE_ZLIB wird zur Unterstützung der zlib-Bibliothek verwendet. Die Bibliothek wurde verteilt und auf WebAssembly portiert, und Emscripten nimmt sie in das Projekt auf.

Das virtuelle Dateisystem Emscrippten ist aktiviert. Das POSIX-ähnliches FS, läuft im RAM im Browser. Beim Aktualisieren der Seite wird der Speicher gelöscht.

Um zu verstehen, warum ein virtuelles Dateisystem benötigt wird, lohnt es sich, die Art und Weise, wie Sie seqtk über die Befehlszeile ausführen, mit der Art und Weise zu vergleichen, wie Sie ein kompiliertes WebAssembly-Modul ausführen.

# On the command line
$ ./seqtk fqchk data.fastq
 
# In the browser console
> Module.callMain(["fqchk", "data.fastq"])

Der Zugriff auf das virtuelle Dateisystem ist erforderlich, um seqtk nicht für Zeichenfolgen statt für Dateieingaben neu zu schreiben. In diesem Fall wird das Datenfragment als data.fastq-Datei im virtuellen FS mit einem Aufruf von main() seqtk darauf angezeigt.

Hier ist die neue Architektur:

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Die Abbildung zeigt, dass anstelle von Berechnungen im Hauptbrowser-Thread WebWorker. Mit dieser Methode können Sie Berechnungen in einem Hintergrundthread durchführen, ohne die Reaktionsfähigkeit des Browsers zu beeinträchtigen. Nun, der WebWorker-Controller startet den Worker und verwaltet seine Interaktion mit dem Hauptthread.

Der seqtk-Befehl wird mit Worker für die gemountete Datei ausgeführt. Nach Abschluss der Ausführung erstellt der Worker ein Ergebnis in Form eines Versprechens. Wenn eine Nachricht vom Hauptthread empfangen wird, wird das Ergebnis zum Aktualisieren der Diagramme verwendet. Und so weiter in mehreren Iterationen.

Wie sieht es mit der Leistung von WebAssembly aus?

Um die Leistungsänderung zu bewerten, verwendete das Projektteam den Parameter Leseoperationen pro Sekunde. Die Zeit, die zum Erstellen interaktiver Diagramme benötigt wird, wird nicht berücksichtigt, da beide Implementierungen JavaScript verwenden.

Beim Einsatz der Out-of-the-Box-Lösung betrug die Leistungssteigerung das Neunfache.

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Das ist ein hervorragendes Ergebnis, aber wie sich herausstellt, besteht auch die Möglichkeit, es zu optimieren. Tatsache ist, dass eine große Anzahl von QC-Analyseergebnissen von seqtk nicht verwendet wird und daher gelöscht werden kann. Wenn Sie dies tun, verbessert sich das Ergebnis im Vergleich zu JS um das 13-fache.

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Dies wurde durch einfaches Auskommentieren der printf()-Befehle erreicht.

Aber das ist nicht alles. Tatsache ist, dass fastq.bio zu diesem Zeitpunkt die Analyseergebnisse durch den Aufruf verschiedener C-Funktionen erhält. Jede von ihnen berechnet ihre eigenen Merkmale, sodass jedes Fragment der Datei zweimal gelesen wird.

Um dieses Problem zu umgehen, wurde beschlossen, zwei Funktionen in einer zu kombinieren. Dadurch stieg die Produktivität um das Zwanzigfache.

Wie wir WebAssembly verwendet haben, um eine Webanwendung um das 20-fache zu beschleunigen

Es ist erwähnenswert, dass solch ein hervorragendes Ergebnis nicht immer erreicht werden kann. In manchen Fällen sinkt die Leistung, daher lohnt es sich, jeden Einzelfall zu bewerten.

Zusammenfassend können wir sagen, dass Wasm zwar die Möglichkeit bietet, die Anwendungsleistung zu verbessern, Sie diese jedoch mit Bedacht nutzen müssen.

Skillbox empfiehlt:

Source: habr.com

Kommentar hinzufügen