Состояние WebAssembly в 2022-23 годах
Автор статьи Жерар Галлан известен как автор книги “WebAssembly in Action”, выпущенной Manning в 2018 году. Существует перевод его книги на русский — “WebAssembly в действии” (Питер, 2022).
Предыдущий обзор The State of WebAssembly – 2021 and 2022 опубликован автором в январе 2022 года.
— Прим. переводчика.
В этой статье я рассмотрю текущее состояние дел с WebAssembly (wasm). Начну с обзора событий 2022 года, чтобы посмотреть, сбылись ли какие-либо из моих прогнозов и не было ли каких-то сюрпризов. Затем я попытаюсь предсказать, куда, как мне кажется, всё пойдёт в 2023 году.
Обзор 2022 года
В 2021 году Safari удивил меня тем, сколько работы понадобилось для сокращения отставания в поддержке WebAssembly по сравнению с другими браузерами. Итак, как дела у Safari за последний год?
Safari
В Safari продолжают улучшать поддержку WebAssembly, сделав несколько багфиксов и улучшений, но большая часть их работы, по-видимому, была направлена на улучшение других функций браузера. Хотя в прошлом году и не было реализовано каких-либо важных фич wasm, по сравнению с тем, что произошло годом ранее, многое происходит “под капотом”.
Так, например, в прошлогоднем прогнозе я предполагал, что SIMD с фиксированной шириной — это то, что Safari внедрит в 2022 году, и тем самым он будет поддержан во всех основных браузерах. К сожалению, SIMD с фиксированной шириной не появился в Safari в 2022 году, но теперь он завершён и является частью Technical Preview 161!
SIMD (Single Instruction, Multiple Data) — это тип параллельной обработки, который использует SIMD-инструкции ЦП для одновременного выполнения одной и той же операции над несколькими потоками данных. Этот процесс может привести к значительному повышению производительности в таких вещах, как обработка изображений. Поскольку существует несколько типов SIMD, в качестве отправной точки были выбраны 128-битные SIMD-операции фиксированной ширины.
Еще одна область, в которой Safari принял вызов в 2022 году, — это фича “хвостовые вызовы” (Tail Call), которая теперь также находится в Technical Preview 161. В течение некоторого времени она находилась за флагом в браузере Chrome и не могла продвигаться вперёд до фазы 4 спецификации (стандартизация). Чтобы спецификация перешла к этапу 4, по крайней мере две веб-VM должны поддерживать эту фичу, поэтому требовалась её реализация в другом браузере, в данном случае — Safari.
Хвостовые вызовы полезны для оптимизации компиляции и некоторых форм потока управления, таких как рекурсивные функции. В следующей статье объясняется, как хвостовые вызовы работают с рекурсивными функциями, чтобы предотвратить исчерпание стека: https://leaningtech.com/fantastic-tail-calls-and-how-to-implement-them
Обработка исключений
Chrome и Safari добавили поддержку обработки исключений WebAssembly в 2021 году, но к концу года над ней всё ещё работали в Firefox. В мае 2022 года Firefox завершил поддержку браузером этой функции, позволив модулям использовать исключения, не беспокоясь о снижении производительности или увеличении размера кода, которое появлялось при использовании JavaScript в качестве обходного пути.
Инструментарий быстро освоил эту фичу. В 2022 году .NET 7 и Uno Platform добавили поддержку обработки исключений WebAssembly, а также SIMD. В Uno даже пошли дальше и добавили экспериментальную поддержку многопоточности WebAssembly.
Множество блоков памяти
В настоящее время модули WebAssembly могут иметь только один блок памяти. Если модулю необходимо взаимодействовать с JavaScript или другим модулем, разрешая прямое чтение и запись в свою память, существует риск раскрытия или случайного повреждения информации. Данная фича позволит модулю иметь несколько блоков памяти, и модуль сможет делать такие вещи, как использование одного блока для внутренних данных, а другого блока – для обмена информацией. Здесь определён ряд других вариантов использования, если вы хотите узнать больше: https://github.com/WebAssembly/multi-memory/blob/main/proposals/multi-memory/Overview.md
Это была фича, на которую я надеялся в 2022 году, потому что я вижу много способов использования нескольких блоков памяти. К сожалению, я не вижу, чтобы кто-либо из производителей браузеров работал над этим в настоящее время.
Сборка мусора
Сборка мусора необходима для ряда управляемых языков (managed languages). Поскольку WebAssembly ещё не поддерживает сборку мусора, языки, которые в ней нуждаются, должны либо включать собственный сборщик мусора, либо компилировать свою среду выполнения в WebAssembly. Оба подхода приводят к увеличению объёма загрузки и увеличению времени запуска, особенно если модуль ещё не в кэше браузера.
Предложение по сборке мусора для WebAssembly было создано ещё в 2017 году, но до сих пор оно находится на этапе 1. В 2022 году я был приятно удивлён, увидев, что это предложение перешло на этап 2 в феврале, а затем на этап 3 в октябре!
Все производители браузеров встраивают поддержку, и уже предпринимаются усилия по адаптации компиляторов для нескольких языков, чтобы воспользоваться ею.
WebAssembly 2.0
Когда WebAssembly был выпущен в качестве MVP в 2017 году, было решено считать это версией 1.0. С тех пор ряд функций WebAssembly, таких, как упомянутое ранее предложение SIMD с фиксированной шириной, были стандартизированы.
В 2022 году была начата работа над версией 2.0 спецификации WebAssembly. По сути, это способ сказать, что если среда исполнения поддерживает WebAssembly 2.0, она поддерживает все стандартизированные фичи, которые являются ее частью.
Детали на следующей странице даны на довольно низком уровне, а список предложений, которые составляют изменения с версии 1.0, перечислены внизу: https://webassembly.github.io/spec/core/appendix/changes.html
Контейнеры и WebAssembly
Помимо предложений фич WebAssembly и их реализации, я считаю, что этот элемент значительно изменит правила игры: модули WebAssembly, которые могут запускаться вашим контейнерным движком и могут работать бок о бок с вашими существующими контейнерами!
Containerd — это среда исполнения контейнеров, которая используется несколькими механизмами контейнеров, такими как Docker и Kubernetes. Было внесено изменение, позволяющее containerd использовать прослойку для wasm, а затем эта прослойка использует среду исполнения wasm для запуска модулей WebAssembly.
Благодаря этому изменению вы сможете использовать существующую контейнерную инфраструктуру для запуска модулей WebAssembly. Модули wasm по умолчанию не имеют доступа к базовой системе, что обеспечивает дополнительную безопасность. Образы wasm также меньше по размеру и запускаются быстрее, чем традиционные образы. Ещё одно преимущество в том, что вы сможете использовать репозитории контейнеров, такие как Docker Hub, для публикации образов WebAssembly.
В следующей статье есть несколько примеров запуска wasm в Docker: https://docs.docker.com/desktop/wasm/
Microsoft также выпустила предварительную версию AKS, которая запускает WebAssembly: https://learn.microsoft.com/en-us/azure/aks/use-wasi-node-pools
JavaScript вне браузера
В течение многих лет над JavaScript было проделано много работы, чтобы сделать его действительно быстрым в браузере, и, подобно тому, как многие разработчики хотят, чтобы их языки работали и в браузере тоже, разработчики JavaScript хотят запускать свой код вне браузера.
Когда речь идет о таких вещах, как масштабные производительные вычисления, становится важно, как быстро запускается ваш код JavaScript. С изолятами V8 время запуска теперь находится в диапазоне миллисекунд, но проводятся эксперименты, чтобы увидеть, можно ли улучшить и это время.
The Bytecode Alliance (группа, работающая над системным интерфейсом WebAssembly или WASI) взяли механизм Firefox JavaScript — SpiderMonkey, и скомпилировали его в WASI. Затем они использовали хитрую технику, создав шаг сборки, который запускает код JavaScript, а затем делает снимок инициализированного байт-кода, хранящегося в линейной памяти. Этот моментальный снимок хранится в разделе данных модуля, и все эти предварительно инициализированные данные просто сбрасываются обратно в линейную память по мере надобности для движка, что значительно ускоряет время инициализации (0,36 миллисекунды или в 13 раз быстрее в их примере). Более подробную информацию об этом эксперименте можно найти здесь: https://bytecodealliance.org/articles/making-javascript-run-fast-on-webassembly
Механизм SpiderMonkey, доступный в виде модуля WASI, означает, что потенциально JavaScript может быть встроен в ещё большее количество систем и работать так же быстро, как в хорошо оптимизированном веб-браузере.
Ожидания от 2023 года
По состоянию на 12 января, SIMD с фиксированной шириной в Safari входит в состав Technology Preview 161. Это значит, что фича уже будет поддержана во всех основных браузерах, когда Safari 16.4 будет выпущен в течение следующих одного-двух месяцев.
Хвостовые вызовы (Tail Calls)
В выпуск Safari Technology Preview 161 также включена фича “хвостовые вызовы”. При этом спецификация хвостового вызова WebAssembly уже перешла к этапу 4.
В Chrome ждали перехода спецификации к фазе 4, прежде чем вывести хвостовые вызовы из-под флага. Теперь, когда эта фича сменила этапы, мы, вероятно, увидим выпуск хвостовых вызовов в Chrome и Edge в ближайшие месяцы.
Firefox работает над реализацией хвостовых вызовов и, надеюсь, выпустят поддержку в ближайшем будущем, с тем чтобы поддержка браузеров стала полной.
Сборка мусора
Теперь, когда предложение по сборке мусора достигло фазы 3, все производители браузеров работают над его поддержкой.
Также воодушевляет, что несколько языков программирования, таких как Java, Kotlin и Dart, уже работают над использованием этой новой возможности.
Я не уверен, что эта фича будет полностью поддержана браузерами в 2023 году, но как я вижу, некоторые её части выпускаются или, возможно, находятся под флагом, так что производители инструментария могут начать с этим играть.
WebAssembly и контейнеры
Теперь, когда поддержка WebAssembly Docker’ом находится в стадии бета, а такие поставщики, как Azure AKS, заботятся о предварительной поддержке, я думаю, что контейнеры помогут дать взрывной рост использованию wasm за пределами браузера. Возможность использовать уже существующую инфраструктуру и сервисы, а также возможность делиться образами WebAssembly в репозиториях, таких как Docker Hub, — это большие преимущества.
Другие возможные фичи в 2023 году
В разработке находится довольно много предложений по WebAssembly, и некоторые из них уже находятся в браузерах Chrome и Firefox под флагом, поэтому я думаю, что они имеют высокую вероятность выпуска в 2023 году. К ним относятся: Memory 64, Relaxed SIMD и Type reflection.
Предложение по интеграции промисов JavaScript кажется весьма полезным, когда модуль может продолжать создаваться для вызова функций синхронным образом, но браузер будет приостанавливать выполнение модуля, ожидая завершения асинхронного вызова. Более подробную информацию об этом предложении можно найти здесь: https://v8.dev/blog/jspi
Поддержка со стороны языков и инструментов
Благодаря тому, что многие из основных фич WebAssembly теперь кросс-браузерные, и к этому списку присоединяются более продвинутые фичи, такие как обработка исключений, хвостовые вызовы и сборка мусора, я думаю, мы увидим больше языков, ориентированных на WebAssembly, а также улучшение существующих инструментов.
Использование WebAssembly по-прежнему мало — около 2% пользователей Chrome, но его использование в вебе неуклонно растет. Даже 2% это довольно много, учитывая размер всего веба. Показатели использования можно найти здесь (установите флажок «Show all historical data»): https://chromestatus.com/metrics/feature/timeline/popularity/2237
Похоже, что WebAssembly широко применяется вне браузера, например, в таких областях, как бессерверные провайдеры и потоковые сервисы, такие как Disney и Amazon. Я надеюсь, что в 2023 году мы также будем чаще использовать WebAssembly в браузере.
В заключение
В 2022 году не было особого движения в отношении выпускаемых фич, но было ощущение, что многие вещи встали на свои места для того, что будет дальше.
Такие вещи, как хвостовые вызовы и сборка мусора, позволят языкам уменьшить размеры своих модулей и работать быстрее. В результате больше языков смогут быть ориентированы на WebAssembly.
Я верю, что возможность использовать WebAssembly параллельно с существующими контейнерами, а также совместное использование образов WebAssembly в репозиториях контейнеров поможет экосистеме ещё больше вырасти за пределами браузера.
Наконец, такие проекты, как компиляция SpiderMonkey в WASI, могут обеспечить ещё более быстрое выполнение JavaScript вне браузера и расширит количество мест, где может выполняться ваш код JavaScript.