Як мы пры дапамозе WebAssembly у 20 разоў вэб-дадатак паскорылі
У гэтым артыкуле разглядаецца кейс па паскарэнні браузернага прыкладання праз замену вылічэнняў JavaScript на WebAssembly.
WebAssembly - што гэта такое?
Калі сцісла, тое гэта гэта бінарны фармат інструкцый для стэкавай віртуальнай машыны. Часта Wasm (скарочаная назва) называюць мовай праграмавання, але гэта не так. Фармат інструкцый выконваецца ў браўзэры нараўне з JavaScript.
Важна, што WebAssembly можна атрымаць пры кампіляцыі зыходнікаў на такіх мовах, як C/C++, Rust, Go. Тут прымяняецца статыстычная тыпізацыя і так званая плоская мадэль памяці. Код, як сказана вышэй, захоўваецца ў кампактным бінарным фармаце, дзякуючы чаму выконваецца амаль гэтак жа хутка, як калі б прыкладанне было запушчана з дапамогай каманднага радка. Гэтыя магчымасці і прывялі да росту папулярнасці WebAssembly.
Нагадваем:для ўсіх чытачоў "Хабра" - зніжка 10 000 рублёў пры запісе на любы курс Skillbox па промакодзе "Хабр".
На дадзены момант Wasm выкарыстоўваецца ў шматлікіх прыкладаннях, ад гульняў накшталт Doom 3 да партаваных у вэб прыкладанняў тыпу Autocad і Figma. Wasm прымяняецца і ў такой сферы, як serverless вылічэнні.
У гэтым артыкуле прыведзены прыклад выкарыстання Wasm для паскарэння аналітычнага вэб-сэрвісу. Для навочнасці мы ўзялі працавальнае прыкладанне, напісанае на З, якое скампілюецца ў WebAssembly. Вынік будзе выкарыстаны для замены малапрадукцыйных участкаў JS.
Трансфармацыя прыкладання
У прыкладзе будзе выкарыстоўвацца браузерны сэрвіс fastq.bio, які прызначаны для генетыкаў. Інструмент дазваляе ацаніць якасць секвеніравання (расшыфроўкі) ДНК.
Вось прыклад прыкладання ў працы:
Падрабязнасці працэсу не варта прыводзіць, паколькі яны даволі складаныя для неспецыялістаў, але калі сцісла, то навукоўцы па названай вышэй інфаграфіцы могуць зразумець, ці прайшоў працэс секвеніравання ДНК гладка і якія ўзніклі праблемы.
У гэтага сэрвісу ёсць альтэрнатывы, дэсктопныя праграмы. Але fastq.bio дазваляе паскорыць працу, візуалізуючы дадзеныя. У большасці іншых выпадкаў трэба ўмець працаваць з камандным радком, але не ва ўсіх генетыкаў ёсць патрэбны досвед.
Працуе ўсё проста. На ўваходзе - дадзеныя, якія прадстаўляюцца ў выглядзе тэкставага файла. Гэты файл генеруецца спецыялізаванымі прыладамі для секвеніравання. У файле размяшчаецца спіс паслядоўнасцяў ДНК і ацэнка якасці для кожнага нуклеатыдаў. Фармат файла .fastq, таму сэрвіс і атрымаў такую назву.
Рэалізацыя на JavaScript
Першы крок карыстальніка пры працы з fastq.bio - выбар адпаведнага файла. Выкарыстоўваючы аб'ект File, прыкладанне счытвае выпадковую выбарку дадзеных з файла і апрацоўвае гэты пакет. Задача JavaScript тут - выкананне нескладаных радковых аперацый і падлік паказчыкаў. Адзін з іх - колькасць нуклеатыдаў A, C, G і T на розных фрагментах ДНК.
Пасля праліку патрэбных паказчыкаў яны візуалізуюцца пры дапамозе Plotly.js, а сэрвіс пачынае працаваць з новай выбаркай дадзеных. Падзел на фрагменты зроблена для павышэння якасці UX. Калі працаваць з усімі дадзенымі адразу, працэс завісне на нейкі час, паколькі файлы з вынікамі секвеніравання займаюць сотні гігабайтаў файлавай прасторы. Сэрвіс жа бярэ ўчасткі дадзеных памерам ад 0,5 да 1 Мб і працуе з імі крок за крокам, выбудоўваючы графічныя дадзеныя.
Вось як гэта працуе:
У чырвоным прамавугольніку размяшчаецца алгарытм радковых пераўтварэнняў для атрымання візуалізацыі. Гэта найболей нагружаная з пункта гледжання вылічэнняў частка сэрвісу. Варта паспрабаваць замяніць яе на Wasm.
Тэстуем WebAssembly
Для ацэнкі магчымасці выкарыстання Wasm каманда праекта занялася пошукам гатовых рашэнняў для стварэння QC-метрыкі (QC – quality control) на аснове файлаў fastq. Пошук вёўся сярод прылад, напісаных на З, З++ ці Rust, каб была магчымасць партаваць код на WebAssembly. Акрамя таго, інструмент не павінен быць "волкім", патрабаваўся сэрвіс, ужо правераны навукоўцамі.
У выніку выбар быў зроблены на карысць seqtk. Прыкладанне даволі папулярнае, яно open-source, зыходная мова - С.
Перад пераўтварэннем у Wasm варта паглядзець прынцып кампіляцыі seqtk для дэсктопа. Згодна з Makefile, вось тое, што трэба:
Замест вываду ў бінарны файл Emscripten для генерацыі файлаў выкарыстоўваецца .wasm і .js, які прымяняецца для запуску модуля WebAssemby.
Для падтрымкі бібліятэкі zlib выкарыстоўваецца сьцяг USE_ZLIB. Бібліятэка распаўсюджана і партавана на WebAssembly, а Emscripten уключае яе ў праект.
Актывуецца віртуальная файлавая сістэма Emscrippten. Гэта POSIX-падобная ФС, якая працуе ў аператыўнай памяці ўнутры браўзэра. Калі старонка абнаўляецца, памяць чысціцца.
Каб зразумець, навошта патрэбна віртуальная файлавая сістэма, варта параўнаць спосаб запуску seqtk з каманднага радка са спосабам запуску скампіляванага модуля WebAssembly.
# On the command line
$ ./seqtk fqchk data.fastq
# In the browser console
> Module.callMain(["fqchk", "data.fastq"])
Атрыманне доступу да віртуальнай файлавай сістэмы трэба, каб не перапісваць seqtk пад радковы, а не файлавы ўвод. У гэтым выпадку фрагмент дадзеных адлюстроўваецца як файл data.fastq у віртуальнай ФС з выклікам на ім main() seqtk.
Вось новая архітэктура:
Малюнак дэманструе, што замест вылічэнняў у асноўным струмені браўзэра выкарыстоўваецца WebWorkers. Гэты спосаб дае магчымасць выконваць вылічэнні ў фонавым струмені, не пагаршаючы спагадлівасць браўзэра. Ну а кантролер WebWorker запускае Worker, кіруючы яго ўзаемадзеяннем з асноўным струменем.
Каманда seqtk запускаецца пры дапамозе Worker на прымантаваным файле. Пасля завяршэння выканання Worker выдае вынік у выглядзе Promise. Калі паведамленне атрымана галоўнай плынню, вынік выкарыстоўваецца для абнаўлення графікаў. І так у некалькі ітэрацый.
Што наконт прадукцыйнасці WebAssembly?
Для таго, каб ацаніць змену прадукцыйнасці, каманда праекту скарысталася параметрам колькасці аперацый чытання ў секунду. Час пабудовы інтэрактыўных графікаў не ўлічваецца, паколькі ў абедзвюх імплементацыя выкарыстоўваецца JavaScript.
Пры выкарыстанні рашэння са скрынкі прырост прадукцыйнасці склаў дзевяць разоў.
Гэта выдатны вынік, але, як аказалася, ёсць магчымасць аптымізаваць і яго. Справа ў тым, што вялікая колькасць вынікаў QC-аналізу не выкарыстоўваецца seqtk, таму іх можна выдаліць. Калі гэта зрабіць, вынік у параўнанні з JS паляпшаецца ў 13 разоў.
Дасягнуць яго атрымалася простым каментаваннем каманд printf().
Але і гэта не ўсё. Справа ў тым, што на гэтым этапе fastq.bio атрымлівае вынікі аналізу з выклікам розных функцый С. Любая з іх вылічае свой набор характарыстык, так што кожны фрагмент файла чытаўся па два разы.
Для таго, каб абыйсці гэтую праблему, было вырашана сумясціць дзве функцыі ў адну. У выніку прадукцыйнасць павялічылася ў 20 разоў.
Варта адзначыць, што такога выбітнага выніку можна дасягнуць далёка не заўсёды. У некаторых выпадках прадукцыйнасць падае, таму варта ацэньваць кожны канкрэтны выпадак.
У якасці высновы можна сказаць, што Wasm сапраўды дае магчымасць палепшыць прадукцыйнасць дадатку, але выкарыстоўваць яго трэба з розумам.