Skip to content

Instantly share code, notes, and snippets.

@MaxGraey
Last active January 19, 2024 22:26
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save MaxGraey/326b1c04d66de3beb247c2c1e6358fd0 to your computer and use it in GitHub Desktop.
Save MaxGraey/326b1c04d66de3beb247c2c1e6358fd0 to your computer and use it in GitHub Desktop.
WebAssembly FAQ для телеграм сообщества WebAssembly_ru

Введение

Данный FAQ был специально создан для телеграм сообщества https://t.me/WebAssembly_ru.

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

0. Какие цели у WebAssembly?

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

1. WebAssembly это нативный код CPU?

Нет! WebAssembly - это цель компиляции и промежуточный формат, который скорее похож на байткод в .NET, LLVM IR или Java, нежели нативный машинный код. Если вам не нравится ассоциации с .NET или Java-байткодом, то по-другому это можно представить себе как некий портативный набор инструкций для виртуального процессора (ISA).

2. WebAssembly это ассемблерный код?

Нет! "ассемблерный код" обычно означает текстовое представление определенного набора команд центрального процессора. WebAssembly в своей типичной форме не является ни текстовым представлением, ни специфичным для процессора бинарным представлением, хотя спецификация WASM определяет и текстовое представление имеющие одно из расширений: .wat или .wast. Безусловно вы можете писать код используя wat синтаксис и собирать его в бинарный модуль с помощью wat2wasm, но это стоит делать лишь в академических целях или для изучения новых возможностей, недоступных пока в компиляторах высокого уровня. В действительности, WebAssembly - это цель компиляции, так же как и нативный код для x86 или ARM.

3. WebAssembly это очередной "Java Applets"/ActiveX/Flash/Silverlight?

Нет! WebAssembly отличается от Java-апплетов тем, что он использует существующие части виртуальной машины JavaScript и ее среду изоляции (sandbox), вместо добавления другой громоздкой виртуальной машины посредством плагинов или расширений и тем самым снижая надежность и безопасность системы в целом. WebAssembly также не позволяет вызывать нативный код или системные вызовы напрямую, минуя слои безопасности самого браузера или другой виртуальной машины, как это делали Flash или Java-апплеты (через JNI).

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

Кроме того, большинство этих плагинов имели свои виртуальные машины, которые создавались для конкретных языков. Например, Java Applets - для Java, Flash - для ActionScript, Silverlight - для C#. WebAssembly же - это унивирсальная виртуальная машина c открытым стандартом, готовая принять в свои объятия любой язык, будь то Haskell, PHP или TypeScript.

4. WebAssembly это угроза для безопасности? Надо ли опасаться вирусов?

Нет! Если только вы не считаете JavaScript угрозой безопасности для браузера =) WebAssembly примерно так же безопасен, как и JavaScript, поскольку он работает в той же песочнице. Типичные реализации WebAssembly только добавляют довольно небольшой модуль синтаксического анализа и загрузчика к существующему JavaScript движку. Например, в WebKit, WebAssembly, составляет всего около 10 тыс строк из 432 тыс строк кода для всего движка JavaScriptCore. Таким образом, всего лишь ~2% от всего JavaScript-движка - это новая поверхность атаки, специфичная для WebAssembly. Кроме того, WebAssembly не позволяет напрямую обращаться к Web API или любому другому внешнему интерфейсу системы без явного импорта внутри WebAssembly сборки и некоторого "склеивающего кода" со стороны хоста.

5. Могу ли я вызывать tcp-сокеты/операции ввода-вывода/DOM/WebGL и другие API браузера или ОС из под WebAssembly напрямую?

Нет! WebAssembly работает внутри изолированной программной среды браузера или другой VM и может получать доступ только к веб-API только косвенно через JavaScript. Однако emscripten SDK (C++) и web-sys (Rust) предоставляют обертки для многих распространенных API, что упрощает перенос существующего кода C / C++ / Rust (например, конвертировать TcpSockets-в-WebSockets, OpenGL-в-WebGL, OpenAL-в-WebAudio и т.д.). В дальнейшем, когда будет реализован interface-types (webidl-bindings) proposal всеми браузерами, всего вышеперечисленного не потребуется, и можно будет обращаться непосредственно к Web API или любому другому интерфейсу (в случае со standalone VM) непосредственно через WebIDL а так же WASI интерфейс.

6. Могу ли я загрузить или создать нативную DLL-библиотеку в WebAssembly?

Нет! Динамические библиотеки, которые используются в операционной системе являются машинным кодом и, следовательно, не будут работать (без эмуляции соответсвуюшего процессора). Стоит так же заметить, что Blazor, может действительно загружать файлы с расширением .dll в браузере, но это CIL-библиотеки Mono-рантайма которые выполняются в режиме интерпретации.

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

7. Могу ли я запустить программу или отдельный процесс из WebAssembly?

Нет! По той же причине, почему нельзя загружать DLL.

8. Можно ли использовать WebAssembly для обхода блокировщиков рекламы?

Нет! WebAssembly может делать только то, что и JavaScript. Даже если реклама не загружает изображения, а отображает ее контент "процедурно" с помощью кода WebAssembly, сам WebAssembly-модуль должен быть сперва загружен с какого-либо адреса (обычно это сервер рекламной сети), и это может быть перехвачено и заблокировано Ad-блокерами.

…но я ведь не могу посмотреть исходный код?!

Это уже стало давно проблематично даже для JavaScript, с тех пор как все начали использовать минификаторы и обфускаторы. Тем не менее, большинство браузеров сейчас умеют отображать wasm-модули в текстовом представлении, что порой куда более понятней, чем минифицированный и обфусцированный JavaScript-код. Кроме того, браузеры и инструменты сборки давно уже поддерживают source maps для WebAssembly и ведутся работы над поддержкой DWARF секций что позволит делать полноценную символьную отладку.

9. WebAssembly это раздолье для криптомайнеров? Могу ли я запретить WebAssembly в своем браузере?

Нет! Вы не сможете запретить исполняться WebAssembly если только не запретите исполнение самого JavaScript в браузере.

Насчет майнеров. Первые криптовалютные майнеры в браузере появились еще в 2012 году, задолго до WebAssembly или asm.js и использовали новую тогда технолугию WebGL 1.0 (точнее GLSL язык) и конечно же JavaScript. После этого были майнеры использующие asm.js и некоторые из них используют его до сих пор, если ваш браузер не поддерживает WebAssembly. Стало быть WebAssembly ни в коей мере не является главным инициатором активности браузерных майнеров. На данный момент производители браузеров стремяться мониторить активность скриптов и автоматически блокировать такие майнеры, но пока не слишком успешно. Также в этом немного помогают блокировщики рекламы.

10. Я простой frontend-разработчик, выходит мне теперь необходимо изучать C++ или Rust?

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

Так что написание тех частей приложения, которые впоследствии будут компилироваться в wasm-модуль можно поручить системным разработчикам, уже знакомыми с одним из таких языков. Кроме того, активно развивается TypeScript-подобный язык AssemblyScript способный производить WebAssembly-модуль и с которым большинство JavaScript/TypeScript разработчиков будут себя чувствовать в комфортной и знакомой среде.

Полный список языков, поддерживающих WebAssembly можно посмотреть здесь.

11. Может ли WebAssembly манипулировать DOM?

Мы уже частично затронули этот вопрос. И здесь мы имеем неоднозначный ответ - и да, и нет. WebAssembly не может получить прямой доступ к DOM, но может вызывать вспомогательный код на JavaScript, и этот код уже может предоставлять доступ к DOM. В emscripten это так же просто, как прямое встраивание кода JavaScript в код C++. Но такое взаимодействие между WebAssembly и JavaScript налагает дополнительные расходы. В последнее время браузеры стремятся сократить время этого взаимодействия, но если для простых типов это осуществимо, то ссылочные типы по-прежнему требуют структурное клонирование и дополнительные затраты на сериализацию и десереализацию в случае со структурами или объектами.

Может возникнуть очень заманчивая идея создать свою реактивную библиотеку работы с DOM (или реализовать лишь diff-алгоритм для Virtual DOM) например для Rust, С++ или Go. Не делайте этого! По крайней мере пока. Как показывает опыт таких экспериментальных библиотек как yew и asm-dom это зачастую медленее даже самых медлительных JavaScript-библиотек или фреймворков, не говоря уже о непосредственной работе с vanilla DOM без дополнительных абстракций.

12. WebAssembly бесполезен для языков требующих Сборщик Мусора (GC)?

И да, и нет. Текущая MVP версия WebAssembly не предпологает встроенный сборщик мусора, тем самым ограничивая языки с наличием таковых, но это не мешает таким языкам как C#, Go, Java или Kotlin включать их в сборку вместе с остальным рантаймом, что они и делают. Безусловно это увеличивает размер wasm-модуля в сравнении с Rust или C++, которые не требуют GC. Кроме того существует предложение для расширения MVP включающее Сборщик Мусора и над которым сейчас активно работают основные производители браузеров.

13. WebAssembly существенно ускоряет код по сравнению с аналогичным, но на JavaScript?

И да, и нет. Это зависит от нескольких факторов:

  • от выбора языка/компилятора и его настроек;
  • от текущих задач, которые вы стремитесь решить. Как мы уже выяснили манипуляции с DOM у WebAssembly явно не будут быстрее. Зато игры, криптография, эмуляторы, CAD-системы, DSP, кодирование/декодирование мультимедиа определенно да! Особенно если учесть, что в будущем WebAssembly будет поддерживать SIMD-комманды недоступные для JavaScript и уже поддерживает (пока только Chrome) атомарные инструкции и потоки, работающие с разделяемой памятью SharedArrayBuffer;
  • от того, как часто вы вызываете методы хоста (Web API) из под WebAssembly или экспортируемые методы wasm на стороне хоста;
  • и наконец, от скорости оптимизирующих AOT/JIT-компиляторов самих виртуальных машин.

14. Что такое WASI?

Префикс "Web" в названии WebAssembly может навести на мысль, что эта технология создавалась исключительно для веба, но это не так. На данный момент уже существует огромное множество standalone рантаймов для WebAssembly способные исполнять wasm не в самом браузере а непосредственно в ОС или в нативном приложении.

WASI (WebAssembly System Interface) - это проект ABI от Mozilla, который определяет стандартизированный интерфейс взаимодействия ОС с wasm-модулем (такой себе POSIX только для wasm). WASI дает возможность получить доступ к таким функциям как файловая система, сетевые сокеты, таймеры и генераторы случайных чисел. Развитие ABI предполагает независимость от браузера, JavaScript и WebAPI. При этом проект обеспечивает надлежащий уровень изоляции от основной системы и позволяет определять полномочия приложения в стиле CloudABI и Capsicum. Файлы, каталоги, сокеты и другие ресурсы ассоциируются со специальным типом файловых дескрипторов, а для взаимодействия с каждым из ресурсов приложения должен иметь полномочия. Последние обрабатываются иерархически, то есть доступ к каталогу автоматически открывает и доступ ко всем файлам в нем. Кроме того существует polyfill WASI для браузеров и готовиться для node.js. Все это дает возможность писать модули с единым интерефейсом как для десктопных так и для браузерных приложений. Стоит также отметить, что на данном этапе это довольно базовая спецификация, не описывающая пока криптографию, API для работы с GPU, асинхронный I/O, TLS и т.д. кроме работы с процессами, так что IPC и fork не планируются.

15. WebAssembly это конец гегемонии и смерть JavaScript?

Нет! Определенно нет! При всех очевидных преимуществах WebAssembly будет слишком смело ожидать, что то огромное колличество библиотек, фреймворков и инструментов уже созданных для JavaScript экосистемы вдруг начнет переписываться на Rust, C++ или любой другой поддерживающий wasm язык, а огромная армия frontend-разработчиков незамедлительно ринется осваивать системное програмирование и соответствующие ему языки, особенно, если учесть, что в этой области порог вхождения несопостовимо выше чем у JavaScript. Кроме того, как мы уже выяснили далеко не для всех задач WebAssembly целесообразен. Языку Cи уже почти 50 лет и за это время возникло довольно много его надмножеств и прямых конкурентов, которые должны были покончить с ним, но как мы видим этого не произошло и он до сих пор остается в десятке наиболее часто используемых языков.

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

Кроме того, JavaScript давно вышел за пределы браузера и используется для бэкенда (node.js, deno), мобильной разработки (ReactNative, NativeScript, Cordova) и даже для программирования логики встраиваемых (IoT) устройств.

Будем надеяться и WebAssembly постигнет такой же успех!

Полезные ресурсы

Автор

@frenzzy
Copy link

frenzzy commented Jun 3, 2019

Пункт №5: битая ссылка "host-binding proposal"

@MaxGraey
Copy link
Author

MaxGraey commented Jun 3, 2019

Спасибо. Поправил

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment