
Ebben a cikkben a böngészőalkalmazás gyorsításának esetét vizsgáljuk meg, ahol a JavaScript számításokat WebAssembly-ra cseréljük.
Mi az a WebAssembly?
Röviden, ez egy bináris utasításformátum a verem virtuális gép számára. Gyakran a Wasm (rövidített név) programozási nyelvnek nevezik, de ez nem igaz. Az utasításformátumot a böngésző hajtja végre a JavaScript mellett.
Fontos, hogy a WebAssembly-t olyan nyelvek forráskódjaiból lehet előállítani, mint a C/C++, Rust, Go. Itt statikus típusellenőrzést és úgynevezett lapos memória modellt alkalmaznak. A kód, mint említettük, tömör bináris formátumban tárolódik, ami miatt majdnem olyan gyorsan fut, mintha az alkalmazást parancssorból indították volna. Ezek a lehetőségek vezetettek a WebAssembly népszerűségének növekedéséhez.
Emlékeztetjük: minden «Habr» olvasónak 10 000 rubeles kedvezmény jár bármely Skillbox kurzus jelentkezésekor a «Habr» promóciós kód felhasználásával.
A Skillbox ajánlja: Gyakorlati kurzus .
Jelenleg a Wasm-t számos alkalmazásban használják, a Doom 3 játékoktól a webre portolt alkalmazásokig, mint az Autocad és Figma. A Wasm-t a serverless számítások területén is alkalmazzák.
Ebben a cikkben példa található a Wasm használatára egy analitikai webszolgáltatás gyorsítására. A szemléltetés érdekében egy működő alkalmazást vettünk alapul, amely C nyelven készült és WebAssembly-ba fordítható. Az eredményt a gyenge teljesítményű JS szakaszok helyettesítésére fogjuk használni.
Az alkalmazás átalakítása
A példában a fastq.bio böngészőszolgáltatás kerül felhasználásra, amely genetikusok számára készült. Ez az eszköz lehetővé teszi a DNS szekvenálás (dekódolás) minőségének értékelését.
Íme egy példa az alkalmazás működésére:

A folyamat részleteit nem célszerű ismertetni, mivel azok a nem szakemberek számára meglehetősen bonyolultak, de röviden, a tudósok az említett infografika alapján megérthetik, hogy a DNS szekvenálási folyamat zökkenőmentes volt-e, és milyen problémák merültek fel.
Ennek a szolgáltatásnak vannak alternatívái, asztali programok. De a fastq.bio segít a munka felgyorsításában az adatok vizualizálásával. A legtöbb más esetben szükség van a parancssori munkavégzés tudására, de nem minden genetikus rendelkezik a megfelelő tapasztalattal.
Minden nagyon egyszerűen működik. A bemenet egy szöveges fájlban megjelenített adat. Ezt a fájlt a szekvenáláshoz szükséges speciális eszközök generálják. A fájlban DNS-szekvenciák listája és minden egyes nukleotid minősége található. A fájl formátuma .fastq, ezért a szolgáltatás is ezt a nevet kapta.
Megvalósítás JavaScript-ben
Az első lépés a felhasználónál a fastq.bio használatakor a megfelelő fájl kiválasztása. A File objektum segítségével az alkalmazás véletlenszerű adatmintát olvas be a fájlból és dolgozza fel ezt a csomagot. A JavaScript feladata itt egyszerű karakterlánc műveletek végrehajtása és a mutatók számítása. Az egyik ezek közül az A, C, G és T nukleotidek száma a különböző DNS-fragmentumokon.
A szükséges mutatók számítása után azokat a Plotly.js segítségével vizualizálják, és a szolgáltatás új adatmintával kezd dolgozni. A fragmentálás célja a felhasználói élmény minőségének javítása. Ha egyszerre minden adaton dolgoznánk, a folyamat egy ideig leállna, mivel a szekvenálási eredmények fájlok száz gigabájtok terjedelmet foglalnak el. A szolgáltatás viszont 0,5 és 1 MB közötti adatdarabokat vesz, és lépésről lépésre dolgozik velük, grafikákat építve.
Így működik:

A piros téglalapban található a karakterlánc-transzformációs algoritmus a vizualizáció létrehozásához. Ez a szolgáltatás legnagyobb számítási igényű része. Érdemes lenne ezt Wasm-re cserélni.
WebAssembly tesztelése
A Wasm használatának lehetőségének értékeléséhez a projekt csapata keresett kész megoldásokat a QC-metrika (QC - minőségellenőrzés) létrehozásához fastq fájlok alapján. A keresés során C, C++ vagy Rust nyelven íródott eszközöket kerestek, hogy lehetőség legyen a kód WebAssembly-re történő portolására. Ezen kívül az eszköznek nem szabad «nyersnek» lennie, már tudósok által tesztelt szolgáltatásra volt szükség.
Végül a választás a következőre esett . Az alkalmazás meglehetősen népszerű, open-source, alapnyelve C.
A Wasm-re való átalakítás előtt érdemes megnézni a seqtk asztali verziójának fordítási elvét. A Makefile szerint ez az, amire szükség van:
# Compile to binary
$ gcc seqtk.c
-o seqtk
-O2
-lm
-lzAlapvetően a seqtk-t Emscripten segítségével lehet fordítani. Ha ez nincs, akkor .
$ docker pull robertaboukhalil/emsdk:1.38.26
$ docker run -dt --name wasm-seqtk robertaboukhalil/emsdk:1.38.26Ha szükséges, , de ez időt vesz igénybe.
A konténeren belül probléma nélkül használhatjuk az emcc-t a gcc alternatívájaként:
# Compile to WebAssembly
$ emcc seqtk.c
-o seqtk.js
-O2
-lm
-s USE_ZLIB=1
-s FORCE_FILESYSTEM=1Minimum változtatások:
A bináris fájlok helyett az Emscripten a .wasm és .js fájlok generálására használatos, amelyek a WebAssembly modul futtatásához szükségesek.
A zlib könyvtár támogatásához a USE_ZLIB kapcsolót kell használni. Ez a könyvtár széles körben elérhető és portálva van WebAssembly-re, az Emscripten pedig belefoglalja a projektbe.
Az Emscripten virtuális fájlrendszere aktiválva van. Ez , amely a böngésző memóriájában működik. Amikor az oldal frissül, a memória törlődik.
Ahhoz, hogy megértsük, miért van szükség virtuális fájlrendszerre, érdemes összehasonlítani a seqtk parancssori indítását a WebAssembly modul futtatásának módjával.
# On the command line
$ ./seqtk fqchk data.fastq
# In the browser console
> Module.callMain(["fqchk", "data.fastq"])A virtuális fájlrendszerhez való hozzáférés szükséges ahhoz, hogy ne kelljen a seqtk-t karakteres, hanem fájl alapú bemenetre átírni. Ebben az esetben az adatrészlet egy fájlként jelenik meg a data.fastq néven a virtuális fájlrendszerben, amelyen a main() seqtk hívás történik.
Íme az új architektúra:

A rajz bemutatja, hogy a böngésző fő szála helyett használhatók. Ez a módszer lehetővé teszi a háttérben történő számítások végrehajtását anélkül, hogy rontaná a böngésző reakcióidejét. A WebWorker vezérlő elindítja a Workert, irányítva annak interakcióját a fő szálal.
A seqtk parancsot Worker segítségével a csatolt fájlon keresztül indítjuk. Miután a Worker végrehajtása befejeződött, az eredmény Promise formájában érkezik. Amikor az üzenet a fő szálon megérkezik, az eredmény felhasználásra kerül a grafikonok frissítésére. Így történik ez többszöri iteráción keresztül.
Mi a helyzet a WebAssembly teljesítményével?
A teljesítményváltozás értékelése érdekében a projektcsapat a másodpercenkénti olvasási műveletek számát vette alapul. Az interaktív grafikonok felépítésének idejét nem számítják bele, mivel mindkét implementáció JavaScriptet használ.
A "dobozból való" megoldás alkalmazásával a teljesítmény növekedés kilencszeres volt.

Ez nagyszerű eredmény, de kiderült, hogy van lehetőség a további optimalizálásra is. Az a helyzet, hogy a QC-elemzés sok eredménye nem használt a seqtk által, így ezeket el lehet távolítani. Ha ezt megteszik, az eredmény a JS-hez képest 13-szoros javulást mutat.

Ezt egyszerűen a printf() parancsok kikommentelésével sikerült elérni.
De ez még nem minden. A helyzet az, hogy ezen a ponton a fastq.bio különböző C-funkciók hívásával kapja az elemzési eredményeket. Mindegyikük a saját jellemzőit számolja ki, így a fájl minden egyes darabját kétszer olvassák.
Annak érdekében, hogy megkerüljük ezt a problémát, úgy döntöttünk, hogy egyesítjük a két funkciót egybe. Ennek eredményeként a teljesítmény 20-szorosára nőtt.

Érdemes megjegyezni, hogy az ilyen kiemelkedő eredmények elérése nem mindig lehetséges. Néhány esetben a teljesítmény csökken, ezért érdemes minden egyes esetet külön-külön értékelni.
Összegzésképpen elmondható, hogy a Wasm valóban lehetőséget ad az alkalmazás teljesítményének javítására, de okosan kell használni.
A Skillbox ajánlja:
- Kétéves gyakorlati tanfolyam .
- Online kurzus .
- Gyakorlati éves kurzus .
Forrás: habr.com
