🔥

Тред (Андрей Нагих)


Мы поговорили о том, что может Wasm и какой он классный. Но, как и у любой технологии, у него есть ограничения.

🛑Как я уже говорил, в Wasm нет сборщика мусора, поэтому либо вы используете язык с ручным управлением памяти, либо пишете рантайм со своим сборщиком мусора. Есть пропозал о подключении Wasm к GC браузера сейчас он на 1 стадии github.com/webassembly/gc…

Но работы по нему ведутся поэтапно. И пропозал ReferenceTypes, который нужен для реализации GC, уже на 3 стадии. Это значит, что уже идёт реализация в браузерах.

🛑Другая особенность: только 32 битный доступ к памяти. Это оставляет нас с жалкими 4Гб памяти возможной для использования.😀 Есть планы по wasm64, но они где-то впереди. Есть более насущные вопросы.

🛑 Ещё одна проблема, это треды. Изначально их поддержка была реализована в Emscripten, но она использует SharedArrayBuffer, которые браузеры отключили в 2018 году для борьбы с уязвимостями Spectre и Meltdown chromium.org/Home/chromium-…

На сегодняшний день поддержка вернулась только в Chrome. Ожидается поддержка в Edge. FF пока осторожничает.

🛑Пожалуй, главная неприятность, которая нас ждёт, это то, что Wasm исполняется внутри песочницы браузера. Поэтому как и у JS, у нас нет доступа к платформе: нет файлов, нет сети, нет генератора случайных чисел, и пр.

Все эти возможности нам придётся реализовать теми средствами, которые уже есть у браузеров. Далеко не всегда удаётся подобрать полноценную замену.
notion image

Например, до tcp или udp сокета не добраться никак. Мы можем посылать HTTP запросы. Или работать по WebSocket. Или использовать WebRTC. На этом с сетью точка.

Наш p2p прокси-сервер Bytefog, как вы понимаете, основательно полагается на сеть. И нам пришлось полностью переделать сетевую часть. Мы используем все три возможности. На сервере мы написали tcp2http прокси, чтобы адаптировать протокол. Для этого использовали Node.js

При портировании приложения больше половины времени (8 мес.) у нас ушло на рефакторинг C++ кода. Мы выделяли интерфейсы в тех местах, где подставили JS реализацию. Таким образом, мы оставили старые реализации для нативных платформ, и JS для браузера.
notion image
notion image

🛑Очень важный и для многих неожиданный недостаток — Wasm не ускорит ваш код. Есть популярное мнение, что если взять алгоритм на JS, переписать его на плюсы, скомпилировать в Wasm, то он станет гораздо быстрее. Короткий ответ: Это не так.

Мы провели небольшой эксперимент: реализовали несколько фильтров обработки изображения на JS и C++. При компиляции C++ с оптимизацией мы получили паритет. Исходники теста выложили, можете попробовать сами. github.com/andrnag/wasm_c… График нормирован к JS.
notion image

Я тут по ходу публикую слайды из своего доклада о нашем опыте внедрения WebAssembly. Для нетерпеливых сразу опубликую ссылки. Текстовая версия на Хабре: habr.com/ru/company/jug… И видео с HolyJS: youtube.com/watch?v=uqG9Di…

Продолжая о производительности. В доклад не попало, но мы сделали ещё один замер, С++ код в нативе (без Wasm, и без браузера). Мы ожидали увидеть ускорение по сравнению с Wasm, но и здесь его не было.

Из всего этого я делаю такой вывод. Современные виртуальные машины JS настолько оптимизированы, что простой арифметический код почти сразу оптимизируется JIT-ом до машинного. Поэтому работает с той скоростью, что позволяет ваш процессор.

В случае Wasm браузеру проще это сделать, т.к. код уже разложен по полочкам, использует строгие типы и сам управляет памятью. Вы получаете ожидаемую, ровную производительность. Без сюрпризов деоптимизации, которые может подкинуть JS.

. @jsunderhood а есть какая-то стоимость у interop между wasm-js? Есть ми порог, после которого лучше выкинуть что-то в wasm, а не писать на жс?
С чем на самом деле возникают сложности, это с вызовами между контекстами JS и Wasm. Сёва задал очень правильный вопрос. twitter.com/jabher/status/…

Любой такой вызов имеет накладные расходы вызванные устройством браузера. Также Emscripten добавляет к ним при пробросе объектов туда-обратно. В итоге, в реальных приложениях производительность сильно зависит от того, что конкретно вы делаете.

Именно поэтому сложно сделать объективный benchmark. Также, браузеры постоянно работают над снижением накладных расходов. Значительный успех был в конце 2018 года: ускорили вызов функций. Подробнее — у Lin Clark. hacks.mozilla.org/2018/10/calls-…🎉

В нашем случае, вычислительного кода было совсем мало, и выполнялся он почти мгновенно. Ограничителем производительности является сеть. Мы тестировали передачу больших блобов из JS в Wasm и обратно. Передача 12 Мб данных занимает около 100 ms. 12 Мб это 5 секунд FullHD видео.