Хабрахабр

[Перевод] Будущее WebAssembly в виде «дерева навыков»

Некоторые люди как-то неправильно поняли WebAssembly. Есть те, кто считает, что раз браузеры уже поддерживают выполнение WebAssembly (ещё с 2017 года), значит всё уже готово. Даже и близко ещё нет, готов лишь MVP (минимально жизнеспособный продукт). Я могу предположить откуда произрастает корень этого заблуждения: после релиза MVP его разработчики пообещали поддерживать обратную совместимость на уровне «любой написанный сейчас код будет работать и в будущем». Но это ведь не значит, что разработка WebAssembly закончена, совсем нет! Множество фич разрабатывается прямо сейчас и планируется к разработке в ближайшем будущем. И когда они будут реализованы — всё очень сильно изменится.

У нас есть пару «базовых» (уже реализованные фичи) и целое дерево со множеством веток и листьев, которые будут со временем открываться, давая нам всё больше и больше могущества.
image
Давайте посмотрим на то, что у нас уже есть сейчас и что нам ещё предстоит открыть.
(Под катом много картинок, трафик)
Все эти фичи можно попробовать представить себе в виде дерева навыков в какой-нибудь игре.

Минимально жизнеспособный продукт (MVP)

image
В самом начале истории создания WebAssembly стоит Emscripten, который дал возможность скомпилировать кода на С++ в код на JavaScript. Это позволило перенести в мир веба большое количество С++ библиотек, без которых был бы невозможен запуск более высокоуровневого кода. Генерируемый JS-код был далёк от идеала и работал медленно (по сравнению с его нативной версией). Но всё же инженеры из Mozilla нашли пару способов сделать его быстрее. Основным из них стало выделение подмножества языка, которое можно было бы выполнять на скоростях, сравнимых со скоростями выполнения нативного кода. Это подмножество назвали asm.js.

Но это не стало концом истории. Разработчики других браузеров заметили и оценили скорость asm.js, его поддержку получили все основные браузеры. Всё ещё оставались возможности работать быстрее. Это было лишь начало. Получалось, что нативный код (например, на С++) нужно было компилировать не в Javascript, а во что-то другое. Но они уже выходили за рамки Javascript. И вот так появился WebAssembly. Во что-то новое, созданное специально в качестве быстрой альтернативы JS.

Чего было достаточно для получения гордого звания «минимально жизнеспособного продукта»? Что же вошло в первую версию WebAssembly?

Навык: целевая платформа для компилятора

image

Задачей было дать возможность скомпилировать в WebAssembly код на любом языке. Программисты, работавшие над WebAssembly, понимали, что их задачей не является поддержка одного лишь С или С++. Но этот новый язык не должен полагаться на какую-то конкретную платформу, его целью должна быть абстрактная платформа более высокого уровня, конкретные реализации которой уже зависели бы от используемого на данном железе набора инструкций. Это должен был быть такой себе «ассемблер», который должен исполняться в браузере, так же как машинный код десктопного приложения исполняется, например, на платформе х86.

Навык: быстрое выполнение кода

image

А иначе зачем вообще затевать всю эту историю? Всё должно было работать быстро. В конце концов пользователь должен получить возможность запускать реально «тяжелые» приложения, иметь возможность играть в браузере в топовые игры и т.д.

Навык: компактность

image

Пользователи привыкли к декстопным приложениям, которые запускаются очень быстро (ведь они установлены локально и имеют под рукой все необходимые ресурсы). Важна не только скорость выполнения кода, но и скорость его загрузки. И это ставит перед нами новую задачу: если мы хотим создать веб-приложение нового типа, со столь большой кодовой базой, как классическое «десктопное», но загружаемое из Интернета — код должен быть компактен настолько, насколько это только возможно. Веб-приложения тоже запускаются относительно быстро, поскольку не загружают так много ресурсов сразу.

Навык: доступ к памяти

image

Нужен прямой доступ к блокам памяти. Нашим новым приложениям также понадобится работать с памятью несколько иначе, чем это делает JavaScript-код. Указатель — это, грубо говоря, переменная, которая содержит в себе адрес в памяти. Это обусловлено особенностью работы языков С и С++, в которых есть указатели. Огромное количество кода на С/С++ использует указатели для повышения эффективности своей работы, создание целевой платформы для подобного кода невозможно без поддержки указателей. Приложение может прочитать данные по этому адресу, изменить их и даже использовать арифметику указателю, чтобы «прогуляться» по памяти вперёд от указанного адреса.

Нам придётся создать такое окружение, которое с одной стороны позволит нативному коду, скомпилированному в WebAssembly верить, что он имеет прямой доступ к памяти, но с другой — жестко ограничить ту область, в которой ему разрешено манипулировать данными. Но мы не можем позволить какому-то там скачанному из интернета куску кода иметь прямой доступ к памяти нашего процесса — это слишком опасно.

Это реализовано с использованием TypedArrays — что-то вроде массива в JavaScript, но содержащего только последовательный набор байт в памяти. Для это в WebAssembly используется «линейная модель памяти». Таким образом данный массив «прикидывается» блоком памяти для С++ кода. Когда вы хотите что-то в него поместить, то используете доступ к элементу по индексу (в качестве которого может выступать адрес в памяти).

Новое достижение!

Итак, со всем вышеперечисленным люди наконец смогут запустить десктопное приложение в браузере с примерно той же производительностью, как если бы оно было нативным. Вот примерно этот набор фич и был назван «минимально жизнеспособным продуктом» (MVP).

image

Но впереди оставался ещё длинный путь. На этом этапе некоторые приложения действительно уже могли быть собранными под WebAssembly и заработать в браузере.

Тяжеловесные десктопные приложения

image

Вы уже представляете полную версию Photoshop, работающую в браузере? Следующим важным шагом должна стать возможность запуска действительно больших десктопных приложений. И вы не устанавливали её, просто открыли ссылку — и вот уже перед вами вся на 100% мощь данного продукта, на нативной скорости, последняя версия со всеми обновлениями и исправлениями, на любом устройстве.

Например, AutoCAD. И мы не так далеко от этого — примеры уже начинают появляться. Но будем откровенны — не всё ещё готово в текущей реализации WebAssembly для запуска по-настоящему больших приложений. А ещё Adobe Lightroom. Узкие места исследуются и исправляются прямо вот в этот момент, когда вы читаете данную статью.

Навык: многопоточность

image

У современных компьютеров много ядер. Очевидно, что нам нужна многопоточность. Нам нужно иметь возможность их задействовать.

Навык: SIMD

image

Это SIMD: обработка одной инструкцией сразу нескольких блоков данных. Помимо многопоточности есть ещё одна технология, позволяющая более эффективно реализовать параллельную обработку данных. Важный аспект, необходимый для действительно быстрой работы WebAssembly.

Навык: 64-битная адресация

image

Тут всё просто: с 32-битными адресами вы можете использовать лишь 4 Гб памяти (что очень мало для больших программ), а вот с 64-битными — уже до 16 экзабайт (это очень много для современного ПО). Ещё одна важная возможность современной аппаратной архитектуры, которой пока нет в WebAssembly — поддержка 64-битной адресации памяти. Но на большинстве современных устройств уже 4 или больше Гб оперативной памяти и это число будет расти. Конечно, важен не только теоретический максимум, но и практический (сколько памяти вам выдаст ОС).

Навык: потоковая компиляция

image

Нам также нужно уменьшить промежуток времени между началом его загрузки по сети и его стартом. Нам нужно не только быстро выполнять приложения. Мы разбираем инструкции по ходу того, как они загружаются по сети. Потоковая компиляция позволяет начать обработку WebAssembly-файла ещё до его окончательной загрузки. В коде Firefox нам удалось добиться скорости компиляции выше скорости загрузки — то есть время обработки какого-то кода размером N байт получилось меньше, чем время загрузки этого кода по сети. Таким образом загрузка и компиляция идут параллельно. Разработчики других браузеров также работают над потоковой компиляцией.

image

Один из них (вышеописанный) работает быстро и позволяет немедленно запустить скачанный код. Связанная с потоковой компиляцией вещь — это использования двух компиляторов. Такие оптимизации выполняет другой, работающий в фоне компилятор. Он, однако, не выполняет всех теоретически возможных его оптимизаций, поскольку это требует больше времени. Как только он закончит свою работу — одна версия в памяти подменяет другую и дальше работает вместо неё.

Так мы получаем и быстрый старт приложения, и его эффективную работу.

Навык: кэширование

image

Скомпилированный код может (и должен) быть закэширован и затем использован из кэша. Если мы уже однажды скачали и скомпилировали оптимизирующим компилятором какой-то WebAssembly код, то не имеет смысла делать то же самое при загрузке этого кода в другой вкладке (или при следующем открытии браузера при условии неизменности приложения).

Навык: другие улучшения

image

Что-то точно будет реализовано, что-то не сразу, что-то совсем не будет. Сейчас идёт много дискуссий о том, какие ещё улучшения возможны и на чём должны быть сфокусированы усилия разработчиков. Я, с вашего позволения, определю все эти пункты в общий класс «другие улучшения», а что в него войдёт — мы поймём со временем.

Где мы сейчас?

Примерно где-то здесь:

image

Многопоточность

Для многопоточности у нас есть почти готовый план, но одна из его ключевых частей (SharedArrayBuffers) была вынужденно отключена в начале этого года. Она скоро будет включена снова и мы сможем продолжить.

SIMD

Активно разрабатывается прямо сейчас.

64-битная адресация

Для wasm-64 у нас есть достаточно чёткое представление о том, как всё должно работать. Мы основывались на подходах архитектур x86 и ARM.

Потоковая компиляция

В Firefox она была добавлена ещё в 2017 году, другие браузеры работают над этим.

Использование двух компиляторов

В Firefox это было добавлено ещё в 2017 году, а в другие браузеры — в 2018.

Implicit HTTP caching

В Firefox разработка почти закончена, скоро будет релиз.

Другие улучшения

Идёт обсуждение

И тем ни менее, мы уже сегодня можем увидеть приложения, работающие на WebAssembly, поскольку и сегодняшних возможностей для кого-то уже достаточно. Как вы можете заметить — большинство пунктов ещё в стадии активной разработки. Как только все вышеуказанные фичи будут готовы — мы откроем ещё одно «новое достижение» и ещё больше новых приложений получит поддержку WebAssembly.

image

Взаимодействие с Javascript

image

Он может быть использован и для обычной веб-разработки. WebAssembly создавался не только как платформа для игр и тяжеловесных приложений. Важный момент здесь в том, что это и не нужно. Мы осознаём, что на сегодняшний день существую очень большие веб-приложения, написанный на Javascript и мало кто решится взять и полностью переписать их на WebAssembly. Мы хотим дать разработчикам возможность переписать лишь эти «узкие» места на WebAssembly, оставив остальной код на привычном JS. Скорее всего большая часть этих приложений работает достаточно хорошо и лишь в некоторых узких местах, возможно, ощущается недостаток производительности в рассчётах, или пропускной способности обработки данных, или недостатке функционала из-за отсутствия JS-версии какой-то библиотеки. Например, переписав парсер Gutenberg на Rust и собрав его под WebAssebly удалось достичь прироста производительности в 86 раз. И это уже возможно.

Но, чтобы сделать подобную практику массовой и удобной, нам нужно реализовать кое-что ещё.

Навык: быстрые вызовы между JS и WebAssembly

image

Добавив небольшой WebAssembly-модуль, программист не должен ощутить потери производительности, даже если этот модуль будет вызываться очень часто. Вызов WebAssembly из JS должен работать очень быстро. Данную проблему ещё предстоит исправить. В MVP это не так (поскольку целью MVP не была максимальная производительность подобных вызовов). Разработчики других браузеров тоже работают над этой задачей. В Firefox мы уже добились того, что некоторые вызовы JS->WebAssembly уже работают быстрее неинлайновых вызовов JS->JS.

Навык: быстрый обмен данными

image

С этим есть определённые проблемы. Эта задача связана с предыдущей: важно не только быстро вызвать WebAssembly-код из JS, но и быстро передать данные между ними. В нём нет объектов, а вот в JS они есть. Например, тот факт, что WebAssembly понимает только цифры. Он уже существует, но ещё недостаточно производителен. Получается, нам нужен какой-то слой трансляции.

Навык: интеграция с ES-модулями

image

Но это означает, что WebAssembly-модуль на самом деле не является частью графа JS-модулей веб-приложения. Сейчас использование WebAssembly-модуля выглядит как вызов специального API, который вернёт вам модуль для использования. Чтобы иметь все доступные ES-модулям функции (вроде экспорта и импорта) WebAssembly-модуль должен уметь интегрироваться с ES-модулями.

Навык: интеграция в разработку

image

Нам нужно место, где WebAssembly-модули могли бы распространяться. Просто иметь возможность импорта и экспорта — ещё не значит стать полнофункциональным модулем. Хм… как на счёт самого npm? Что будет аналогом npm для WebAssembly? Хм… как на счёт webpack и Parcel? А что будет аналогом webpack или Parcel для WebAssembly?

Но нам нужны инструменты для их интеграции в эту инфраструктуру. WebAssembly-модули не должны отличаться от обычных модулей, а значит они могут распространяться через ту же самую инфраструктуру.

Навык: обратная совместимость

image

Всё должно хорошо работать даже в старых версиях браузеров. Есть ещё одна важная вещь, которую мы должны обеспечить. Мы должны дать гарантию того, что, написав один раз код под WebAssembly, разработчику не придётся писать вторую версию того самого кода на Javascript просто потому, что сайт должен открываться и в IE11 тоже. Даже в тех, которые понятия не имеют о WebAssembly.

Где мы сейчас?

Где-то вот здесь:
image

Быстрые вызовы между JS и WebAssembly

Уже реализовано в Firefox, идёт работа в других браузерах.

Быстрый обмен данными

Есть несколько предложений. Например, расширить систему типов в WebAssembly ссылками на JS-объекты. Это возможно, но вызовет необходимость написания дополнительного кода (например, для вызова JS-методов), что работает не слишком быстро. Для решения этой проблемы, в свою очередь, тоже есть несколько предложений.

Это касается отслеживания того, как долго данные могут храниться в памяти. Есть и ещё один аспект, касающийся обмена данными. Но если вы оставите их там навечно — то мы получим утечку памяти. Если у вас есть какие-то данные в памяти, к которым должен иметь доступ JS-код, то вы должны оставить их там до того момента, как JS-код их прочтёт. На сегодняшний день эта ответственность возлагается на программиста — всё освобождается вручную. Как узнать, что данные уже можно удалять (JS-код их уже прочёл)? Но этот подход морально устарел и часто приводит к ошибкам. Как только JS-код закончил чтение данных, он должен вызвать что-то типа функции «free». Это даёт возможность читать данные на стороне JS-кода, а когда сработает сборщик мусора — произвести корректную очистку памяти в WebAssembly-модуле. Для решения данной проблемы мы ввели понятие WeakRef в Javascript.

А тем временем в экосистеме Rust были созданы инструменты, которые автоматизируют написание подобного кода для вас, заменяя пока не реализованные части собственной их реализацией. Всё это ещё в разработке. Он называется wasm-bindgen. Один из этих инструментов заслуживает отдельного упоминания. А ещё эта прослойка способна взаимодействовать и с WebAssembly модулем, написанном на любом другом языке, так что не только программисты на Rust могут использовать данный инструмент. Когда он замечает, что ваш код на Rust пытается получить или вернуть JS-объекты или DOM-объекты — он автоматически создаёт JS-прослойку, которая будет способна взаимодействовать с вашим Rust-кодом.

Интеграция с ES-модулями

План работ по данному направлению существует уже достаточно давно. Мы активно работаем над ним совместно с разработчиками других браузеров.

Интеграция в разработку

Уже сейчас существуют инструменты вроде wasm-pack в экосистеме Rust, позволяющие автоматически упаковать всё необходимое для релиза в npm. И есть люди, использующие этот инструмент для создания своих модулей.

Обратная совместимость

Для обратной совместимости у нас есть инструмент wasm2js. Он позволяет превратить wasm-файл в эквивалентный JS-файл. Этот Javascript-код не будет быстрым, но он будет работать на любом браузере (в том числе, не поддерживающем WebAssembly).

И как только мы сделаем это, откроется путь к ещё двум.
image Как видите, мы очень близки к получению данного «достижения».

JS-фреймворки и компилируемые в JS языки

Первый из них это возможность переписать популярные тяжеловесные JS-фреймворки на WebAssebly.

image

Речь идёт о языках вроде Scala.js, Reason, Elm. Второй — дать возможность языкам программирования, компилирующимся в Javascript, заменить его на WebAssembly.

image

Для обоих этих задач WebAssembly должен поддерживать рядо новых высокоуровневых фич.

Навык: сборщик мусора

image

Во-первых, вспомним о задаче переписывания JS-фреймворков (или их частей). Нам нужна интеграция с браузерным сборщиком мусора по целому ряду причин. Например, в React у нас есть алгоритм сравнения DOM-деревьев, который можно переписать на Rust с эффективной многопоточностью. Это может понадобиться. В виртуальном DOM вместо создания множества небольших объектов, которые потом сборщику мусора нужно будет отслеживать и удалять, можно было бы использовать специальную схему выделения памяти. Также мы можем ускорить кое-что лучше выделяя и освобождая память. Это одновременно и ускорит выполнение кода, и сэкономит память. Например, выделить сразу блок памяти, разместить в нём все объекты, а затем удалить его одним вызовом.

Вы не можете просто копировать данные туда-сюда постоянно, это будет неэффективно. Но нам также придётся постоянно взаимодействовать с JS-кодом. Некоторые JS-объекты должны будут ссылаться на блоки линейной памяти созданные в WebAssembly-модулях, и некоторые блоки линейной памяти будут хранить в себе ссылки на JS-объекты. А значит нужна возможность интеграции с работающем в браузере сборщиком мусора, чтобы получить возможность работы с объектами, время жизни которых определяется виртуальной машиной Javascript.

Он не сможет определить, что ещё используется, а что уже нет. Если при этом будут создаваться циклы (а они будут), то это создаст проблемы для сборщика мусора. WebAssembly нужна более тесная интеграция со сборщиком мусора браузера, чтобы избежать этого.

Если и WebAssembly и будет использовать его же — значит код на этих языках сможет быть собран под WebAssembly и не должен заметить никакой разницы в плане нюансов работы сборщика мусора (он будет попросту тот же). Это также поможет таким языкам как Scala.js, Reason, Kotlin и Elm — они могут компилироваться в Javascript, а значит используют при этом его сборщик мусора.

Навык: обработка исключений

image

Да, некоторые языки, вроде Rust, не используют исключения. Нам нужна обработка исключений. На данный момент вы можете подменить обработку исключений кодом без исключений — но работает это медленно. Но многие другие — используют. Таким образом сейчас при разработке под WebAssembly лучше не использовать исключения изначально.

Даже если вы в своём коде их не используете — какая-нибудь стандартная функция может его выбросить и с этим нужно будет что-то делать. Кроме того, исключения есть в Javascript. Код на Rust, например, при этом просто аварийно завершится. Если ваш WebAssembly-код вызовет JS-код, а тот бросит исключение — мы не сможем его корректно обработать. Это нужно изменить, нам нужен нормально работающий сценарий обработки исключений.

Навык: отладка

image

Все современные браузеры имеют инструментарий для удобного анализа Javascript-кода. Ещё одна вещь, к которой привыкли JS-разработчики, это хорошие инструменты отладки. Нам нужен тот же уровень поддержки и для WebAssembly.

Навык: хвостовые вызовы

image

Я не буду углубляться в эту тему, несколько упрощая можно сказать что хвостовой вызов — это способ в некоторых случаях вызвать функцию без выделения для неё фрейма в стеке. Для поддержки функциональных языков нам понадобиться вещь, которая называется "хвостовые вызовы". Поскольку данная возможность является критически важной для функциональных языков, мы хотим иметь её поддержку и в WebAssembly.

Где мы сейчас?

Где-то вот здесь:

image

Сборка мусора

Для реализации сборки мусора в данный момент идёт работа в двух направлениях: это Typed Objects для JS и, собственно, сборщик мусора для WebAssembly. Typed Objects позволит описать чёткую структуру объекта. Уже есть виденье того, как это должно работать, и оно будет обсуждаться на предстоящем собрании ТС39. Соответственно, GC для WebAssembly будет способен получить доступ к вышеупомянутой структуре для своих целей. Над его реализацией уже идёт работа.

У нас уже есть работающий прототип. Как только обе части будут закончены, мы получим систему из взаимодействующих JS и WebAssembly, способную понимать на всех уровнях из чего состоит объект и эффективно использовать его внутренние данные. Мы рассчитываем что дело дойдёт до релиза где-то в 2019-ом году. Прототип, однако, нельзя просто взять и релизнуть — нам предстоит потратить какое-то время на стандартизацию и правки.

Обработка исключений

Работа над исключениями сейчас на стадии исследования и разработки. Мы рассматриваем различные предложения, пробуем их реализовать, смотрим насколько эффективно они работают.

Отладка

Для отладки уже сейчас есть некоторая поддержка в инструментах разработчика Firefox. Но до идеала ещё далеко. Мы хотим показать разработчику его исходный код и текущую позицию в нём, а не просто ассемблерные инструкции. Нам предстоит разработать и внедрить поддержку символьных файлов, которые позволят соотнести каждую инструкцию кода со строкой исходников. Прямо сейчас идёт работа над спецификацией данного механизма.

Хвостовые вызовы

Идёт работа.

Когда всё вышеуказанное будет закончено — мы можем считать, что получили достижение «JS-фреймворки и компилируемые в JS языки»

image

Что на счёт происходящего вне браузера? Итак, это был план получения «ачивок» в браузере.

Вне браузера

Возможно, вас смутило само сочетание слов «вне браузера». Неужели у нас есть что-то кроме браузера, когда мы говорим о вебе? А ведь «веб» у нас прямо в названии «WebAssembly». Но на самом деле HTML, CSS и JavaScript — лишь вершина айсберга.

image

Но есть и ещё одна очень важная часть веба — это связи. Да, они видимы лучше всего, ведь именно ими формируется пользовательский интерфейс. Связи всего со всем.

image

Мне не нужно ваше или чьё-то ещё разрешение. Я могу сделать ссылку на вашу страницу прямо сейчас. Кто-угодно сможет перейти по ней — и будет показан ваш контент, запустится написанный вами код. Я просто делаю эту ссылку, добавляю её себе на сайт. Сейчас у нас есть социальные сети и другие сайты, которые, по сути, расширяют понятие «ссылки» возможностью стыковать что-угодно: людей, устройства, бизнесы и т.д. Эта простота создания связей и перехода по ним и создала наш Интернет таким, какой он есть.

Но со всеми этими ссылками и связями есть две проблемы.

Если вы переходите куда-то и сайт предлагает вам некоторый код, который должен быть выполнен в вашем браузере — этот код должен быть кроссплатформенным. Во-первых, на что должна вести ссылка? Везде. Он должен скомпилироваться во что-то и запуститься на маке, на Windows, на андроиде. Портируемость загружаемого кода — важная часть концепции связанности веба.

image

Нужно понимать, что мы ничего не знаем об этом коде. Но просто скачать и запустить код мало. Вдруг это вредоносный код? Мы не доверяем ему настолько, чтобы отдать полный контроль над компьютером пользователя. И вот здесь нам становится нужна какая-то модель безопасности. Он может сделать что-то плохое. Нам нужна песочница, куда можно будет поместить незнакомый код, дать ему кое-какие контролируемые инструменты для работы, но убрать подальше от него всё критически важное и небезопасное.

image

Мы знаем, что точно сможем запустить код и что он точно нам не навредит. Итак, два аспекта понятия «связи»: портируемость и безопасность. Потому что такой подход в корне меняет взгляд на то, чем является WebAssembly. Почему я настаиваю на этих понятиях и чем такой взгляд на вещи отличается от взгляда на веб как на совокупность HTML, CSS и Javascript?

И это так. С одной стороны, можно думать о WebAssembly как о «ещё одном инструменте, доступном в современном браузере».

image

Но портируемость и безопасность выполнения кода открывают перед нами и другие двери.

image

Node.js

image

Принеся портируемость. Как WebAssembly может помочь Node?

Но всё же есть много случаев, когда производительности JS-кода недостаточно или просто пока не написан нужный JS-код, но есть его нативная версия. Node обеспечивает достаточно большой уровень портируемости тем, что использует Javascript. Они пишутся на языках вроде С и их нужно компилировать для той конкретной платформы, на которой бежит ваша Node. И тогда Node использует нативные модули.

Оба подхода возможны, но это всего лишь выбор из двух зол: либо лишняя головная боль пользователя, либо автора модуля. Нативные модули могут либо компилироваться при установке, либо можно взять сразу готовые под одну из популярных платформ.

Портируемость позволит запустить их на любой платформе, сразу, как Javascript-код. Если представить себе, что данные модули будут на WebAssembly, то их не нужно будет компилировать вообще. Но работать они будут с производительностью нативных версий.

Вы можете перенести Node-приложение с Linux на Windows — и всё продолжит работать без какой-либо перекомпиляции. И вот в мир Node приходит счастье в виде полной портируемости всего и везде. Но нативные (и даже ненативные) модули Node не работают в песочнице, они имеют доступ ко всему — такова идеология Node. Но при этом WebAssembly-модуль не имеет доступа к системным ресурсам (он работает в своей песочнице). Что-то типа POSIX-функций (не обязательно именно они, приведено лишь в качестве примера относительно стабильного и достаточного интерфейса доступа к ресурсам). Таким образом, чтобы WebAssembly-модуль получил те же возможности — понадобиться дополнительный слой доступа к ресурсам ОС.

Навык: портабельный интерфейс

image

Какой-то интерфейс доступа к его функциям. Итак, что же понадобиться Node-разработчикам для использования WebAssembly-модулей? Ну, чтобы не только Node могла вызывать эти функции, но и вообще кто-угодно. Хорошо бы его стандартизировать. Что-то типа «POSIX для WebAssembly». Захотели использовать WebAssembly-модуль в своём приложении — подключили и используем. PWSIX (portable WebAssembly system interface)?

Где мы сейчас?

Есть документ, описывающий механизм предоставления пути к модулю по его имени. Это, вероятно, будет использовано и браузерами и Nodе (они смогут предоставлять разные пути). Пока активной разработки не ведётся, но идёт много обсуждений.

image

Это хорошо, поскольку открывает нам ряд возможностей.
image Скорее всего это будет реализовано в каком-то виде.

CDN, Serverless, и Edge Computing

image

Случаи, когда вы кладёте свой код на чужой сервер, который заботится о его доступности для клиентов. Примерами могут быть такие вещи, как CDN, Serverless, Edge Computing. Недавно был отличный доклад на эту тему. Зачем здесь может понадобиться WebAssembly? Этот код нужно изолировать друг от друга и от ОС. Если вкратце — то бывает необходимость в рамках одного процесса запускать код из разных (не доверяющих друг другу) источников. А WebAssembly — даёт. Решения типа виртуальной машины JS (SpiderMonkey или V8) кое-как работают, но не дают нужной производительности и масштабируемости.

Что же нужно, чтобы заставить это работать?

Навык: среда выполнения

image

У нас уже есть компиляторы WebAssembly (типа Cranelift) — они быстрые и эффективно используют память. Нужна среда выполнения и некоторые компании создают свою собственную. Сейчас некоторые компании, типа Fastly, пишут эту среду выполнения самостоятельно. Но сгенерированный им код не может жить в вакууме — ему нужно на что-то опираться, как-то взаимодействовать с окружающей средой. Мы могли бы сделать это один раз, добавить в стандарт — и сэкономить всем кучу ресурсов. Но это не очень хороший подход — ведь это понадобиться многим компаниям и они будут делать одну и ту же работу, снова и снова.

Где мы сейчас?

Где-то вот здесь:
image

Что не мешает уже существовать и работать нескольким независимым средам выполнения, уже используемым в реальных проектах. Стандарта среды выполнения пока нет. Например, WAVM и wasmjit.

И как только у нас будет что-то стандартизированное и работающее, это открое возможность разработки целого ряда вещей, таких, например, как… Мы также планируем выпустить среду выполнения, построенную поверх Cranelift, она будет называться wasmtime.

Портируемые утилиты командной строки

image

Не будем говорить о ядре (хотя есть смельчаки, которые замахиваются и на это), но WebAssembly-код вполне может работать в пользовательском режиме. WebAssembly может использоваться не только в браузере, но и в традиционных операционных системах. И это даёт возможность создать утилиты командной строки, которые, будучи однажды собранными, заработают гарантированно одинаково под любой ОС.

Интернет вещей

image

Ограничения по доступным процессорным ресурсам и оперативной памяти негативно сказываются на возможности запускать там JS-код, но вот WebAssembly — совсем другое дело. Под «интернетом вещей» обычно имеют в виду маломощные устройства (вроде носимых или различных датчиков/контроллеров в «умных домах»). В абсолютно крайних случаях WebAssembly даже даёт возможность скомпилировать свой модуль в нативный бинарник целевой платформы. Оптимизирующие компиляторы вроде Cranelift и среда выполнения вроде wasmtime будут сиять в подобных условиях, ведь они как-раз писались для задач экономии ресурсов. С WebAssembly вам можно будет об этом не беспокоиться — разработанный код запустится везде. Ну и опять же портируемость — всех этих IoT-устройств сегодня очень много и построены они на разных платформах.

Выводы

Давайте отмотаем немного назад и снова взглянем на наше «дерево навыков».
image

Как вы можете теперь понять — его путь едва начат. Я начал эту статью с того, что некоторые люди не понимают почему WebAssembly ещё не закончен. Мы уже можем что-то скомпилировать в WebAssembly и запустить это в браузере. Да, MVP уже открывает некоторые возможности. Когда всё это будет готово — мы увидим новый веб. Но впереди ещё много работы — поддержка всего необходимого тяжелым приложениям и высокоуровневым языкам, замена JS-фреймворков и все эти вещи «вне браузера», о которых я говорил. Больше не будет такого типа ПО, который нельзя будет написать для выполнения в браузере: игры, блокчейн, интернет вещей, утилиты командной строки — запустится всё. Высокопроизводительный, более масштабный, более портируемый.

Он только начат. WebAssembly не закончен.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть