
Cet article décrit un cas pour accélérer une application de navigateur en remplaçant JavaScript par WebAssembly.
WebAssembly - qu'est-ce que c'est?
En bref, il s'agit d'un format d'instructions binaires pour une machine virtuelle empilée. Wasm (nom court) est souvent appelé langage de programmation, mais ce n'est pas le cas. Le format d'instruction est exécuté dans le navigateur avec JavaScript.
Il est important que WebAssembly puisse être obtenu en compilant des sources dans des langages tels que C / C ++, Rust, Go. Il utilise le typage statique et le modèle de mémoire dit plat. Le code, comme mentionné ci-dessus, est stocké dans un format binaire compact, il s'exécute donc presque aussi vite que si l'application était lancée à l'aide de la ligne de commande. Ces fonctionnalités ont conduit à la popularité croissante de WebAssembly.
Nous vous rappelons: pour tous les lecteurs de «Habr» - une remise de 10 000 roubles lors de l'inscription à un cours Skillbox en utilisant le code promo «Habr».
Skillbox recommande: Cours pratique "Mobile Developer PRO" .
Wasm est actuellement utilisé dans de nombreuses applications, des jeux comme Doom 3 aux applications Web comme Autocad et Figma. Wasm est également utilisé dans des domaines tels que l'informatique sans serveur.
Cet article fournit un exemple d'utilisation de Wasm pour accélérer un service Web analytique. Pour plus de clarté, nous avons pris une application de travail écrite en C, qui est compilée dans WebAssembly. Le résultat sera utilisé pour remplacer les sections à faible productivité de JS.
Transformation d'application
L'exemple utilisera le service de navigation fastq.bio, qui est destiné aux généticiens. L'outil vous permet d'évaluer la qualité du séquençage de l'ADN (décodage).
Voici un exemple d'application en cours:

Les détails du processus ne doivent pas être donnés, car ils sont plutôt compliqués pour les non-spécialistes, mais en bref, les scientifiques des infographies ci-dessus peuvent comprendre si le processus de séquençage de l'ADN s'est bien déroulé et quels problèmes sont survenus.
Ce service propose des alternatives, des programmes de bureau. Mais fastq.bio peut accélérer les choses en visualisant les données. Dans la plupart des autres cas, vous devez être en mesure de travailler avec la ligne de commande, mais tous les généticiens n'ont pas l'expérience nécessaire.
Tout fonctionne simplement. À l'entrée - données présentées sous la forme d'un fichier texte. Ce fichier est généré par des outils de séquençage spécialisés. Le fichier contient une liste de séquences d'ADN et une évaluation de la qualité de chaque nucléotide. Le format de fichier est .fastq, c'est pourquoi le service a obtenu son nom.
Implémentation JavaScript
La première étape de l'utilisateur lorsqu'il travaille avec fastq.bio est de sélectionner le fichier approprié. À l'aide de l'objet File, l'application lit une sélection aléatoire de données du fichier et traite ce package. La tâche de JavaScript ici est d'effectuer des opérations de chaîne simples et des indicateurs de comptage. L'un d'eux est le nombre de nucléotides A, C, G et T sur différents fragments d'ADN.
Après avoir calculé les indicateurs nécessaires, ils sont visualisés à l'aide de Plotly.js et le service commence à travailler avec une nouvelle sélection de données. La fragmentation est effectuée pour améliorer la qualité de l'UX. Si vous travaillez avec toutes les données à la fois, le processus se fige pendant un certain temps, car les fichiers avec des résultats de séquençage occupent des centaines de gigaoctets d'espace fichier. Le service prend des données de 0,5 à 1 Mo et travaille avec elles pas à pas pour créer des données graphiques.
Voici comment cela fonctionne:

Le rectangle rouge contient l'algorithme de conversion de chaîne pour le rendu. Il s'agit de la partie la plus chargée du service en termes informatiques. Il vaut la peine d'essayer de le remplacer par Wasm.
Test de WebAssembly
Pour évaluer la possibilité d'utiliser Wasm, l'équipe du projet a commencé à rechercher des solutions toutes faites pour créer des métriques QC (QC - contrôle qualité) basées sur des fichiers fastq. La recherche a été effectuée parmi les outils écrits en C, C ++ ou Rust, de sorte qu'il était possible de porter le code sur WebAssembly. De plus, l'outil ne doit pas être "brut", il nécessite un service déjà vérifié par les scientifiques.
En conséquence, le choix a été fait en faveur de
seqtk . L'application est assez populaire, elle est open-source, la langue source est C.
Avant de convertir en Wasm, vous devriez regarder le principe de la compilation de seqtk pour le bureau. Selon le Makefile, voici ce dont vous avez besoin:
# Compile to binary $ gcc seqtk.c \ -o seqtk \ -O2 \ -lm \ -lz
Fondamentalement, vous pouvez compiler seqtk avec Emscripten. Si ce n'est pas le cas, contournez
l'image Docker .
$ docker pull robertaboukhalil/emsdk:1.38.26 $ docker run -dt --name wasm-seqtk robertaboukhalil/emsdk:1.38.26
Si vous le souhaitez,
vous pouvez le récupérer vous -
même , mais cela prend du temps.
À l'intérieur du conteneur, vous pouvez facilement prendre emcc comme alternative à gcc:
# Compile to WebAssembly $ emcc seqtk.c \ -o seqtk.js \ -O2 \ -lm \ -s USE_ZLIB=1 \ -s FORCE_FILESYSTEM=1
Modifications minimales:
Au lieu de sortir dans le fichier binaire Emscripten, .wasm et .js sont utilisés pour générer les fichiers, qui sont utilisés pour exécuter le module WebAssemby.
Pour prendre en charge la bibliothèque zlib, l'indicateur USE_ZLIB est utilisé. La bibliothèque est distribuée et portée sur WebAssembly, et Emscripten l'inclut dans le projet.
Le système de fichiers virtuel Emscrippten est activé. Il s'agit d'un
FS de type POSIX fonctionnant en RAM à l'intérieur du navigateur. Lorsque la page est actualisée, la mémoire est effacée.
Pour comprendre pourquoi un système de fichiers virtuel est nécessaire, il vaut la peine de comparer la façon de démarrer seqtk à partir de la ligne de commande avec la façon d'exécuter le module WebAssembly compilé.
# On the command line $ ./seqtk fqchk data.fastq # In the browser console > Module.callMain(["fqchk", "data.fastq"])
L'accès au système de fichiers virtuel est nécessaire afin de ne pas écraser seqtk avec une chaîne plutôt qu'avec une entrée de fichier. Dans ce cas, le fragment de données est affiché en tant que fichier data.fastq dans le FS virtuel avec le seqtk principal () appelé dessus.
Voici la nouvelle architecture:

La figure montre qu'au lieu de l'informatique, le flux principal du navigateur utilise
WebWorkers . Cette méthode permet d'effectuer des calculs dans le thread d'arrière-plan sans affecter la réactivité du navigateur. Eh bien, le contrôleur WebWorker lance Worker, contrôlant son interaction avec le thread principal.
La commande seqtk est lancée à l'aide de Worker sur le fichier monté. Une fois le travail terminé, Worker affiche le résultat sous forme de promesse. Lorsqu'un message est reçu par le thread principal, le résultat est utilisé pour mettre à jour les planifications. Et donc en quelques itérations.
Qu'en est-il des performances de WebAssembly?
Afin d'évaluer l'évolution de la performance, l'équipe projet a utilisé le paramètre du nombre d'opérations de lecture par seconde. Le temps de création de graphiques interactifs n'est pas pris en compte, car les deux implémentations utilisent JavaScript.
Lors de l'utilisation de la solution prête à l'emploi, le gain de performances était neuf fois.

C'est un excellent résultat, mais il s'est avéré qu'il était possible de l'optimiser. Le fait est qu'un grand nombre de résultats d'analyse QC ne sont pas utilisés par seqtk, vous pouvez donc les supprimer. Si vous faites cela, le résultat par rapport à JS est amélioré 13 fois.

Il était possible d'y parvenir en commentant simplement les commandes printf ().
Mais ce n'est pas tout. Le fait est qu'à ce stade, fastq.bio reçoit les résultats de l'analyse en appelant différentes fonctions de C. Chacune d'elles calcule son propre ensemble de caractéristiques, de sorte que chaque fragment du fichier est lu deux fois.
Afin de contourner ce problème, il a été décidé de combiner les deux fonctions en une seule. En conséquence, la productivité a été multipliée par 20.

Il convient de noter qu'un résultat aussi remarquable ne peut pas toujours être obtenu. Dans certains cas, les performances diminuent, il vaut donc la peine d'évaluer chaque cas.
En conclusion, nous pouvons dire que Wasm permet vraiment d'améliorer les performances des applications, mais vous devez l'utiliser à bon escient.
Skillbox recommande: