web assembly что это

Что это за зверь — WebAssembly?

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

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

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

Когда же наши потребности начали превосходить возможности датацентров, мы вошли в эпоху образов Docker и теперь развертываем эти образы поверх виртуальных машин, развертываемых поверх голого железа.

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

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

Так что же это за зверь — WebAssembly?

WebAssembly – это ни web, ни assembly

При изучении WebAssembly (кратко именуемого Wasm) в сети можно нередко встретить эту фразу. Она открыто заявляет о том, чем Wasm не является, но ничего не говорит о его истинной сути. Надеюсь, что данная статья поможет вам внести в этот вопрос ясность.

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

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

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

Примитивность

WebAssembly примитивен, но в хорошем смысле. Мне всегда нравились языки, которые делают немногое: языки, чьи разработчики старательно уделили внимание исключению всего лишнего. Значительный потенциал Wasm – о чем я буду говорить в течение статьи – в первую очередь определяется его возможностями.

Единственный нюанс, на который зачастую обращают внимание разработчики (и которого побаиваются) – это присутствие в языке только численного типа данных. Функции могут принимать и возвращать значения в виде целых чисел либо чисел с плавающей запятой, причем допускаются только 32- и 64-битные значения.

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

Этот порядок может не соответствовать спецификации, но в качестве примера сгодится (двоичный формат имеет достаточно сложные требования к кодировке, которые на данном этапе нас только запутают):

Портативность

Я уже упомянул, что никакая инструкция Wasm не ограничивается ни операционной системой, ни архитектурой ЦПУ. Это означает, что при соответствии среды выполнения (например, браузера или кастомного инструмента встраивания (embedder)) спецификации, один и тот же файл Wasm можно интерпретировать на любой машине, независимо от ее ОС или архитектуры ЦПУ.

Быстродействие

Задача среды выполнения проста – считывать коды операций, управлять стеком и памятью с линейной адресацией, а также выполнять диктуемую операционным кодом задачу. Именно эта простота позволяет невероятно быстро обрабатывать файл WebAssembly. Несмотря на доступность только JIT-компиляторов, преобразующих модуль Wasm в нативный код, многие среды выполнения (например, ваш браузер) могут очень быстро работать путем одной только интерпретации.

Потоковость

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

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

Компактность

Wasm очень компактен. Даже язык, который обычно производит самые крупные бинарники WebAssembly (речь о Rust), все равно создает их на порядок меньшего размера, чем образы Docker и даже отдельные специфичные для ОС и ЦПУ исполняемые файлы, создаваемые такими языками, как Go и тот же Rust.

Существует ряд фреймворков и кастомных инструментов встраивания, которые за счет скорости и компактности Wasm способны поддерживать сотни и даже тысячи мелких модулей на одном хосте. Подобной вычислительной плотности нереально добиться при помощи доступных на сегодня языков и фреймворков, выполняя компиляцию для «традиционных» целевых платформ.

Безопасность

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

В WebAssembly нет встроенных инструкций для обращения к файловой системе, записи в сокеты, управления памятью хоста, доступа к сетевым службам или какого-либо взаимодействия с операционной системой. Даже при том, что стандарты вроде WASI позволяют ограниченный доступ к ОС, он оказывается защищен за счет использования разрешающих токенов, и среда выполнения по-прежнему может просто запретить доступ к вызовам функций на основе WASI.

Модули Wasm зачастую представляют собой чистые вычисления либо совсем без побочных эффектов, либо с такими, которые строго контролируются средой выполнения. К побочным эффектам, допускаемым со стороны среды браузера, относятся доступ к JavaScript API через промежуточные оболочки и возможность управлять DOM (также через промежуточный код, обычно генерируемый специальными инструментами).

Подытожим

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

Характеристики, которые всегда рассматривались как некий священный Грааль в вычислительной среде – малый размер, портативность, безопасность и быстродействие – все они обеспечиваются WebAssembly. Так что, если вы еще не занялись освоением этой новой технологии, то рекомендую надолго не откладывать, потому что вскоре она наверняка будет использоваться разработчиками повсеместно.

Источник

WebAssembly: что и как

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Эта статья основана на моём выступлении на конференции ITSubbotnik, прошедшем 2 ноября 2019 года в Москве.

Вообще я бэкенд программист, но меня заинтересовала эта технология, она позволяет использовать мои знания бэкенда на фронте.

Проблема

Начнём с проблемы, которая решается этой (относительно новой) технологией. Проблема эта — быстро исполнять код в браузере. Быстро — это значит, «быстрее чем JavaScript», в идеале настолько быстро, насколько позволяет имеющийся у нас процессор.
Кроме того, исторически, вокруг этой проблемы постепенно возникли важные дополнительные требования:

История до Wasm

Мы видели множество вариантов исполнения кода в браузере. Можно сказать, что на этом поле есть победители и проигравшие.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Победители: это, безусловно, JavaScript; движок V8, сделавший JS таким быстрым; а также HTML5.

Проигравшие: ActiveX — если вы помните, эта технология позволяла делать с машиной вообще всё что угодно, т.е. с безопасностью было очень плохо; Flash — сейчас мы наблюдаем эпоху заката Flash, хотя внутри него работает ActionScript, по сути, тот же JavaScript; Silverlight — наверное, он появился слишком поздно, чтобы занять серьёзную нишу.
В итоге, проиграли все плагины, в том числе из-за проблем с безопасностью.

Были и другие попытки решения проблемы, уже в браузере:

asm.js

asm.js — ещё одна интересная инициатива, уже от Mozilla Foundation, которая подводит нас вплотную к теме WebAssembly. Появилась она в 2010 году, а в 2013 стала публично доступна.

asm.js это подмножество JavaScript, в него можно компилировать код из C и C++ с помощью компилятора Emscripten.

Поскольку это тоже JavaScript, то такой код будет исполняться в любом браузере. Кроме того, основные современные браузеры уже давно умеют быстро распознавать asm.js и эффективно компилировать его в родной код процессора. В сравнении с родным кодом, полученным непосредственно из C/C++, код полученный из asm.js медленнее всего в 1,5-2 раза (50-67 %).

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

В целом, asm.js это использование наших знаний о том, как браузерный движок компилирует JS, для того чтобы оптимизировать эту работу.

Что же такое WebAssembly

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

WebAssembly (или Wasm) — это бинарный формат, запускаемый в браузере, виртуальная машина, и результат компиляции с языка высокого уровня.

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

Кто-то очень умный сказал, что название web assembly (то есть «ассемблер для веба») полностью неправильное, потому что это не ассемблер (не язык программирования) и он никак не связан с вебом (потому что это просто виртуальная машина).

Создатели WebAssembly руководствовались следующими целями и ограничениями — см. видео Evolving Wasm into a proper misnomer: Andreas Rossberg.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

По сути, они сводятся к трём вещам — кросс-платформенность, компактность, скорость. Но было ещё одно важное требование, это «продаваемость» — инициативу должны были воспринять и подхватить разработчики основных браузеров. В итоге это удалось «продать», в разработке спецификации прияли участие представители Google, Mozilla, Microsoft и Apple.

Посмотрим, что представляет из себя Wasm как виртуальная машина.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Это такой «выдуманный процессор», но без регистров, всё делается через стек. Всего четыре типа данных: два целых, два плавающих. Относительно простой набор операций — см. спецификацию и интерактивную таблицу.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Плоская модель памяти: под память выделяется единый блок, размер которого кратен 64 КБ. Здесь находится код, данные, константы, глобальные переменные, стек растущий вниз, куча растущая вверх. Можно сделать так, чтобы куча автоматически увеличивалась при необходимости, при этом блок памяти расширяется на размер кратный 64 КБ.

Указатели не используется (это сделано для безопасности), вместо этого используется индекс. Индекс 32-разрядный, поэтому адресуется до 4 ГБ памяти.

Вся память WebAssembly полностью доступна из JavaScript, причём как на чтение, так и на запись.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Посмотрим на модель исполнения WebAssembly. Wasm всегда загружается и вызывается ТОЛЬКО из JavaScript. Более того, JS и Wasm работают в одной и той же «песочнице», и исполняются одним и тем же движком.

Заметим, что из Wasm также можно вызывать JS. Это может быть вызов функции с передачей аргументов и возвратом значения, либо это может быть просто выполнение произвольной строки как JS-кода.

Пробуем WebAssembly

Для того чтобы освоиться с WebAssembly, я рекомендую воспользоваться сайтом WasmFiddle или WebAssembly Studio — это простой и наглядный способ понять для себя, что такое Wasm на самом деле.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Это текстовое представление с кучей скобочек — по сути, абстрактное синтаксическое дерево (AST). Ну и собственно скобочной записью это напоминает язык Lisp. По идее, мы можем редактировать код в виде текстового представления, и затем свернуть его вновь в бинарный формат — это напоминает программирование на языке ассемблера. Но обычно мы получаем бинарный Wasm в результате компиляции с языка высокого уровня.

2017 год: Production Ready

В ноябре 2017 года WebAssembly был объявлен «готовым к использованию в продакшене». Спецификация на все основные части Wasm была подготовлена, вышла реализация Wasm во всех основных браузерах. Тем самым, для WebAssembly был «выпущен» MVP — Minimum Viable Product, версия 1.0, с которой мы и имеем дело сейчас.

Поддержка в браузерах

В конце 2017 года были выпущены релизы всех основных браузеров с поддержкой WebAssembly:

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Исключение — IE11, для него поддержки нет, и по всей видимости, уже не будет. Предполагалось, что для старых браузеров будет polyfill — возможность преобразования Wasm в asm.js; такие прототипы есть, но насколько я видел, эти проекты заброшены, видимо, сообществу не до них.

Сейчас среди всех установленных браузеров,

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Поддержка языков

Для того, чтобы ваш любимый язык компилировался в Wasm, нужно чтобы компилятор обеспечивал такую цель компиляции. Сейчас уже довольно много языков поддерживают Wasm, и их становится всё больше с каждым месяцем. См. appcypher/awesome-wasm-langs.

Не так давно появилась новость, что LLVM теперь поддерживает Wasm как цель компиляции. Это облегчает работу для разработчиков языков программирования, мы получим ещё больше языков, компилирующих в Wasm.

Сценарии использования

Наверное, это один из главных вопросов — «А как я могу использовать Wasm?»

Уже сейчас WebAssembly активно применяется:

Другие возможные сценарии:

Производительность

Производительность Wasm была одним из его главных «продающих» факторов, но что с ней происходит на самом деле?

В сравнении с JavaScript, получается, что в среднем Wasm быстрее, но в каждом частном случае нужно делать сравнение JS/Wasm, потому что может получиться и во много раз лучше, и в несколько раз хуже. Также это может сильно зависеть от используемого браузера.

На самом деле, пиковая производительность JS и Wasm одинакова, поскольку оба в итоге превращаются в родной код процессора. Но JS гораздо легче теряет в производительности, а Wasm обеспечивает более «ровный» подход.

Как правило, Wasm хорошо показывает себя на объёмных вычислениях. Там где много операций с памятью, Wasm проигрывает. Ну и основная проблема в реальных применениях — это медленный интероп JS Wasm. См. например, бенчмарк.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

В июле 2019 года вышла научная статья «Not So Fast: Analyzing the Performance of WebAssembly vs. Native Code». Авторы реализовали возможность запуска под WebAssembly консольных утилит Linux, для запуска бенчмарков, и использовали бенчмарки SPEC для оценки производительности Wasm по сравнению с теми же тестами на asm.js и на родном коде.

Авторы статьи также дали анализ причин, на чём именно Wasm «подтормаживает»:

В общем, на самом деле, с производительностью всё не так плохо. К тому же, этот анализ позволит разработчикам браузеров сделать Wasm ещё быстрее.

В будущем нас ожидает ускорение Wasm не только за счёт лучшей оптимизации в браузерах, но и за счёт новых фич, таких как: блоковые операции над памятью, поддержка SIMD-инструкций, поддержка threads.

Что будет дальше?

Как развивается WebAssembly?

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

В частности, в ближайшее время мы ожидаем дальше увидеть такие фичи:

Во-вторых, разработчики браузеров, со своей стороны, реализуют эти спецификации, т.е. постепенно к Wasm добавляются новые фичи, сначала скрытые «под флагом» в настройках, а затем и включенные по умолчанию.

Вот, например, список фич Chrome, относящихся к WebAssembly.
Для Firefox подобный список можно найти здесь.

WebAssembly вне браузера

Как было сказано выше, Wasm по сути никак не связан с вебом, это просто виртуальная машина. А значит, его вполне можно использовать и вне веба.

Сейчас видны несколько сценариев использования Wasm вне браузера:

Для Wasm работающего вне браузера, уже не нужны ограничения «песочницы», напротив, необходим доступ к функциям системы — файловая система и файлы, консольный ввод/вывод и т.д. Это привело к созданию WebAssembly System Interface (WASI) — спецификации кросс-платформенного API, подобного POSIX. См. WebAssembly/WASI и wasi.dev.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Заключение

Итак, WebAssembly вполне можно использовать, он уже два года как «production ready».
Применение Wasm вполне может дать некоторое ускорение, по сравнению с аналогичным кодом на JavaScript, но всегда нужно проверять, получился ли прирост скорости.
Поддержка Wasm со стороны языков программирования постоянно развивается.

Ну и самое главное, WebAssembly несколько «изменил ландшафт» веба — предоставил нам новые сценарии использования, которые мы можем реализовать в своих приложениях.

Источник

Основы WebAssembly

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

Что такое WebAssembly?

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

Более того, вам даже не нужно знать, как создавать код WebAssembly, чтобы его использовать. Модули WebAssembly можно импортировать в веб-приложение (или Node.js), и экспортировать из них функции для использования через JavaScript. JavaScript-фреймворки могут использовать модули WebAssembly для получения огромных преимуществ в производительности и новых функций, в то же время делая их функциональность легко доступной для веб-разработчиков.

Цели WebAssembly

Технология WebAssembly создаётся как открытый стандарт внутри W3C WebAssembly Community Group со следующими целями:

Примечание: Технология WebAssembly также будет иметь возможность использования за пределами веб и JavaScript-сред (см. Встраивание вне Web).

Как WebAssembly встраивается в веб-платформу?

Веб-платформа может рассматриваться как состоящая из двух частей:

Исторически ВМ могла загружать только JavaScript. Раньше нас это вполне устраивало, поскольку JavaScript достаточно мощный, чтобы решать большинство проблем, с которыми мы сталкивались в интернете. Однако мы столкнулись с проблемами производительности, когда попытались использовать JavaScript для более нагруженных сценариев использования, таких как 3D-игры, виртуальная и дополненная реальность, компьютерное зрение, редактирование изображений / видео и в ряде других применений, которые требуют повышенной производительности (см. варианты использования WebAssembly где описано больше идей).

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

Язык WebAssembly отличается от языка JavaScript, но он не предназначен для его замены. Он предназначен для дополнения и работы вместе с JavaScript, что позволяет веб-разработчикам использовать преимущества обоих языков:

Ключевые понятия WebAssembly

Есть несколько ключевых понятий, необходимых для понимания того, как WebAssembly работает в браузере. Все эти понятия отражены 1:1 в WebAssembly JavaScript API.

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

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

В будущем модули WebAssembly будут загружаться так же, как и модули ES2015 (с использованием

Источник

Знакомство с WebAssembly

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Эта статья основана на моём выступлении на ITSubbotnik, прошедшем в Рязани 14 октября 2017 года. На русском пока что довольно мало материала на эту тему, надеюсь что статья будет вам полезна.

Disclaimer: Автор не является экспертом ни в WebAssembly, ни в JavaScript. Данная статья есть компиляция мыслей и идей, полученных из выступлений других людей на данную тему, плюс эпизодического опыта изучения WebAssembly в течение нескольких месяцев.

Что такое WebAssembly?

WebAssembly (WASM) — новый бинарный формат, позволяющий запускать код в браузере.
Пока нам будет достаточно такого определения, более полное определение можно найти в Википедии.

Проблема

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

Ситуация

В попытке решения этой проблемы у нас есть один победитель, и это JavaScript.

Проигравшие (далеко не полный список):

Другие попытки решения:

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

Решение 1: Родной код прямо в браузере

Примеры: ActiveX, NaCl
Что плохо: нет портируемости, потенциальные или реальные проблемы с безопасностью.

Решение 2: Код для виртуальной машины

Примеры: Java Applets, Silverlight и др.
Что плохо: нужен плагин и/или runtime ⇒ нет zero configuration
В целом, если вы хотите обеспечить кросс-платформенное выполнение вашего кода, то виртуальная машина это правильный подход.

Что не так с JavaScript?

С JavaScript всё хорошо. Но если смотреть на рост его производительности с годами, то мы увидим что он сейчас находится на втором «плато» S-образной кривой. Сначала производительность была небольшой и росла постепенно, с появлением V8 мы увидели резкий скачок, который уже достаточно давно вновь перешёл в плавный рост.
web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это
(Картинка из статьи An Abridged Cartoon Introduction To WebAssembly by Lin Clark.)

Посмотрим как работают современные движки JavaScript.

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

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Допустим, у нас есть функция с двумя аргументами: foo(a, b), и мы вызываем её много раз с числовыми значениями параметров. В некоторый момент функция будет передана компилятору и станет выполняться быстрее. Допустим, мы вызовем её со строковым аргументом. В результате, движок выполнит «деоптимизацию»: передаст функцию от компилятора обратно интерпретатору, а готовый машинный код будет выброшен.

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

asm.js

Ещё одна интересная инициатива, уже от Mozilla Foundation, которая подводит нас вплотную к теме WebAssembly. Появилась она в 2010 году, а в 2013 стала публично доступна.

Идея заключается в том, что создано подмножество JavaScript, в которое можно компилировать код из C и C++ с помощью специального компилятора Emscripten.

Поскольку это подмножество JavaScript, то такой код будет исполняться в любом браузере. Кроме того, основные современные браузеры уже давно умеют быстро распознавать asm.js и эффективно компилировать его в родной код процессора. В сравнении с родным кодом, полученным непосредственно из C/C++, код полученный из asm.js код медленнее всего в 1,5-2 раза (50-67 %).

Для простейшей функции на C/C++ код asm.js выглядит так:
web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это
Здесь ‘use asm’ это директива, показывающая JS-движку что код ниже это asm.js, и конструкции вида |0 показывают, что работа идёт с целыми числами (побитовое ИЛИ с нулевым значением обнуляет дробную часть Number).

Цели разработки WebAssembly

Так что же такое WebAssembly?

С чего начать? Hello World

Освоение WebAssembly я очень советую начать с онлайнового инструмента WasmFiddle.
(Сам я начал с Emscripten и понял свою ошибку лишь спустя время.)

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Слева вверху исходный код, слева внизу результат компиляции по кнопке Build (сейчас видно текстовое представление), справа вверху код для запуска и справа внизу результат запуска по кнопке Run.

В качестве примера я использовал простой код для расчёта числа Фибоначчи (да, опять он :), не сказать чтобы хороший код, просто первый попавшийся нагугленый вариант:

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

В данном случае, по текстовому представлению мы видим, что выделяется 1 страница памяти (каждая страница = 64 Кбайт), наружу видны (экспортируются) память и функция fib, а дальше идёт определение этой функции, то есть собственно её реализация.

Начало текстового представления этой сборки выглядит так:

Если собрать всё вместе, то минимальный JavaScript-код для запуска примера выглядит примерно так:

Здесь готовый WASM описывается в коде в виде массива чисел, но в реальной жизни конечно WASM-файл будет довольно намного больше, и мы будем подгружать его с сервера.

Исполнение WebAssembly в браузере выглядит так. Браузер как обычно загружает HTML-страницу, с которой выполняется JavaScript, который уже выполняет загрузку WebAssembly — получается «модуль» (WebAssembly module), затем создаёт экземпляр модуля, после чего можно вызывать для этого экземпляра экспортируемые им функции.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Обратите внимание здесь на серую стрелку: изнутри WebAssembly можно вызывать функции JavaScript. Рассмотрим это подробнее на диаграмме последовательности:

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Здесь мы сначала из JavaScript вызываем WebAssembly, затем из WebAssembly вызываем функцию JavaScript.

Во втором вызове здесь я показал то, как WebAssembly пользуется любыми API (например, DOM / WebGL итд.). Это возможно, но не напрямую, такие вызовы тоже происходят только через JavaScript. Очевидно, здесь возникает «бутылочное горлышко»: если мы будем интенсивно работать с API из WASM, то будем терять много времени на «прокидывании» этих вызовов через JavaScript.

Модель памяти WebAssembly очень проста. Это плоский «кусок» памяти, в котором находится код программы, глобальные переменные, стек и куча. Есть возможность сделать так, чтобы память была расширяемой, то если если при очередном выделении памяти нам не хватает места, то верхняя граница памяти автоматически увеличивается.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это
Весь блок памяти доступен из JavaScript, просто как массив байтов (и кроме того, как массив 16- и 32-разрядных слов, как массив 16- и 32-разрядных float-значений). Причём, память из JavaScript доступна как на чтение так и на запись.

Emscripten

Emscripten это основной компилятор для получения asm.js и WebAssembly из C/C++. (Существуют также компиляторы в WASM из других языков, например из Rust и TypeScript.) Здесь я буду рассматривать использование Emscripten под Windows, но не думаю что для других систем будут существенные различия.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Говоря об Emscripten, стоит немного рассказать о Low Level Virtual Machine (LLVM).

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

LLVM это семейство компиляторов. Основная идея LLVM это разделение компиляции на frontend и backend. Frontend-компилятор занимается компиляцией из исходного кода во внутреннее представление (Intermediate Representation, IR). IR это код для некоторой виртуальной машины. Backend-компилятор занимается уже преобразованием IR в код для конкретной платформы, например, часто используется backend для x86 и x86-64. Если нужен компилятор с другого языка программирования, то пишется только новый frontend. Если нужна компиляция под новую платформу, то пишется новый backend.

Emscripten задействует LLVM для компиляции из C/C++, и предоставляет свои backend-компиляторы для сборки в asm.js и WebAssembly.

Установка Emscripten

Установка Emscripten проходит довольно просто, в моём случае это было под Windows, и мне даже не понадобилось ничего компилировать из исходников.

Компиляция в asm.js

Посмотрим как можно собрать код с помощью Emscripten, начнём с asm.js.

Пример тот же что и выше, немного модифицированный для Emscripten (fib.c):

Для компиляции я использую следующий командный файл:

На выходе компиляции мы получаем HTML-файл (fib.html), включающий JavaScript для запуска скомпилированного кода:
web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Также мы получили файл fib.js, в недрах которого можно найти функцию fib() и её вызов в main():
web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Кроме того, генерируется двоичный файл fib.html.mem — это «образ памяти», то как выглядит память перед запуском программы, здесь все константы и глобальные переменные.

Открыв fib.html мы увидим вот такую картину:

Компиляция в WebAssembly

Для компиляции в WebAssembly нам вообще не нужно менять исходник на C/C++ (и это прекрасно!).

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

В результате компиляции мы также получаем fib.html, плюс fib.js (набор сервисных функций Emscripten), плюс наконец-то fib.wasm:

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

В начале WASM-файла стоит байт 00 и затем символы «asm», по этим первым четырём байтам можно определить, что мы загружаем именно wasm, а не какую-нибудь страницу-заглушку с кодом ошибки. Следующие 4 байта это номер версии, в данном случае 1.0. Отдельного файла для образа памяти не генерируется, константы и глобальные переменные включены в тот же WASM-файл.

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

Давайте посмотрим что у нас есть в плане отладки. Открыв инструменты разработчика Chrome (F12), переходим в Sources и там увидим новый раздел «wasm», в котором среди набора блоков можем найти нашу функцию, можем поставить там точку останова, остановиться на ней и пошагать в отладчике.
web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Как видите, для отладки используется текстовое представление (WAST), о котором я говорил выше.

Посмотрим что нам это даст в плане отладки. Обновив страницу, в разделе Sources мы теперь увидим наш исходник fib.c, можем поставить в нём точку останова, остановиться на ней, просмотреть локальные переменные и пошагать отладчиком по коду.
web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Возможности Emscripten

Emscripten развивается с 2010 года и уже много чего умеет. В данном случае речь уже не о компиляторе, а о поддержке популярных библиотек, используемых из кода на C/C++. Поддерживаются:

И другие возможности:

Более сложный пример

У меня есть свой хобби-проект эмулятора старого советского компьютера, написанный на C++, я его описывал вот в этой статье. С тех пор я успел его несколько дописать, а также портировать под Qt (Windows/MacOS/Linux). Так что у меня уже было выделено ядро эмуляции (

7 килострок), которое собиралось под разными компиляторами. Собственно я и начал изучение WebAssembly с того, что компилировал этот эмулятор с помощью Emscripten. До первого удачного запуска у меня ушло два вечера после работы, я считаю это неплохой результат, говорящий о том, что порог вхождения в тему относительно низкий. Большая часть работы была связана с JavaScript: как из JS вызывать методы WASM, как передавать параметры, как отрисовывать canvas итп.

Кстати, экран эмулируемой машины формируется полностью внутри WASM, в виде сплошного блока памяти, с форматом «пикселей», подходящем для canvas. Наружу в JavaScript передаётся только адрес готового «экрана». В JavaScript остаётся только скопировать этот блок памяти в canvas.

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Итак, подводя итоги по Emscripten. Я убедился в том, что из одного и того же кода он генерирует результат в виде asm.js и в виде WebAssembly, полученный результат выглядит и работает в точности одинаково (кроме скорости конечно). Порог вхождения до получения реального результата оказался относительно низким.

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

Думаю что не стоит начинать освоение WebAssembly сразу с Emscripten, по той причине что довольно сложно для себя отделить то что даёт Emscripten от того что имеет WASM «из коробки». Но на реальных проектах Emscripten более чем полезен, именно за счёт тех возможностей, которые он предоставляет разработчику.

Текущее состояние WebAssembly

Новости WebAssembly в 2017 году:

Поддержка в браузерах

На начало октября 2017 года ситуация выглядела примерно так:

web assembly что это. Смотреть фото web assembly что это. Смотреть картинку web assembly что это. Картинка про web assembly что это. Фото web assembly что это

Версия Edge привязана к версии операционной системы. Вместе с Windows 10 Fall Creators Update мы получаем Edge 16, в котором WebAssembly работает сразу, уже не нужно ничего включать в настройках.

Для браузеров, не поддерживающих WebAssembly, предполагается использовать т. н. «polyfill», то есть автоматическое преобразование WASM в код, который может выполняться в данном браузере. В частности, был сделан прототип, эффективно выполняющий преобразование WebAssembly в asm.js. Но пока я не видел примеров реального применения такого подхода.

Будущее WebAssembly

Ряд вещей над которыми команда WebAssembly работает сейчас:

Производительность

Вопрос по производительности на самом деле довольно сложный. Потому что не всегда WebAssembly работает быстрее того же JavaScript или asm.js. Например, посмотрите сравнения из JavaScript vs WebAssembly easy benchmark. На первом же тесте collisionDetection у меня получается что WASM даёт 88% от JS. А допустим на следующем тесте Fibonacci WASM выдаёт гораздо лучший результат, в 3 раза быстрее чем JS.

Отмечу здесь только несколько моментов, влияющих на скорость, реально их конечно гораздо больше.

Выше уже отмечал, что WebAssembly может значительно терять в производительности при интенсивных вызовах JS-функций.

WebAssembly теряет в производительности на обращениях к памяти: каждое такое обращение делает проверку на выход за границы доступного блока памяти.

WebAssembly может существенно выигрывать за счёт типа целых переменных. В JS у нас есть только тип Number, фактически всегда 64-разрядный с плавающей точкой, и целые числа это плавающее число без дробной части. При компиляции в JS-движке, для целых чисел используется 64-разрядный целый тип. В WASM мы сами выбираем разрядность типа, и если мы используем 32-разрядный целый тип, операции над которым немного быстрее чем над 64-разрядным целым, то мы получаем здесь «нечестное» преимущество в скорости вычислений.

В целом, у меня сложилось мнение, что нет такого что «в среднем WebAssembly обеспечивает 10-15% прирост скорости», нет никакого «в среднем», для каждого алгоритма нужно тестом определять, получите ли вы прирост скорости, применив WASM. Но в целом, можно предсказать что для интенсивных вычислений, скорее всего, WebAssembly даст какой-то более или менее ощутимый прирост производительности. Ну и кроме того, видно что уже даже за последние полгода скорость WASM несколько выросла с выходом новых версий браузеров.

Заключение

Применение WebAssembly

Варианты использования

Ссылки

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

Источник

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

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