Веб-разработка

WebAssembly в браузере

Photoshop, AutoCAD, Figma, Google Earth - всё это работает в браузере на скорости нативного приложения. Секрет - WebAssembly: бинарный формат, который браузер компилирует в нативный машинный код.

  • **Figma:** C++ rendering engine скомпилирован через Emscripten в Wasm. 3x ускорение против JS-рендерера, поддержка 1000+ объектов в реальном времени.
  • **Adobe Photoshop Web:** 20 лет C++ кода портированы в браузер через WebAssembly. Пользователи получают нативные инструменты без установки.
  • **Cloudflare Workers:** Wasm + WASI на 300+ edge-локациях. Rust/Go/C++ код компилируется один раз и запускается везде с изоляцией V8 sandbox.

Wasm

WebAssembly (Wasm) - бинарный формат инструкций для стековой виртуальной машины браузера. Браузер загружает `.wasm`-модуль, компилирует его JIT в нативный машинный код и выполняет с близкой к нативной скоростью. Figma построила весь графический движок на C++ + Wasm и получила 3x ускорение против аналогичного JavaScript-рендерера. Google Earth Web, AutoCAD Web, Adobe Photoshop Web - всё это Wasm.

Wasm не заменяет JavaScript - он дополняет его. JS управляет DOM, событиями и оркестрацией, Wasm выполняет вычислительно тяжёлые задачи: кодеки, физические движки, криптографию, компьютерное зрение.

WebAssembly.instantiateStreaming() эффективнее WebAssembly.instantiate() потому что:

Emscripten

Emscripten - тулчейн, компилирующий C/C++ (через LLVM) в WebAssembly + JavaScript glue-код. Именно он позволяет портировать существующие нативные библиотеки: OpenCV, FFmpeg, SQLite, Box2D в браузер без переписывания. Figma использовала Emscripten для компиляции C++ rendering engine. FFmpeg.wasm - 100K строк C-кода, скомпилированных через Emscripten.

Emscripten генерирует не только `.wasm`, но и `.js` glue-файл, который содержит загрузчик, маппинг файловой системы (FS API), эмуляцию POSIX-окружения и биндинги для экспортированных функций.

Что генерирует Emscripten при компиляции C++ в WebAssembly?

Wasi

WASI (WebAssembly System Interface) - стандартный интерфейс для доступа Wasm-модулей к системным ресурсам: файлам, сокетам, переменным окружения. WASI позволяет запускать один и тот же `.wasm` файл в браузере, Node.js, Deno, на сервере и на edge (Cloudflare Workers, Fastly Compute). Это как POSIX, но для Wasm - универсальный ABI.

Cloudflare Workers поддерживают WASI с 2023 года. Это означает: компилируй Rust/Go/C++ один раз в .wasm, деплой в 300+ edge-локаций без изменений. Fastly использует Wasm + WASI как основу своего compute platform.

Главное преимущество WASI перед Emscripten-подходом:

Performance

Wasm быстрее JavaScript в compute-bound задачах: числодробилки, обработка изображений, криптография. Но у Wasm есть накладные расходы: передача данных между JS heap и Wasm linear memory (копирование через TypedArray), вызов JS-функций из Wasm (FFI overhead), отсутствие прямого доступа к DOM. Figma измерила: рендеринг 1000 объектов - C++ Wasm в 3x быстрее эквивалентного JS, но мелкие вызовы с копированием данных могут быть медленнее.

Ключ к производительности: минимизация cross-boundary вызовов. Передавать большие блоки данных одним вызовом, а не много мелких. Использовать SharedArrayBuffer для zero-copy между JS и Wasm Worker. WebAssembly SIMD (v128) даёт ещё 4x ускорение на векторных операциях.

WebAssembly всегда быстрее JavaScript

Wasm быстрее JS только для compute-bound задач. Для DOM-manipulation, коротких функций с частыми вызовами и операций с небольшими данными JS может быть быстрее из-за FFI overhead.

Wasm оптимален для: кодеков, физических движков, криптографии, компьютерного зрения. JS лучше для: DOM, event handling, коротких утилит, работы с JSON.

Почему мелкие частые вызовы Wasm-функций из JS могут быть медленнее JS-аналогов?

Ключевые идеи

  • **Wasm = бинарный формат** для стековой VM браузера. Загружается, компилируется JIT, выполняется с близкой к нативной скоростью. Дополняет JS, не заменяет.
  • **Emscripten** компилирует C/C++ в Wasm + JS glue. Позволяет портировать миллионы строк нативного кода: FFmpeg, OpenCV, SQLite - в браузер без переписывания.
  • **WASI** - универсальный ABI: один .wasm файл работает в браузере, Node.js, Deno и edge (Cloudflare Workers). Оптимален для батч-обработки; мелкие частые вызовы могут нивелировать выигрыш из-за FFI overhead.

Связанные темы

WebAssembly связан с производительностью браузера и архитектурой edge-вычислений:

  • Web Workers и параллелизм — Wasm-модули запускаются в Web Workers для параллельной обработки; SharedArrayBuffer обеспечивает zero-copy обмен данными
  • Performance API — performance.now() и PerformanceObserver используются для бенчмаркинга Wasm vs JS реализаций
  • Edge Computing (Cloudflare Workers) — WASI позволяет деплоить Wasm-модули на edge без изменений; Rust + wasm-pack - стандартный стек

Вопросы для размышления

  • Какие задачи в текущем проекте являются compute-bound и могли бы выиграть от переноса на Wasm?
  • Как минимизировать FFI overhead при передаче больших изображений или массивов данных между JS и Wasm?
  • В каких сценариях WASI-модуль предпочтительнее Emscripten-подхода, и наоборот?

Связанные уроки

  • comp-01-intro
WebAssembly в браузере

0

1

Войти