Введение в WebAssembly (WASM)



Книга Введение в WebAssembly (WASM)



WebAssembly был анонсирован в 2015 году. Первой демонстрацией стала реализация игры Unity Angry Bots в Firefox, Google Chrome и Microsoft Edge. Спустя всего 4 года после анонса WebAssembly был признан официальным веб-стандартом и четвертым веб-языком после HTML, CSS и JavaScript, а на сегодняшний день его поддерживают 94% браузеров. 


WebAssembly обеспечивает скорость исполнения в браузере, близкую к нативной, что позволяет переносить в интернет десктопные приложения (например, AutoCAD) и даже видеоигры (например, Doom 3).


Похоже, WebAssembly удалось привлечь к себе всеобщее внимание. Самое время поговорить о нем.


  • Что не так с JavaScript?
  • Что такое WebAssembly?
  • Это просто новый язык программирования, как C и C++?
  • Как работает WebAssembly?
  • Станет ли WASM будущим веб-приложений?

Мы ответим на все эти вопросы и познакомим вас с WebAssembly. Его потенциал способен изменить привычные нам сайты до неузнаваемости!


Что не так с JavaScript?


JavaScript был разработан Бренданом Эйхом в 1995 году для браузера Netscape. Он давал возможность добавлять некоторые взаимодействия к статичным веб-страницам тех дней.


JavaScript  —  интерпретируемый язык программирования с динамической типизацией. Язык является динамически типизированным, если тип переменной проверяется во время выполнения. В чем же проблема с таким типом языка? Посмотрим, что будет, если объявить переменную в C++, который является статически типизированным языком.


int x = 5 ;

Компилятор определяет тип и место в памяти для x. И все это укладывается в одну инструкцию. Однако для такого же присваивания в JavaScript движок должен каждый раз при выполнении программы проверять, является ли переменная целым числом, float или любым другим допустимым типом данных. Таким образом, каждая инструкция в JavaScript должна пройти через несколько проверок типов и преобразований, что замедляет ее выполнение.


Ниже показано, на что JavaScript тратит время в процессе выполнения кода.


Javascript

А теперь посмотрим, на что тратит время WebAssembly.


WebAssembly

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


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




Что такое WebAssembly?


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


Ниже приведен пример суммирующей функции, написанной на C++ и преобразованной в WASM.


Схема VirtualProcessor, преобразующего код C++ в двоичный код, понятный браузеру.



Это просто новый язык программирования, как C и C++?


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


WASM (аббревиатура от WebAssembly) был разработан как целевая платформа для компиляции других языков, позволяющая компилировать серверный код (например, код на C или C++) и выполнять его внутри браузера.




Как работает WebAssembly?


Что такое язык ассемблера (assembly language) и ассемблер (assembler)?


  • Каждый процессор имеет свою архитектуру, например x86 или ARM. Кроме того, процессоры могут понимать только машинный код.
  • Написание машинного кода утомительно, поэтому для данной архитектуры/процессора существует язык ассемблера.
  • Ассемблер преобразует инструкции на языке ассемблера в машинный код, понятный процессору.

Вот как приложения, написанные на языке C, работают на компьютере.



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




Начало работы с WebAssembly


WebAssembly  —  это просто файл с расширением WASM. Его можно рассматривать как модуль, который может быть импортирован в JavaScript-программу.


Взаимодействие файлов в каталоге проекта

Помните: WASM не может взаимодействовать с DOM напрямую. Поэтому вам нужно использовать как JavaScript, так и WASM.


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


1. Напишите приложение на предпочитаемом языке


Напишем для примера небольшую функцию на C++, которая находит n-ое число Фибоначчи.


// Ниже приведена функция, написанная на C++, которая находит n-ое число Фибоначчи
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}

2. Создайте модуль WASM


Теперь нужно преобразовать файл C++ в предварительно скомпилированный WASM-модуль, который будет понятен браузеру.


Существуют различные способы преобразования кода на языке высокого уровня в WASM. В этом руководстве будет использован Web Assembly Explorer.


Шаг 1: скопируйте и вставьте код на C++ и кликните на компиляцию (compile).


Шаг 2: кликните на ассемблер (assembler).


Шаг 3: загрузите файл WASM.



После нажатия на компиляцию и ассемблер (1-й и 2-й шаги)

Скопируйте и вставьте скачанный файл в каталог проекта под названием “math. wasm”.


3. Дистрибутируйте модуль  —  в идеале, используя CDN для низкой задержки (в данном случае будем запускать WASM-файл локально)


Создайте файл script.js и пока оставьте его пустым.


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


Вид каталога проекта

4. Загрузите модуль WASM


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


script.js должен выглядеть следующим образом.


let math;
// Создадим функцию loadWebAssembly, которая преобразует данный файл в двоичный ArrayBuffer.
function loadWebAssembly(fileName) {
return fetch(fileName)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer)) // Buffer converted to Web Assembly
.then(module => {return new WebAssembly.Instance(module) }); // Instance of Web assmebly module is returened
};

// Мы вызываем функцию для math.wasm для данного экземпляра.
loadWebAssembly('math.wasm')
.then(instance => {

});

5. Создайте экземпляр модуля


Теперь перейдем к самой сложной части  —  нам нужно ссылаться на функции, созданные на C++, в JS-файле. Но напрямую ссылаться на эти функции нельзя. Придется использовать имена, которые генерируются в файле WASM. Эти имена записаны в колонке WAT в Web Assembly Explorer.


Используйте имя функции, выделенное на следующей иллюстрации.


Переменная, на которую нужно ссылаться, выделена

В вашем WAT-файле эти имена будут другими.


1-я часть в script.js посвящена загрузке файла WASM.


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


//---------------------------Часть 1--------------------------------------------------------
// Создадим функцию loadWebAssembly, которая преобразует данный файл в двоичный ArrayBuffer.
function loadWebAssembly(fileName) {
return fetch(fileName)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {return new WebAssembly.Instance(module) });
};

// Вызываем функцию для math.wasm
loadWebAssembly('math.wasm')
.then(instance => {
fibc = instance.exports._Z3fibi;

console.log('Call your functions !');
});

//---------------------------PART 2 -----------------------------------------------
// Функция, написанная на Javascript, для числа Фибоначчи
function fibj(n)
{
if (n <= 1)
return n;
return fibj(n-1) + fibj(n-2);
}

// Эта функция дает время, необходимое для выполнения функции C++
function perfoc(n){
var startTime = performance.now()

var c=fibc(n)

var endTime = performance.now()

console.log(`Calculating nth Fibonacci with WASM took ${endTime - startTime} milliseconds,nth fibonacci is ${c}`)

}

// Эта функция дает время, необходимое для функции Javascript
function perfoj(n){
var startTime = performance.now()

var j=fibj(n)

var endTime = performance.now()

console.log(`Calculating nth Fibonacci with JS took ${endTime - startTime} milliseconds, nth fibonacci is ${j}`)

}

6. Вызовите функции экземпляра


Теперь для завершения работы загрузите сайт на localhost!


Примечание: вы не можете запустить index.html напрямую, так как он не загрузит модуль WASM. Используйте что-то вроде расширения Live Server в Visual Studio Code или Xampp, чтобы переместить каталог проекта на localhost.


Теперь перейдите в консоль, чтобы вызвать следующие две функции.


  1. fibj( )→ написана на простом Javascript.
  2. fibc( )→ написана на C++ и затем преобразована в WebAssembly.

Две функции fibc() и fibj()

Ниже приводится сравнение между функцией fibj(), написанной только на JavaScript, и функцией fibc(), импортированной из WebAssembly.



WebAssembly работает молниеносно

Время выполнения fibj( ) и fibc( ) измеряется с помощью функций:


  1. perfoj() → измеряет время выполнения fibj();
  2. perfoc() → измеряет время выполнения yfibc().

Как видно в приведенных выше GIF, время выполнения fibj()(написанной на JavaScript) больше, чем время выполнения fibc()(написанной с использованием WebAssembly).




Станет ли WebAssembly будущим веб-приложений?


С помощью WebAssembly можно разрабатывать высокоэффективные веб-приложения, которые будут работать с производительностью, близкой к нативной. WebAssembly позволит выполнять такие задачи, как обработка видео, 3D-рендеринг, мультимедийные игры, криптографические вычисления и live-приложения AR/VR.


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


Посмотреть проект можно здесь.



517   0  

Comments

    Ничего не найдено.