Статьи

Понимание asm.js

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

история

JavaScript — один из самых популярных языков программирования в мире. Вы можете использовать его в веб-браузерах в качестве клиентского языка. Теперь, с появлением NodeJS, JavaScript также стал популярным языком для серверных приложений. Когда-то (на самом деле, по сей день) транспортеры (компиляторы исходного кода) использовались, чтобы скрыть некоторые уродливые части JavaScript. CoffeeScript, ClojureScript и TypeScript являются одними из наиболее популярных транспортеров.

Транспортеры в основном используют существующий язык (например, C или C ++) или определяют новый язык (например, CoffeeScript). Затем, вместо написания JavaScript, вы можете разрабатывать на другом языке, который транспортер преобразует в JavaScript. В этой статье мы рассмотрим Emscripten, байт-код LLVM для транспортера JavaScript.

Итак, что такое asm.js?

asm.js является строгим подмножеством JavaScript. Это не новый язык. asm.js — это ограниченный набор определений, которые обеспечивают хорошие характеристики производительности. Эти определения могут быть объединены, как инструкции на ассемблере, для создания очень быстрых приложений JavaScript. asm.js использует некоторые функции JavaScript низкого уровня, такие как Typed Arrays. Он не использует никаких плагинов или модулей для запуска кода JavaScript, что делает его обратно совместимым.

Как это устроено

Основная идея обычно заключается в более строгом использовании JavaScript. Например, устранение динамических типов. Чтобы привести пример, мы собираемся объявить переменную и присвоить ей целочисленное значение. Затем мы объявляем другую переменную и назначаем предыдущую новую. Ниже вы найдете пример в стандартном JavaScript.

var first = 5; var second = first; 

Соответствующий синтаксис asm.js для кода, представленного выше, выглядит следующим образом:

 var first = 5; //By using a bitwise operator, we make sure that the value is 32-bit integer var second = first | 0; 

Единственная разница между первым и вторым примерами кода — это побитовый оператор ИЛИ в последней строке примера asm.js. Используя побитовый оператор, мы конвертируем значение first переменной в 32-битное целое число. Это гарантирует, что second всегда обрабатывается как 32-разрядное целое число. В asm.js есть ряд других похожих правил. Комбинируя эти правила с обычным JavaScript, можно создать гораздо более быстрый код. Для получения дополнительной информации об этих правилах и о том, как они работают, обратитесь к спецификации asm.js.

Стоит отметить, что писать код asm.js от руки не очень хорошая идея. Результат будет трудно поддерживать и отнимать много времени. Исходя из этого наблюдения, остается вопрос: как мы можем разрабатывать приложения, используя asm.js?

Хорошей новостью является то, что существует несколько инструментов для генерации кода JavaScript в соответствии со спецификацией asm.js из других языков, таких как C или C ++. В этой статье мы сосредоточимся на Emscripten, но имейте в виду, что существует ряд подобных инструментов.

Итак, что такое Emscripten? Ответ в том, что это компилятор LLVM-to-JavaScript. Emscripten принимает байт-код LLVM и преобразует их в asm.js JavaScript. Итак, как вы генерируете байт-код LLVM? Вы можете использовать Clang для преобразования кодов C / C ++ в LLVM! Чтобы лучше понять этот процесс, рассмотрите следующую схему:

CPP to JS Workflow

Вот шаги для генерации кода JavaScript с использованием Emscripten:
1. Создайте приложение на C / C ++.
2. Скомпилируйте его, используя Clang, для генерации байт-кода LLVM.
3. Передайте байт-код Emscripten, чтобы получить код JavaScript.

Стоит отметить, что Emscripten выполняет последние два шага самостоятельно. Таким образом, единственное, что вам нужно сделать, это передать код C / C ++ в Emscripten и получить вывод JavaScript.

Привет, мир

Давайте напишем простую программу на C ++ и преобразуем ее в JavaScript-приложение на основе asm.js. Ниже приведен фрагмент кода C ++, который вычисляет число Фибоначчи для n=45 .

 #include <stdio.h> int fib(int x) { if (x < 2) { return 1; } else { return fib(x - 1) + fib(x - 2); } } int main() { int result = fib(45); printf("%d\n", result); return 1; } 

Как видите, алгоритм довольно прост и понятен. Чтобы преобразовать этот код C ++ в JavaScript, вам нужно сначала установить Emscripten. Обратитесь к вики Emscripten за инструкциями по установке. После установки Emscripten вы можете просто преобразовать код C ++ с помощью следующей команды.

 ./emcc -O1 -s ASM_JS=1 ./hello_world.cpp 

ASM_JS свойства ASM_JS значение 1 , вы заставляете Emscripten ASM_JS код JavaScript на основе спецификации asm.js. После выполнения команды вы получите файл a.out.js Это файл JavaScript, который создается из вашего кода C ++. Чтобы выполнить соответствующий файл JavaScript, вы можете установить Node.js и выполнить следующую команду.

 node ./a.out.js 

Выполнив вышеуказанную команду, вы увидите вывод приложения. Поздравляем, вы сделали свое первое приложение asm.js.

Давайте посмотрим на тест

В этом разделе мы предоставляем сравнение времени выполнения нативного кода JavaScript для примера Фибоначчи, представленного выше, с версией на основе asm.js. Чтобы получить более подходящее изображение для этого сравнения, мы компилируем код C ++ с использованием компилятора Clang и выполняем соответствующий сгенерированный собственный код. Таким образом, мы можем сравнить три разных среды: (1) обычный JavaScript, (2) код asm.js и (3) собственное приложение. Чтобы скомпилировать код C ++ с помощью clang, просто введите следующую команду:

 clang ./hello_world.cpp 

Это создаст файл a.out содержащий ваш собственный исполняемый файл.

Обычный пример JavaScript показан в следующем коде.

 var result = 0; function fib(x) { if (x < 2) { return 1; } else { return fib(x - 1) + fib(x - 2); } } result = fib(45); console.log(result); 

Мы можем запустить нормальные примеры JavaScript и asm.js, используя следующие команды.

 node ./handmade.js node ./a.out.js 

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

 ./a.out 

Полученное время выполнения показано на следующем рисунке. Эксперименты проводились на операционной системе OS X 10.9.2, использующей последнюю версию Clang, Node.js и Emscripten.

JS против asm.js против Native Performance

Вывод

В этой статье мы говорили о asm.js, одной из спецификаций Mozilla для создания низкоуровневой среды JavaScript. asm.js — более быстрое подмножество языка программирования JavaScript. Мы изучили Emscripten, который является инструментом для преобразования кода C / C ++ в байт-код LLVM, а затем в код JavaScript asm.js. Мы также создали очень простую программу «Hello world» с использованием кода C ++, который мы преобразовали в asm.js с помощью Emscripten. Кроме того, мы предоставили несколько тестов, чтобы продемонстрировать существенную разницу в производительности между обычными и основанными на asm.js JavaScript-кодами. Следует отметить, что asm.js все еще находится в стадии разработки, и в будущем прирост производительности должен стать еще лучше.