Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

In diesem Artikel wird der Fall beschrieben, wie man eine browserbasierte Anwendung beschleunigen kann, indem man Berechnungen in JavaScript durch WebAssembly ersetzt.

Was ist WebAssembly?

Kurz gesagt, es handelt sich um ein binĂ€res Format fĂŒr Anweisungen einer stackbasierten virtuellen Maschine. Oft wird Wasm (die AbkĂŒrzung) als Programmiersprache bezeichnet, was jedoch nicht zutrifft. Das Anweisungsformat wird im Browser zusammen mit JavaScript ausgefĂŒhrt.

Es ist wichtig zu beachten, dass WebAssembly durch die Kompilierung von Quellcode in Programmiersprachen wie C/C++, Rust und Go erzeugt werden kann. Hierbei kommt eine statische Typisierung und ein sogenanntes flaches Speichermodell zum Einsatz. Der Code, wie bereits erwĂ€hnt, wird in einem kompakten binĂ€ren Format gespeichert, wodurch er fast genauso schnell ausgefĂŒhrt wird, als ob die Anwendung ĂŒber die Kommandozeile gestartet worden wĂ€re. Diese Eigenschaften haben zur wachsenden PopularitĂ€t von WebAssembly beigetragen.

Wir erinnern daran: alle Leser von „Habr“ erhalten einen Rabatt von 10.000 Rubel bei der Anmeldung zu einem beliebigen Kurs von Skillbox mit dem Aktionscode „Habr“.

Skillbox empfiehlt: Praktischer Kurs „Mobile Entwickler PRO“.

Derzeit wird Wasm in vielen Anwendungen eingesetzt, von Spielen wie Doom 3 bis hin zu in das Web portierten Anwendungen wie Autocad und Figma. Wasm findet auch in Bereichen wie serverlosen Berechnungen Anwendung.

In diesem Artikel wird ein Beispiel fĂŒr die Nutzung von Wasm zur Beschleunigung eines analytischen Webdienstes vorgestellt. Zu Illustrationszwecken verwenden wir eine funktionierende Anwendung, die in C geschrieben ist und in WebAssembly kompiliert wird. Das Ergebnis wird zur Optimierung wenig leistungsfĂ€higer JavaScript-Abschnitte verwendet.

Transformation der Anwendung

Im Beispiel wird der browserbasierte Dienst fastq.bio verwendet, der fĂŒr Genetiker konzipiert ist. Das Tool ermöglicht die Bewertung der SequenzierungsqualitĂ€t von DNA.

Hier ist ein Beispiel der Anwendung in Aktion:

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Die Details des Prozesses mĂŒssen nicht im Einzelnen erlĂ€utert werden, da sie fĂŒr Laien ziemlich komplex sind. Kurz zusammengefasst können Wissenschaftler anhand der oben genannten Infografik herausfinden, ob der DNA-Sequenzierungsprozess reibungslos verlief und welche Probleme auftraten.

Dieser Dienst hat Desktop-Alternativen. Doch fastq.bio ermöglicht eine schnellere Verarbeitung durch die Visualisierung der Daten. In den meisten anderen FĂ€llen ist Erfahrung mit der Befehlszeile erforderlich, aber nicht alle Genetiker verfĂŒgen ĂŒber die nötigen Kenntnisse.

Alles funktioniert ganz einfach. Der Eingang sind Daten, die in Form einer Textdatei vorliegen. Diese Datei wird von spezialisierten Sequenzierungswerkzeugen generiert. In der Datei befindet sich eine Liste von DNA-Sequenzen sowie eine QualitĂ€tsbewertung fĂŒr jedes Nukleotid. Das Dateiformat ist .fastq, weshalb der Service diesen Namen trĂ€gt.

Implementierung in JavaScript

Der erste Schritt des Nutzers bei der Arbeit mit fastq.bio ist die Auswahl der entsprechenden Datei. Mit Hilfe des File-Objekts liest die Anwendung eine zufĂ€llige Auswahl von Daten aus der Datei und verarbeitet dieses Paket. Die Aufgabe von JavaScript dabei besteht in der DurchfĂŒhrung einfacher String-Operationen und der Berechnung von Kennzahlen. Eine davon ist die Anzahl der Nukleotide A, C, G und T in verschiedenen DNA-Fragmenten.

Nach der Berechnung der erforderlichen Parameter werden diese mithilfe von Plotly.js visualisiert, und der Dienst beginnt, mit dem neuen Datensatz zu arbeiten. Die Segmentierung wurde zur Verbesserung der Benutzererfahrung vorgenommen. Wenn man mit allen Daten gleichzeitig arbeitet, könnte der Prozess einige Zeit hĂ€ngen bleiben, da die Dateien mit den Sequenzierungsergebnissen Hunderte von Gigabyte Speicherplatz beanspruchen. Der Dienst verarbeitet daher DatenstĂŒcke von 0,5 bis 1 MB und arbeitet schrittweise damit, um grafische Daten zu erstellen.

So funktioniert es:

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Im roten Rechteck befindet sich der Algorithmus fĂŒr die Zeichenfolgenumwandlung zur Erstellung der Visualisierung. Dies ist der rechenintensivste Teil des Dienstes. Es wĂ€re ratsam, ihn durch Wasm zu ersetzen.

WebAssembly testen

Um die Möglichkeiten der Nutzung von Wasm zu bewerten, beschĂ€ftigte sich das Projektteam mit der Suche nach vorhandenen Lösungen zur Erstellung von QC-Metriken (QC – QualitĂ€tskontrolle) basierend auf fastq-Dateien. Die Suche konzentrierte sich auf Werkzeuge, die in C, C++ oder Rust geschrieben wurden, um die Portierung des Codes auf WebAssembly zu ermöglichen. Zudem sollte das Werkzeug nicht "roh" sein; es wurde ein bereits wissenschaftlich validierter Dienst benötigt.

Die Wahl fiel auf seqtk. Die Anwendung ist recht populÀr, sie ist Open Source, die Programmiersprache ist C.

Bevor man es in Wasm umwandelt, sollte man sich das Kompilierungsprinzip von seqtk fĂŒr den Desktop ansehen. Laut Makefile ist Folgendes erforderlich:

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

Im Grunde kann seqtk mit Emscripten kompiliert werden. Wenn es nicht vorhanden ist, nutzen wir Docker.

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

Wenn gewĂŒnscht kann man es auch selbst kompilieren, aber das braucht Zeit.

Im Container kann man problemlos emcc als Alternative zu gcc verwenden:

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

Minimale Änderungen:

Anstelle der Ausgabe in eine BinÀrdatei verwendet Emscripten .wasm und .js zur Generierung von Dateien, die zum Starten des WebAssembly-Moduls verwendet werden.

Um die zlib-Bibliothek zu unterstĂŒtzen, wird die Flagge USE_ZLIB verwendet. Diese Bibliothek ist weit verbreitet und auf WebAssembly portiert, und Emscripten beinhaltet sie im Projekt.

Das virtuelle Dateisystem von Emscripten wird aktiviert. Es ist eine POSIX-Àhnliche FS, die im Arbeitsspeicher innerhalb des Browsers funktioniert. Bei einem Seitenaktualisierung wird der Speicher gelöscht.

Um zu verstehen, warum ein virtuelles Dateisystem notwendig ist, lohnt sich ein Vergleich zwischen dem Start von seqtk ĂŒber die Befehlszeile und dem Start eines kompilierten WebAssembly-Moduls.

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

Der Zugriff auf das virtuelle Dateisystem wird benötigt, um seqtk nicht fĂŒr den zeilenweisen, sondern fĂŒr den dateibasierten Input umzuschreiben. In diesem Fall wird ein Datenfragment als Datei data.fastq im virtuellen FS angezeigt, mit einem Aufruf von main() seqtk darauf.

Hier ist die neue Architektur:

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Die Abbildung zeigt, dass anstelle von Berechnungen im Hauptthread des Browsers WebWorkersverwendet werden. Diese Methode ermöglicht es, Berechnungen im Hintergrund durchzufĂŒhren, ohne die ReaktionsfĂ€higkeit des Browsers zu beeintrĂ€chtigen. Der WebWorker-Controller startet einen Worker und verwaltet dessen Interaktion mit dem Hauptthread.

Der seqtk-Befehl wird durch einen Worker auf der eingehĂ€ngten Datei ausgefĂŒhrt. Nach Abschluss der AusfĂŒhrung gibt der Worker das Ergebnis als Promise zurĂŒck. Sobald die Nachricht im Hauptthread eingegangen ist, wird das Ergebnis zur Aktualisierung der Grafiken verwendet. Und das geschieht ĂŒber mehrere Iterationen.

Wie sieht es mit der Leistung von WebAssembly aus?

Um die VerĂ€nderung der Leistung zu bewerten, hat das Projektteam den Parameter der Leseoperationen pro Sekunde genutzt. Die Zeit fĂŒr den Aufbau interaktiver Grafiken wird nicht berĂŒcksichtigt, da in beiden Implementierungen JavaScript verwendet wird.

Bei der Verwendung der "Out-of-the-Box"-Lösung betrug der Leistungszuwachs das Neunfache.

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Das ist ein hervorragendes Ergebnis, aber wie sich herausstellte, gibt es Möglichkeiten zur weiteren Optimierung. Viele der QC-Analysergebnisse verwenden nicht seqtk, daher können sie gelöscht werden. Wenn dies erfolgt, verbessert sich das Ergebnis im Vergleich zu JS auf das 13-fache.

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Dies wurde einfach durch das Kommentieren der printf()-Befehle erreicht.

Aber das ist noch nicht alles. Zu diesem Zeitpunkt erhÀlt fastq.bio die Analyseergebnisse durch den Aufruf verschiedener C-Funktionen. Jede davon berechnet ihren eigenen Satz an Merkmalen, sodass jeder Dateifrag ment zweimal gelesen wurde.

Um dieses Problem zu umgehen, wurde beschlossen, zwei Funktionen in einer zu kombinieren. Infolgedessen stieg die Leistung um das 20-fache.

Wie wir die Webanwendung mit Hilfe von WebAssembly um das 20-Fache beschleunigt haben

Es ist wichtig zu beachten, dass ein solch herausragendes Ergebnis nicht immer erreicht werden kann. In einigen FĂ€llen sinkt die Leistung, daher sollte jeder spezifische Fall bewertet werden.

Zusammenfassend lĂ€sst sich sagen, dass Wasm tatsĂ€chlich die Leistung von Anwendungen verbessern kann, aber sein Einsatz wohlĂŒberlegt sein sollte.

Skillbox empfiehlt:

Quelle: habr.com

Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Servern đŸ”„ Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Servern | ProHoster