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

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

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


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

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

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

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


image

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

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


image

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

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


image

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

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


image

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

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

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

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


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

image

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

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


image

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

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

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


image

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

Навык: SIMD


image

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

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


image

Ещё одна важная возможность современной аппаратной архитектуры, которой пока нет в WebAssembly — поддержка 64-битной адресации памяти. Тут всё просто: с 32-битными адресами вы можете использовать лишь 4 Гб памяти (что очень мало для больших программ), а вот с 64-битными — уже до 16 экзабайт (это очень много для современного ПО). Конечно, важен не только теоретический максимум, но и практический (сколько памяти вам выдаст ОС). Но на большинстве современных устройств уже 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. Важный момент здесь в том, что это и не нужно. Скорее всего большая часть этих приложений работает достаточно хорошо и лишь в некоторых узких местах, возможно, ощущается недостаток производительности в рассчётах, или пропускной способности обработки данных, или недостатке функционала из-за отсутствия JS-версии какой-то библиотеки. Мы хотим дать разработчикам возможность переписать лишь эти «узкие» места на WebAssembly, оставив остальной код на привычном JS. И это уже возможно. Например, переписав парсер Gutenberg на Rust и собрав его под WebAssebly удалось достичь прироста производительности в 86 раз.

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

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


image

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

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


image

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

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


image

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

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


image

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

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

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


image

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

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


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

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


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

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


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

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

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

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


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

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


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

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


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

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

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


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

image

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

image

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

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


image

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

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

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

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

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


image

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

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

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


image

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

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

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

image

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

image

Node.js


image

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

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

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

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

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

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


image

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

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


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

image

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

CDN, Serverless, и Edge Computing


image

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

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

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


image

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

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


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

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

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

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


image

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

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


image

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

Выводы


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

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

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

Комментарии (57)


  1. Filippok
    31.10.2018 15:03
    -1

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

    Нет. Не нужно все это в браузере. Браузер нужен для просмотра html документов, не более. Хватит уже тащить все в браузер и браузер во все.


    1. nochnoy
      31.10.2018 15:25

      Не хватит. Приложения-которые-надо-скачивать-и-устанавливать-а-потом-обновлять до сих пор не вымерли только потому что веб не мог с ними соревноваться по скорости. Когда WA взлетит — вымрут. И туда им и дорога.


      1. Filippok
        31.10.2018 15:58
        +1

        Ну так может прямо в браузер будем загружаться? Кому вообще нужна ОС когда есть всемогущий браузер?


        1. nochnoy
          31.10.2018 16:11

          Так оно и будет, когда все приложения станут жить в браузере


          1. Filippok
            31.10.2018 16:29
            -2

            Надеюсь, что такое не случится никогда.


            1. rusbaron
              01.11.2018 10:11

              Согласен. И тут дело даже не в удобстве, если приложения будут не локально, то можно устроить допустим гос. регулирование какие приложения могут использовать а какие нет. Так себе перспективка.
              И я скорее против переноса всего в браузер. Некоторые вещи конечно удобно иметь в браузере, как было с квейк лайв по началу. Или IDE в браузере(они есть, но не все удобные)


        1. Foror
          31.10.2018 16:11

          прямо в браузер будем загружаться?
          Уже, гуглите ChromeOS


      1. 0serg
        31.10.2018 17:43
        +1

        Не только по скорости, еще по памяти. И WA всегда будет там проигрывать и проигрывать сильно. Топовые игры где достигается лишь 50% fps и требуется 32 Гб оперативки? Ну-ну, удачи в продажах веб-версии. Причем поверх всего этого всего всегда будет еще висеть вопрос «а что будет если не будет соединения с интернетом или оно будет стоить 100500$ за Гб». Который для меня, например, как пользователя довольно существенен.

        Ну и в целом концепция, как ни крути, все-таки порочна. По сути-то это «jvm + принудительное автообновление» только реализованное в веб-браузере. И нафига тут нужен именно веб-браузер не вполне понятно.


        1. Alexey2005
          31.10.2018 17:59
          +2

          Нужен не браузер. Нужна кроссплатформенность, которую он даёт.
          Пока свыше 90% пользовательских устройств работало на винде, на все эти VM смотрели с усмешкой. Но вот когда возникла задача обеспечить рендеринг GUI на множестве принципиально различных устройств и окружений, вот тут без слоя абстракции в виде VM уже никуда. Потому что фрагментация просто охрененно замедляет и удорожает разработку нативного кода.
          Например, если я хочу писать код под iOS, но при этом сидеть на Linux, браузер — единственный уверенно и без танцев с бубном работающий вариант.
          Если когда-нибудь удастся установить новую монополию, чтоб подавляющее большинство устройств работало под одной-единственной ОС, то все эти VM вновь станут оверхедом.


          1. 0serg
            31.10.2018 19:38

            Да делали уже эту кроссплатформенность и не один раз. Я потому JVM собственно и упомянул. И он не один — тот же Qt к примеру вроде бы позволяет «писать код под iOS но при этом сидеть на Linux». Свои танцы с бубном там будут, но не больше чем с зоопарком веб-браузеров.


            1. ankh1989
              01.11.2018 07:39

              Писать код под Qt мучительно сложно по сравнению с тем же реактом.


              1. 0serg
                01.11.2018 10:59

                Зато Qt работает в 10 раз быстрее, если не в 100 и поддерживать код в нем проще


                1. tangro Автор
                  01.11.2018 12:05

                  А теперь будет WebAssembly, который будет кроссплатформенный как react и быстрый, как Qt. Неужели плохо?


            1. YemSalat
              01.11.2018 14:47

              Свои танцы с бубном там будут, но не больше чем с зоопарком веб-браузеров.

              «Зоопарк веб-браузеров» сейчас гораздо менее актуальная проблема. Тем более в контексте js-приложений для телефонов/десктопов.


      1. Fedcomp
        01.11.2018 01:11

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


    1. Balek
      31.10.2018 18:37

      Как же надоело это зашоренное нытьё.
      Веб-приложения решают три проблемы: переносимость, изоляция (sandboxing) и деплой.
      1. Да, переносимости можно было бы добиться с любым языком программирования.
      2. Для изоляции найдутся какие-то решения. В мобильных ОС она есть, например.
      3. Доставка и автоматические обновления — киллер фича веба. Опять же, в мобильных ОС эта задача решена чуть лучше, но этого всё равно недостаточно. С точки зрения простых пользователей процедура установки — бессмысленное действие. Где грань между программами, которые могут встраиваться в «html документы» и которые требуют установки? Для кредитного калькулятора банка, например, нужно делать установку или нет? А зачем тогда нужно делать какие-то специальные манипуляции, прежде чем поиграть в игру или отретушировать фотографию? Зачем эта сложность простым пользователям? Веб образует единое пространство для работы с компьютером. Потому что разница между страничкой из трёх html-тегов и AutoCAD — условна как для пользователя, так и для разработчика.

      Неужели не очевидно, что все эти проблемы разбухающего и тормозящего веба вызваны переходным периодом? Как раз WebAssembly на это прямо указывает. Он сокращает разницу между вебом и нативными приложениями. А когда веб вытеснит всё, что мешает превратить веб в нейтив? Заточить процессоры под WebAssembly, а операционные системы переделать в браузер. И слава богу, что во всём сегодняшнем зоопарке технологий появляется абсолютно доминирующая высокоуровневая платформа для приложений. Потому что, если такой платформы не будет, то нужно сохранять совместимость на уровне ниже — придётся тащить x86 до бесконечности.


      1. boblenin
        01.11.2018 03:52

        Ну в целом установка всегда была своего рода оптимизацией канала передачи данных. Пока данные передвигались со скоростью грузовика, груженного 5 дюймовыми дискетами — выгоднее было держать бинарники и ресурсы локально. Потом скорость передачи данных выросла достаточно, чтобы можно было приложению находится на удаленной машине, а клиенту получать описание интерфейса и передавать события. Теперь благодаря усилиям JS разработчиков приложения становятся достаточно тяжелыми, чтобы приходилось уже ощутимое время ждать загрузки, но по сути до сих пор каждый раз когда мы запускаем JS приложение — оно вполне может полностью обновиться. Подождем еще немного — и electron наконец-то будет собран в webassembly и тогда опять придется приложения кэшировать (предустанавливать) на клиенте.


      1. vikarti
        01.11.2018 08:13

        а операционные системы переделать в браузер.

        Уже. Chromebook'и более менее успешно продаются. Хотя с точки зрения пользователя — там именно один браузер и есть (в новых версиях правда добавили поддержку Android).


      1. Balek
        01.11.2018 10:00

        Filippok, извините за мой тон. Не нужно было пускаться в оскорбления. В последнее время перечитал наездов на JavaScript, Electron и прочее.) Мне кажется эта критика очень недальновидной. Да, сегодня кажется, что веб не предназначен для создания приложений. Но в будущем всё поменяется.

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


  1. kovserg
    31.10.2018 19:05
    +2

    Уже были java-aplets, flash теперь webassembly. Очередная попытка отвязаться от windows. Всегда рассказывают как хорошо и замечательно будет, но не очень про то нафига оно вообще.
    Безопасность, песочница это конечно здорово но где механизмы лимитирования вычислительных ресурсов, памяти и потребляемой энергии. Реклама на flash-е умудрялось останавливать любую машину.
    С нетерпением ждём windows10 на webassembly


    1. Halt
      31.10.2018 20:51

      Рекомендую почитать статью Стива Клабника, где в том числе разбирается и ваш вопрос.


      1. freecoder_xx
        31.10.2018 21:58

        На Хабре, кстати, есть ее перевод: WebAssembly — это возвращение апплетов Java и Flash?


      1. kovserg
        01.11.2018 01:48

        Почитал. Выводы в статье не логичные, сравнивают мягкое с тёплым. WA просто больше пиарят. А по факту в таком виде который он есть он нафиг не нужен. Кривая виртуальная машина (грабли с integer overflow), нет платформы всё через жо... js преподносится как плюс. Современное по выкатывает exe-шники по 100мб и больше. Неужели WA сможет уменьшит запросы этих бегемотов.


  1. ZXZs
    31.10.2018 19:19

    Это конечно всё хорошо, но почему-то те же самые 3D-игрульки работают на моём не самом лучшем компьютере куда хуже, чем их десктопные версии, в плане нагрузки на CPU. Предполагаю, что если и можно будет запускать тяжёлые приложения прямо в браузере, то для этого пригодится довольной мощный ПК. Поправьте, если что-то не так.


  1. maslyaev
    31.10.2018 20:15
    +2

    Когда деревья были большими а жёсткие диски маленькими, нас учили, что в компе у нас как-то так:
     Прикладные программы — ОС — Железо

    Теперь, по ходу, концепция дополняется новым обязательным элементом:
     Прикладные программы — Браузер — ОС — Железо

    А поскольку давать браузеру полный доступ к локальным данным никто (надеюсь) не собирается, фактически получаем следующее:
     Прикладные программы — Браузер — Чей-то сервис
    (ОС и железо тоже где-то сбоку есть, но суть уже не в них т.к. логически мы от них избавились)

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

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


    1. freecoder_xx
      31.10.2018 21:20
      +1

      Поэтому существуют децентрализованные сети. В вашей схеме Чей-то сервис — им может быть и децентрализованный сервис, и машина самого пользователя, в том числе.


      1. maslyaev
        31.10.2018 21:51
        +1

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


        1. freecoder_xx
          31.10.2018 21:56
          +1

          Я к тому, что проблема в принципе решаема и некоторые решения уже есть. Их не так много и они не так хороши, как хотелось бы, потому что проблема эта еще не стала массовой.


          1. maslyaev
            31.10.2018 22:17
            +1

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

            Я не склонен верить в теории заговора. Скорее всего (вспоминаем бритву Хэнлона), это некоторые особенности нашей человеческой натуры гонят нас на рифы.


            1. freecoder_xx
              31.10.2018 22:27

              А разве со свободными операционными системами не та же история? Есть репозитории пакетов, поставщики, которым ты так или иначе доверяешь.


              1. maslyaev
                31.10.2018 22:40

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


                1. freecoder_xx
                  31.10.2018 23:05

                  Так есть же кэши и локальные хранилища, разве это не решает проблему?


                  1. maslyaev
                    31.10.2018 23:38

                    В модели SaaS кэши и локальные хранилища — необязательные компоненты.


                    1. freecoder_xx
                      01.11.2018 13:24

                      А по вашему Wasm применим только для SaaS? Тогда извините, мы говорим о разном.


                      1. maslyaev
                        01.11.2018 14:01

                        Понятно, что не только SaaS. Можно и дедовским способом налабать браузерную прогочку в виде html-файлика, и запускать с жёсткого диска. Сам сто раз так делал. Но надо понимать, что это всё извраты для ценителей. Мэйнстрим использования Wasm — это всё же раздача ПО с сервиса. То есть SaaS (и прочие «aaS») во всей идейной чистоте.


    1. bm13kk
      31.10.2018 23:25

      простити, но вьі сильно устарели. Даже новости перестали читать.


      сейчас в винде


      • программа
      • виртуальная машина — дотнет
      • ос
      • uefi — по сложности как ос
      • микрокод процессора — содержит свою ос
      • каждая железка — по сути отдельньій компьютер — с процессором, оперативкой и микрокодом.

      Я молчу про облака. Где добавляются слои легкой виртуализации (аля докер), тяжелой (аля вагрант) и еще железной (аля квм). Одновременно


      1. maslyaev
        31.10.2018 23:42

        Можно ещё вспомнить фреймворки поверх фреймворков поверх фреймворков :))


        1. bm13kk
          01.11.2018 00:25

          можно. но я перечислил свои, которьіе являются черньім ящиком для предьідіщих. И єто те, про которьіе я


          1. bm13kk
            01.11.2018 01:01

            • слои которьіе я


            1. bm13kk
              01.11.2018 12:14

              как же сложно ночью с телефона


              Фреймворки можно добавить. И библиотеки. И всякие подсистемы ОС. И наверно что-то еще, о чем я не подумал. Но я перечислял слои по принципу черного ящика. Когда предыдущий слой — царь, бог и возможность существования.


              Более того. Я, как и большинство тут, узкий специалист. Я знаю только про свой слой (и то можно было бы и лучше). А про остальные прочитал в статьях вроде этой. То есть возможно слоев больше, а я про это ни бум-бум.


              1. maslyaev
                01.11.2018 13:53

                Да что уж там говорить, накручивание слоёв абстракции — наше любимое дело. И даже для многих из нас то, чем зарабатываем на хлебушек с маслицем.
                Просто не нужно забывать, что бороться с нарастающей лавиной сложности методом её, сложности, добавления — не очень перспективно. Ну и, конечно, чётко следить за зависимостями. Если при вырубании инета перестаёт работать текстовый редактор (или считаться бухбаланс, или ещё какая зараза), то в пекло такие решения.


                1. Balek
                  01.11.2018 15:32

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

                  Как можно бороться со сложностью, если не с помощью слоёв абстракций?


  1. freecoder_xx
    31.10.2018 22:07
    +2

    Радует, что Rust — на передовой линии, в плане поддержки Wasm. Хороший современный системный язык, который все больше становится языком общего назначения. Может быть лучшие дни популярности FireFox уже и прошли, но мне нравится, как Mozilla борется за "место под солнцем", вкладываясь в такие фундаментальные технологии, как Wasm и Rust.


    1. Halt
      31.10.2018 22:11
      +1

      Лису рано списывать. Посмотрим что будет, когда WebRender появится в релизе. Обещают буквально в ближайших версиях.


      1. ZoomLS
        31.10.2018 23:38

        WebRender активируют В Firefox 67, для некоторых пользователей с Nvidia.


        1. AngReload
          01.11.2018 11:01

          Вроде бы уже в Firefox 64 beta https://www.mozilla.org/en-US/firefox/64.0beta/releasenotes/


      1. VEG
        01.11.2018 11:18

        Ну WebRender — это просто композитор (собирает кучу изображений из разных частей кода в одно большое и выводит на экран). Не стоит ожидать от него слишком многого.


  1. helg1978
    31.10.2018 23:34

    Надеюсь развитие webassembly похоронит Electron-приложения


    1. ankh1989
      01.11.2018 08:04

      Почему wasm должен похоронить electron? Не вижу причин для этого.


    1. F0iL
      01.11.2018 11:12

      С чего вдруг? WASM и Electron — это совершенно ортогональные вещи :)


    1. justboris
      01.11.2018 11:43
      +1

      А может наоборот? Electron получит поддержку WebAssembly от движка Chrome.

      WebAssembly -> больше возможностей по оптимизации –> больше приложений на Electron.


      1. helg1978
        01.11.2018 11:47

        или так, ага


  1. istepan
    01.11.2018 07:55

    За Мозиллу нарадоваться не могу. Пойду задоначу.


  1. anonymous
    01.11.2018 11:48

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


  1. bm13kk
    01.11.2018 12:21

    Я очень сильно надеюсь, что они смогут добится первых трех ачивок. И ускорить современный веб на порядок.


    Но, к сожалению, остальные очивки — путь по захвату мира. Или борьба с JVM за вершину пищевой цепочки. И тут оно может не вістрелить. А ресурсы с первых трех ачивок украдены.


    1. Balek
      01.11.2018 15:35

      > И ускорить современный веб на порядок.
      Скорость веба не упирается в скорость JS. Движки JS очень быстрые. Поэтому WebAssembly здесь ничего не изменит.


  1. anz
    01.11.2018 13:02

    А никто не знает, в плане доступа к памяти еще что-то делается в webassembly? Кажется это самое критичное место в плане производительности