WebAssembly: более быстрый JavaScript?

Приложения, запускаемые в браузере (а не с жесткого диска), становятся все более распространенными. Подобно разработчикам офисных программ, таким как Microsoft (Microsoft 365) и Google (Docs and Sheets), которые постоянно добавляют новые функции в свои пакеты, браузерные игры становятся все более сложными и используют все больше ресурсов. Во многих случаях эти веб-приложения написаны с использованием JavaScript. Однако в последнее время все большее число разработчиков обращается к WebAssembly — новому подходу с блестящими результатами.

Что такое WebAssembly?

WebAssembly (Wasm) предоставляет веб-разработчикам новый способ создания приложений, доступных в Интернете. Ранее единственным вариантом был JavaScript. Проблема заключается в том, что JavaScript работает относительно медленно, и в некоторых ситуациях производительность может оказаться под вопросом. Поэтому Консорциум Всемирной паутины (W3C) придумал новый метод — WebAssembly. Для того чтобы Wasm функционировал, используемый браузер должен уметь работать с этим языком. В процессе разработки участвовали Mozilla (Firefox), Microsoft (Edge), Apple (Safari) и Google (Chrome). Приложения WebAssembly совместимы со всеми последними версиями браузеров этих разработчиков.

Совет

Чтобы лично убедиться в возможностях WebAssembly, попробуйте свои силы в игре Funky Karts. Эта игра изначально разрабатывалась как мобильное приложение, но была скомпилирована в WebAssembly, чтобы в нее можно было играть в браузере. Разработчик написал интересный пост в блоге о проекте, давая пошаговое описание того, как он выполнял процесс компиляции.

Теоретически говоря, WebAssembly представлен в виде байткода. Его можно рассматривать как нечто среднее между машинным кодом, который может понять только компьютер, и обычным языком программирования, который понятен человеку, но только после компиляции. Именно это делает WebAssembly таким быстрым по сравнению с другими языками — компьютеры могут компилировать код практически без усилий. Действительно, писать на байткоде — это несколько иное. Преимущество Wasm в том, что вам не нужно самому работать на этом языке программирования. На практике разработчики пишут свои приложения, используя, например, C или C++.

Затем исходный текст компилируется с помощью приложения Emscripten. Этот инструмент существовал задолго до WebAssembly и использовался для компиляции C/C++ кода в JavaScript (или ams.js). Теперь его также можно использовать для преобразования кода в Wasm. Это означает, что код предварительно скомпилирован, поэтому его не нужно компилировать или интерпретировать при запуске программы. Когда пользователь открывает приложение в браузере, запускается небольшая виртуальная машина и запускает приложение.

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

Преимущества WebAssembly

В настоящее время у WebAssembly есть только один реальный недостаток: он недостаточно быстро приживается. Веб-разработчики привыкли работать с JavaScript, и нет никаких планов по замене JavaScript. Руководители проекта очень четко заявили, что они хотят продвигать Wasm как альтернативу JavaScript. Однако, благодаря поддержке основных поставщиков браузеров и W3C, популярность WebAssembly растет. Этому способствует и тот факт, что посетителям сайта фактически не нужно ничего делать самим — веб-приложения, использующие WebAssembly, загружаются так же легко, как и код на JavaScript, только быстрее.

Разработчики, которые уже знакомы с такими языками, как C, C++ или Rust, теперь могут писать программы непосредственно для Интернета. Такой выбор языка программирования также открывает больше возможностей для дизайна. Если вы не можете найти необходимые библиотеки JavaScript или фреймворки для своей программы, есть другие способы сделать ее работоспособной. Вот некоторые причины, по которым разработчикам стоит присмотреться к WebAssembly:

  • Открытый веб-стандарт W3C
  • Высокая производительность и малый размер файлов
  • Идеально подходит для мобильного браузинга
  • Даже программы виртуальной реальности теоретически могут работать в браузере
  • Нет необходимости изучать новый язык программирования
  • C, C++ и Rust теперь можно использовать для программирования веб-приложений
  • Поддерживается всеми основными производителями браузеров
  • Никаких ограничений для пользователей

Практические примеры WebAssembly

На самом деле разработчикам не обязательно писать свои программы на WebAssembly. Одним из главных преимуществ решения является то, что программисты могут использовать любой язык, например, C, и впоследствии переносить свой код в формат Wasm. Тем не менее, имеет смысл узнать больше о скомпилированном коде, чтобы выяснить, как работает WebAssembly.

Исходный код доступен в двух версиях: WebAssembly Text Format (WAT) и WebAssembly Binary Format (Wasm). Последний представляет собой реальный код, который может быть запущен на машине. Поскольку Wasm — это в основном двоичный код, который трудно понять, он более или менее непригоден для анализа человеком. Поэтому была разработана подформа WAT. Этот тип кода использует читаемые выражения и может быть изучен программистом. Однако он не обеспечивает того удобства программирования, которое предоставляют более известные языки программирования.

Рассмотрим пример на примере простой строки кода, написанной на языке C:

#define WASM_EXPORT __attribute__((visibility("default")))
WASM_EXPORT
int main() {
  return 1;
}

Тот же самый код в формате WAT значительно длиннее:

(module
  (type $t0 (func))
  (type $t1 (func (result i32)))
  (func $__wasm_call_ctors (type $t0))
  (func $main (export "main") (type $t1) (result i32)
    i32.const 1)
  (table $T0 1 1 anyfunc)
  (memory $memory (export "memory") 2)
  (global $g0 (mut i32) (i32.const 66560))
  (global $__heap_base (export "__heap_base") i32 (i32.const 66560))
  (global $__data_end (export "__data_end") i32 (i32.const 1024)))

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

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

После перевода кода в двоичный код он становится нечитаемым:

0000000: 0061 736d                                 ; WASM_BINARY_MAGIC
0000004: 0100 0000                                 ; WASM_BINARY_VERSION
; section "Type" (1)
0000008: 01                                        ; section code
0000009: 00                                        ; section size (guess)
000000a: 02                                        ; num types
; type 0
000000b: 60                                        ; func
000000c: 00                                        ; num params
000000d: 00                                        ; num results
; type 1
000000e: 60                                        ; func
000000f: 00                                        ; num params
0000010: 01                                        ; num results
0000011: 7f                                        ; i32
0000009: 08                                        ; FIXUP section size
; section "Function" (3)
0000012: 03                                        ; section code
0000013: 00                                        ; section size (guess)
0000014: 02                                        ; num functions
0000015: 00                                        ; function 0 signature index
0000016: 01                                        ; function 1 signature index
0000013: 03                                        ; FIXUP section size
; section "Table" (4)
0000017: 04                                        ; section code
0000018: 00                                        ; section size (guess)
0000019: 01                                        ; num tables
; table 0
000001a: 70                                        ; funcref
000001b: 01                                        ; limits: flags
000001c: 01                                        ; limits: initial
000001d: 01                                        ; limits: max
0000018: 05                                        ; FIXUP section size
; section "Memory" (5)
000001e: 05                                        ; section code
000001f: 00                                        ; section size (guess)
0000020: 01                                        ; num memories
; memory 0
0000021: 00                                        ; limits: flags
0000022: 02                                        ; limits: initial
000001f: 03                                        ; FIXUP section size
; section "Global" (6)
0000023: 06                                        ; section code
0000024: 00                                        ; section size (guess)
0000025: 03                                        ; num globals
0000026: 7f                                        ; i32
0000027: 01                                        ; global mutability
0000028: 41                                        ; i32.const
0000029: 8088 04                                   ; i32 literal
000002c: 0b                                        ; end
000002d: 7f                                        ; i32
000002e: 00                                        ; global mutability
000002f: 41                                        ; i32.const
0000030: 8088 04                                   ; i32 literal
0000033: 0b                                        ; end
0000034: 7f                                        ; i32
0000035: 00                                        ; global mutability
0000036: 41                                        ; i32.const
0000037: 8008                                      ; i32 literal
0000039: 0b                                        ; end
0000024: 15                                        ; FIXUP section size
; section "Export" (7)
000003a: 07                                        ; section code
000003b: 00                                        ; section size (guess)
000003c: 04                                        ; num exports
000003d: 04                                        ; string length
000003e: 6d61 696e                                main  ; export name
0000042: 00                                        ; export kind
0000043: 01                                        ; export func index
0000044: 06                                        ; string length
0000045: 6d65 6d6f 7279                           memory  ; export name
000004b: 02                                        ; export kind
000004c: 00                                        ; export memory index
000004d: 0b                                        ; string length
000004e: 5f5f 6865 6170 5f62 6173 65              __heap_base  ; export name
0000059: 03                                        ; export kind
000005a: 01                                        ; export global index
000005b: 0a                                        ; string length
000005c: 5f5f 6461 7461 5f65 6e64                 __data_end  ; export name
0000066: 03                                        ; export kind
0000067: 02                                        ; export global index
000003b: 2c                                        ; FIXUP section size
; section "Code" (10)
0000068: 0a                                        ; section code
0000069: 00                                        ; section size (guess)
000006a: 02                                        ; num functions
; function body 0
000006b: 00                                        ; func body size (guess)
000006c: 00                                        ; local decl count
000006d: 0b                                        ; end
000006b: 02                                        ; FIXUP func body size
; function body 1
000006e: 00                                        ; func body size (guess)
000006f: 00                                        ; local decl count
0000070: 41                                        ; i32.const
0000071: 01                                        ; i32 literal
0000072: 0b                                        ; end
000006e: 04                                        ; FIXUP func body size
0000069: 09                                        ; FIXUP section size
; section "name"
0000073: 00                                        ; section code
0000074: 00                                        ; section size (guess)
0000075: 04                                        ; string length
0000076: 6e61 6d65                                name  ; custom section name
000007a: 01                                        ; function name type
000007b: 00                                        ; subsection size (guess)
000007c: 02                                        ; num functions
000007d: 00                                        ; function index
000007e: 11                                        ; string length
000007f: 5f5f 7761 736d 5f63 616c 6c5f 6374 6f72  __wasm_call_ctor
000008f: 73                                       s  ; func name 0
0000090: 01                                        ; function index
0000091: 04                                        ; string length
0000092: 6d61 696e                                main  ; func name 1
000007b: 1a                                        ; FIXUP subsection size
0000096: 02                                        ; local name type
0000097: 00                                        ; subsection size (guess)
0000098: 02                                        ; num functions
0000099: 00                                        ; function index
000009a: 00                                        ; num locals
000009b: 01                                        ; function index
000009c: 00                                        ; num locals
0000097: 05                                        ; FIXUP subsection size
0000074: 28                                        ; FIXUP section size
Совет

Если вы хотите попробовать WebAssembly, загляните в WebAssembly Studio — онлайн-среду разработки для Wasm.

Оцените статью
cdelat.ru
Добавить комментарий