Знакомство с WebAssembly


    Эта статья основана на моём выступлении на ITSubbotnik, прошедшем в Рязани 14 октября 2017 года. На русском пока что довольно мало материала на эту тему, надеюсь что статья будет вам полезна.


    Disclaimer: Автор не является экспертом ни в WebAssembly, ни в JavaScript. Данная статья есть компиляция мыслей и идей, полученных из выступлений других людей на данную тему, плюс эпизодического опыта изучения WebAssembly в течение нескольких месяцев.


    Что такое WebAssembly?


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


    Проблема


    Давайте разберёмся сначала, какую проблему или задачу пытались решить, создавая WebAssembly. Проблема далеко не новая, фактически это — быстро исполнять код в браузере. Но не всё так просто, постепенно так сложилось, что помимо самой проблемы, у нас есть ещё несколько сопутствующих требований:


    • Быстрее чем JavaScript — в идеале, со скоростью света родного кода нашего процессора.
    • Zero configuration — решение «из коробки», без установки, нужен только браузер.
    • Безопасно — новая технология не должна создавать новых угроз.
    • Кросс-платформенно — у нас есть несколько платформ, включая мобильные, несколько операционных систем.
    • Удобно для разработчиков — нужны удобные средства разработки и отладки.

    Ситуация


    В попытке решения этой проблемы у нас есть один победитель, и это JavaScript.


    Проигравшие (далеко не полный список):


    • ActiveX — технология позволяла делать вообще всё, безо всякого sandbox, соответственно представляла реальную угрозу безопасности.
    • Flash — в 2017 году Adobe объявила о планах прекращения поддержки Flash.
    • Silverlight
      и другие плагины

    Другие попытки решения:


    • NaCl — Native Client — инициатива от Google, появилась в 2011 году; не нашла поддержки других браузеров кроме Chrome.
    • PNaCl — Portable Native Client — LLVM IR subset.
    • asm.js — Mozilla, появилась в 2013 году — ниже рассмотрим подробнее.

    В целом, все попытки решения можно разбить на две группы:


    Решение 1: Родной код прямо в браузере


    Примеры: ActiveX, NaCl
    Что плохо: нет портируемости, потенциальные или реальные проблемы с безопасностью.


    Решение 2: Код для виртуальной машины


    Примеры: Java Applets, Silverlight и др.
    Что плохо: нужен плагин и/или runtime ⇒ нет zero configuration
    В целом, если вы хотите обеспечить кросс-платформенное выполнение вашего кода, то виртуальная машина это правильный подход.


    Что не так с JavaScript?


    С JavaScript всё хорошо. Но если смотреть на рост его производительности с годами, то мы увидим что он сейчас находится на втором «плато» S-образной кривой. Сначала производительность была небольшой и росла постепенно, с появлением V8 мы увидели резкий скачок, который уже достаточно давно вновь перешёл в плавный рост.

    (Картинка из статьи An Abridged Cartoon Introduction To WebAssembly by Lin Clark.)


    Посмотрим как работают современные движки JavaScript.


    Прежде всего, исходный код (текст на JS) проходит через парсер, в результате возникает внутреннее представление кода — абстрактное синтаксическое дерево. Дальше работает интерпретатор. Отдельные функции при исполнении преобразуются в байт-код — по сути, последовательность вызовов внутренних функций интерпретатора. При этом накапливается статистика использования JS-функций. Если для какой-то отдельной функции преоделён порог вызовов, то принимается решение о том, что её нужно оптимизировать и она передаётся компилятору. Компилятор генерирует машинный код, который сильно завязан на типы входных значений.



    Допустим, у нас есть функция с двумя аргументами: foo(a, b), и мы вызываем её много раз с числовыми значениями параметров. В некоторый момент функция будет передана компилятору и станет выполняться быстрее. Допустим, мы вызовем её со строковым аргументом. В результате, движок выполнит «деоптимизацию»: передаст функцию от компилятора обратно интерпретатору, а готовый машинный код будет выброшен.


    Что я хочу этим сказать? Разработчики JavaScript движков делают отличную работу и спасибо им за это. JavaScript вовсе не плох, но у него есть внутренние ограничения, которые уже не позволят сделать его радикально быстрее.


    asm.js


    Ещё одна интересная инициатива, уже от Mozilla Foundation, которая подводит нас вплотную к теме WebAssembly. Появилась она в 2010 году, а в 2013 стала публично доступна.


    Идея заключается в том, что создано подмножество JavaScript, в которое можно компилировать код из C и C++ с помощью специального компилятора Emscripten.


    Поскольку это подмножество JavaScript, то такой код будет исполняться в любом браузере. Кроме того, основные современные браузеры уже давно умеют быстро распознавать asm.js и эффективно компилировать его в родной код процессора. В сравнении с родным кодом, полученным непосредственно из C/C++, код полученный из asm.js код медленнее всего в 1,5-2 раза (50-67 %).


    Для простейшей функции на C/C++ код asm.js выглядит так:

    Здесь 'use asm' это директива, показывающая JS-движку что код ниже это asm.js, и конструкции вида |0 показывают, что работа идёт с целыми числами (побитовое ИЛИ с нулевым значением обнуляет дробную часть Number).


    Цели разработки WebAssembly


    • Скорость — почти как родной код.
    • Эффективность — бинарный формат, быстрый парсинг и компиляция.
    • Портируемость — все браузеры и операционные системы.
    • Безопасность — запуск в sandbox.
    • Удобство отладки — поддержка отладки в браузерах, отладчик есть уже сейчас.
    • Открытый стандарт — то есть это уже не инициатива отдельной компании, пытающейся «перетянуть одеяло на себя». Стандарт уже принят, в 2017 году.

    Так что же такое WebAssembly?


    • Бинарный формат
    • НЕ язык программирования, а байт-код
      Мы же не называем Java-байткод языком программирования.
    • Загружается в браузер и исполняется в браузере.
      Формально, WebAssembly исполняется JavaScript-движком, а не самим браузером, поэтому есть и другие варианты исполнения, например, под NodeJS.
    • Исполняется виртуальной машиной
      Это простая стековая машина с памятью, простота позволяет легко реализовать её для любого современного процессора.
    • НЕ имеет ничего общего с Web, кроме того что общается с внешним миром через JavaScript.
      Действительно, WebAssembly это просто виртуальная машина, имеющая память и исполняющая инструкции.

    С чего начать? Hello World


    Освоение WebAssembly я очень советую начать с онлайнового инструмента WasmFiddle.
    (Сам я начал с Emscripten и понял свою ошибку лишь спустя время.)


    Интерфейс WasmFiddle:



    Слева вверху исходный код, слева внизу результат компиляции по кнопке Build (сейчас видно текстовое представление), справа вверху код для запуска и справа внизу результат запуска по кнопке Run.


    Текст примера на C/C++

    В качестве примера я использовал простой код для расчёта числа Фибоначчи (да, опять он :), не сказать чтобы хороший код, просто первый попавшийся нагугленый вариант:


    int fib(int n)
    {
        if (n == 0) { return 0; }
        else
        {
            if ((n == -1) || (n == 1)) { return 1; }
            else 
            {
                if (n > 0) { return fib(n - 1) + fib(n - 2); }
                else { return fib(n + 2) - fib(n + 1); }
            }
        }
    }

    Немного про текстовое представление (WAST). Как уже говорилось, WebAssembly это бинарный формат, на выходе компиляции мы получаем WASM-файл. Текстовое представление всегда можно получить из WASM-файла, оно позволяет разобраться в том, что именно содержит сборка, какие таблицы и код. Также это представление используется для отладки.


    В данном случае, по текстовому представлению мы видим, что выделяется 1 страница памяти (каждая страница = 64 Кбайт), наружу видны (экспортируются) память и функция fib, а дальше идёт определение этой функции, то есть собственно её реализация.


    Текстовое представление (WAST)

    Начало текстового представления этой сборки выглядит так:


    (module
      (table 0 anyfunc)
      (memory $0 1)
      (data (i32.const 12) "\01\00\00\00\00\00\00\00\01\00\00\00")
      (export "memory" (memory $0))
      (export "fib" (func $fib))
      (func $fib (param $0 i32) (result i32)
        (local $1 i32)
        (block $label$0
          (br_if $label$0
            (i32.ge_u
              (tee_local $1
                (i32.add
                  (get_local $0)
                  (i32.const 1)
                )
              )
              (i32.const 3)
            )
          )
          (return
            (i32.load
              (i32.add
                (i32.shl
                  (get_local $1)
                  (i32.const 2)
                )
                (i32.const 12)
              )
            )
    ...

    Если собрать всё вместе, то минимальный JavaScript-код для запуска примера выглядит примерно так:


    var wasmCode = new Uint8Array(
    [0,97,115,109,1,0,0,0,1,134,128,128,128,0,1,96,1,127,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,144,128,128,128,0,2,6,109,101,109,111,114,121,2,0,3,102,105,98,0,0,10,203,128,128,128,0,1,197,128,128,128,0,1,1,127,2,64,32,0,65,1,106,34,1,65,3,79,13,0,32,1,65,2,116,65,12,106,40,2,0,15,11,2,64,32,0,65,1,72,13,0,32,0,65,127,106,16,0,32,0,65,126,106,16,0,106,15,11,32,0,65,2,106,16,0,32,1,16,0,107,11,11,146,128,128,128,0,1,0,65,12,11,12,1,0,0,0,0,0,0,0,1,0,0,0]);
    var wasmModule = new WebAssembly.Module(wasmCode);
    var wasmInstance = new WebAssembly.Instance(wasmModule, []);
    console.log(wasmInstance.exports.fib(10));

    Здесь готовый WASM описывается в коде в виде массива чисел, но в реальной жизни конечно WASM-файл будет довольно намного больше, и мы будем подгружать его с сервера.


    Исполнение WebAssembly в браузере выглядит так. Браузер как обычно загружает HTML-страницу, с которой выполняется JavaScript, который уже выполняет загрузку WebAssembly — получается «модуль» (WebAssembly module), затем создаёт экземпляр модуля, после чего можно вызывать для этого экземпляра экспортируемые им функции.



    Обратите внимание здесь на серую стрелку: изнутри WebAssembly можно вызывать функции JavaScript. Рассмотрим это подробнее на диаграмме последовательности:



    Здесь мы сначала из JavaScript вызываем WebAssembly, затем из WebAssembly вызываем функцию JavaScript.


    Во втором вызове здесь я показал то, как WebAssembly пользуется любыми API (например, DOM / WebGL итд.). Это возможно, но не напрямую, такие вызовы тоже происходят только через JavaScript. Очевидно, здесь возникает «бутылочное горлышко»: если мы будем интенсивно работать с API из WASM, то будем терять много времени на «прокидывании» этих вызовов через JavaScript.


    Модель памяти WebAssembly очень проста. Это плоский «кусок» памяти, в котором находится код программы, глобальные переменные, стек и куча. Есть возможность сделать так, чтобы память была расширяемой, то если если при очередном выделении памяти нам не хватает места, то верхняя граница памяти автоматически увеличивается.



    Весь блок памяти доступен из JavaScript, просто как массив байтов (и кроме того, как массив 16- и 32-разрядных слов, как массив 16- и 32-разрядных float-значений). Причём, память из JavaScript доступна как на чтение так и на запись.


    Emscripten


    Emscripten это основной компилятор для получения asm.js и WebAssembly из C/C++. (Существуют также компиляторы в WASM из других языков, например из Rust и TypeScript.) Здесь я буду рассматривать использование Emscripten под Windows, но не думаю что для других систем будут существенные различия.



    LLVM


    Говоря об Emscripten, стоит немного рассказать о Low Level Virtual Machine (LLVM).



    LLVM это семейство компиляторов. Основная идея LLVM это разделение компиляции на frontend и backend. Frontend-компилятор занимается компиляцией из исходного кода во внутреннее представление (Intermediate Representation, IR). IR это код для некоторой виртуальной машины. Backend-компилятор занимается уже преобразованием IR в код для конкретной платформы, например, часто используется backend для x86 и x86-64. Если нужен компилятор с другого языка программирования, то пишется только новый frontend. Если нужна компиляция под новую платформу, то пишется новый backend.


    Emscripten задействует LLVM для компиляции из C/C++, и предоставляет свои backend-компиляторы для сборки в asm.js и WebAssembly.


    Установка Emscripten


    Установка Emscripten проходит довольно просто, в моём случае это было под Windows, и мне даже не понадобилось ничего компилировать из исходников.


    1. Загружаем отсюда: http://emscripten.org/
    2. Распаковываем в отдельную папку, в моём случае C:\bin\emsdk
    3. Открываем командную строку, переходим в папку emsdk и выполняем три команды:

    emsdk update
    emsdk install latest
    emsdk activate latest

    Всё установлено и настроено, можем компилировать. Выполнив команду emsdk list, вы получите список всех версий всех инструментов, доступных для установки, с отметками того что выбрано сейчас.


    Компиляция в asm.js


    Посмотрим как можно собрать код с помощью Emscripten, начнём с asm.js.


    Пример для Emscripten

    Пример тот же что и выше, немного модифицированный для Emscripten (fib.c):


    # include <emscripten/emscripten.h>
    
    int EMSCRIPTEN_KEEPALIVE fib(int n)
    {
        if (n == 0) { return 0; }
        else
        {
            if ((n == -1) || (n == 1)) { return 1; }
            else 
            {
                if (n > 0) { return fib(n - 1) + fib(n - 2); }
                else { return fib(n + 2) - fib(n + 1); }
            }
        }
    }
    
    int main()
    {
        printf("fib(10) = %d\n", fib(10));
        return 0;
    }

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


    Для компиляции я использую следующий командный файл:


    SET EMSDKPATH=C:\bin\emsdk
    
    CALL %EMSDKPATH%\emsdk_env.bat
    
    emcc -O1 fib.c -o fib.html -fno-exceptions -fno-rtti

    Здесь emcc это собственно Emscripten, -O1 опция оптимизации, fib.c что компилировать, -o fib.html куда компилировать, и дальше опции -f чтобы отключить то что нам не нужно.


    Что мы получаем на выходе

    На выходе компиляции мы получаем HTML-файл (fib.html), включающий JavaScript для запуска скомпилированного кода:


    Также мы получили файл fib.js, в недрах которого можно найти функцию fib() и её вызов в main():


    Кроме того, генерируется двоичный файл fib.html.mem — это «образ памяти», то как выглядит память перед запуском программы, здесь все константы и глобальные переменные.


    Открыв fib.html мы увидим вот такую картину:



    Это стандартный вид результата для Emscripten. Чёрный прямоугольник по центру это вывод «консоли» (stdout), туда в частности выводится printf(). Чёрный прямоугольник вверху это canvas; Emscripten не знает нужен ли он вам, но создаёт его здесь на всякий случай.


    Компиляция в WebAssembly


    Для компиляции в WebAssembly нам вообще не нужно менять исходник на C/C++ (и это прекрасно!).


    Мы немного изменяем только командную строку вызова компилятора:


    SET EMSDKPATH=C:\bin\emsdk
    
    CALL %EMSDKPATH%\emsdk_env.bat
    
    emcc -O1 fib.c -g -o fib.html -s WASM=1 -s NO_EXIT_RUNTIME=1 -s NO_FILESYSTEM=1 -fno-exceptions -fno-rtti --llvm-lto 1

    Главное отличие здесь это добавлении опции -s WASM=1. Остальные -s и -f добавлены в попытках объяснить Emscripten что нам НЕ нужно. Emscripten умеет слишком много, и поэтому «на всякий случай», «вдруг понадобится» он много чего добавляет в результирующие файлы.


    В результате компиляции мы также получаем fib.html, плюс fib.js (набор сервисных функций Emscripten), плюс наконец-то fib.wasm:



    В начале WASM-файла стоит байт 00 и затем символы «asm», по этим первым четырём байтам можно определить, что мы загружаем именно wasm, а не какую-нибудь страницу-заглушку с кодом ошибки. Следующие 4 байта это номер версии, в данном случае 1.0. Отдельного файла для образа памяти не генерируется, константы и глобальные переменные включены в тот же WASM-файл.


    Скриншот с результатом я здесь приводить не буду, он выглядит один-в-один точно так же как для примера с asm.js.


    Отладка WebAssembly в Chrome

    Давайте посмотрим что у нас есть в плане отладки. Открыв инструменты разработчика Chrome (F12), переходим в Sources и там увидим новый раздел «wasm», в котором среди набора блоков можем найти нашу функцию, можем поставить там точку останова, остановиться на ней и пошагать в отладчике.


    Как видите, для отладки используется текстовое представление (WAST), о котором я говорил выше.


    Теперь давайте откомпилируем тот же код с отладочной информацией, для этого в командную строку emcc добавим опцию -g. В результате компилятор сгенерирует нам ещё два файла: fib.wast и fib.html.map.
    В файле текстового представления fib.wast есть не только код, но и отсылки к исходнику на C/C++:


     (func $_fib (param $0 i32) (result i32)
      (local $1 i32)
      ;; fib.c:11
      (block $switch-default

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


    Возможности Emscripten


    Emscripten развивается с 2010 года и уже много чего умеет. В данном случае речь уже не о компиляторе, а о поддержке популярных библиотек, используемых из кода на C/C++. Поддерживаются:


    • Стандартные библиотеки С/С++
    • SDL 2 — ввод (клавиатура/мышь/джойстики), видео, звук
    • OpenGL, EGL — 2D/3D-графика, реализуются через WebGL
    • OpenAL — звук

    И другие возможности:


    • Эмуляция файловой системы — многие программы на C/C++ интенсивно работают с файлами, можно оставить этот код как есть; см. Emscripten — File System Overview
    • EM_ASM("JS code") — выполнение произвольного JavaScript-кода, сформированного в виде строки
    • Workers

    Более сложный пример


    У меня есть свой хобби-проект эмулятора старого советского компьютера, написанный на C++, я его описывал вот в этой статье. С тех пор я успел его несколько дописать, а также портировать под Qt (Windows/MacOS/Linux). Так что у меня уже было выделено ядро эмуляции (~280 Кбайт кода, ~7 килострок), которое собиралось под разными компиляторами. Собственно я и начал изучение WebAssembly с того, что компилировал этот эмулятор с помощью Emscripten. До первого удачного запуска у меня ушло два вечера после работы, я считаю это неплохой результат, говорящий о том, что порог вхождения в тему относительно низкий. Большая часть работы была связана с JavaScript: как из JS вызывать методы WASM, как передавать параметры, как отрисовывать canvas итп.


    Кстати, экран эмулируемой машины формируется полностью внутри WASM, в виде сплошного блока памяти, с форматом «пикселей», подходящем для canvas. Наружу в JavaScript передаётся только адрес готового «экрана». В JavaScript остаётся только скопировать этот блок памяти в canvas.


    Работающий эмулятор можно увидеть тут, ну и исходники тоже доступны.


    Скриншот эмулятора собранного как WASM


    Также в какой-то момент я решил «для полноты картины» собрать этот эмулятор ещё и под asm.js. Сделал себе кофе, выделил на это пару свободных часов, и меньше чем через 15 минут эмулятор уже заработал. Это было как бы неожиданно. Фактически, всё что пришлось сделать, это посмотреть различия в сгенерированном HTML-файле и перенести добавленный JavaScript-блок куда нужно. Различие было лишь в том, что для asm.js должен загружаться .mem-файл, образ памяти с константами и глобальными переменными. В остальном все вызовы выполнялись точно так же, и готовая страница выглядела и работала в точности так же, разве что немного медленнее.


    Итак, подводя итоги по Emscripten. Я убедился в том, что из одного и того же кода он генерирует результат в виде asm.js и в виде WebAssembly, полученный результат выглядит и работает в точности одинаково (кроме скорости конечно). Порог вхождения до получения реального результата оказался относительно низким.


    С другой стороны, Emscripten довольно сложный и «нафаршированный» инструмент. В результат компиляции он включает массу вещей которых вы не ожидаете, но которые могут вам пригодится. Поэтому даже для небольших по объёму исходников генерируется большой объём результирующего кода. Часть таких вещей можно отключить опциями командной строки, часть нет.


    Думаю что не стоит начинать освоение WebAssembly сразу с Emscripten, по той причине что довольно сложно для себя отделить то что даёт Emscripten от того что имеет WASM «из коробки». Но на реальных проектах Emscripten более чем полезен, именно за счёт тех возможностей, которые он предоставляет разработчику.


    Текущее состояние WebAssembly


    Новости WebAssembly в 2017 году:



    Поддержка в браузерах


    На начало октября 2017 года ситуация выглядела примерно так:



    Версия Edge привязана к версии операционной системы. Вместе с Windows 10 Fall Creators Update мы получаем Edge 16, в котором WebAssembly работает сразу, уже не нужно ничего включать в настройках.


    Для браузеров, не поддерживающих WebAssembly, предполагается использовать т. н. «polyfill», то есть автоматическое преобразование WASM в код, который может выполняться в данном браузере. В частности, был сделан прототип, эффективно выполняющий преобразование WebAssembly в asm.js. Но пока я не видел примеров реального применения такого подхода.


    Будущее WebAssembly


    Ряд вещей над которыми команда WebAssembly работает сейчас:


    • Threads
      Текущая реализация WASM полностью однопоточная.
    • SIMD
      Поддержка SIMD позволит существенно ускорить однотипную обработку на больших объёмах данных — изображения, видео, звук.
    • Exceptions
    • Garbage Collection
      Реализация GC позволит компилировать под WASM с языков с автоматическим управлением памятью. Это возможно и сейчас, но только в варианте когда GC реализуется на C/C++ внутри WASM.

    Производительность


    Вопрос по производительности на самом деле довольно сложный. Потому что не всегда WebAssembly работает быстрее того же JavaScript или asm.js. Например, посмотрите сравнения из JavaScript vs WebAssembly easy benchmark. На первом же тесте collisionDetection у меня получается что WASM даёт 88% от JS. А допустим на следующем тесте Fibonacci WASM выдаёт гораздо лучший результат, в 3 раза быстрее чем JS.


    Отмечу здесь только несколько моментов, влияющих на скорость, реально их конечно гораздо больше.


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


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


    WebAssembly может существенно выигрывать за счёт типа целых переменных. В JS у нас есть только тип Number, фактически всегда 64-разрядный с плавающей точкой, и целые числа это плавающее число без дробной части. При компиляции в JS-движке, для целых чисел используется 64-разрядный целый тип. В WASM мы сами выбираем разрядность типа, и если мы используем 32-разрядный целый тип, операции над которым немного быстрее чем над 64-разрядным целым, то мы получаем здесь «нечестное» преимущество в скорости вычислений.


    В целом, у меня сложилось мнение, что нет такого что «в среднем WebAssembly обеспечивает 10-15% прирост скорости», нет никакого «в среднем», для каждого алгоритма нужно тестом определять, получите ли вы прирост скорости, применив WASM. Но в целом, можно предсказать что для интенсивных вычислений, скорее всего, WebAssembly даст какой-то более или менее ощутимый прирост производительности. Ну и кроме того, видно что уже даже за последние полгода скорость WASM несколько выросла с выходом новых версий браузеров.


    Заключение


    Применение WebAssembly


    • Уменьшить время загрузки
    • Поднять скорость вычислений
    • Использовать готовый код на C/C++

    Варианты использования


    1. Применять WASM уже сейчас, если вы к этому готовы
    2. Использовать asm.js сейчас, перейти на WASM в будущем
    3. Отдавать asm.js либо WASM, в зависимости от браузера

    Ссылки


    Материала по теме очень много, но он практически весь на английском. Здесь я собрал несколько ссылок которые считаю наиболее полезными.


    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 111
    • 0

      Вы не могли бы пояснить, за счет чего планируется получить безопасность?

      • +2
        Как я это понимаю — очень простая модель виртуальной машины, нужно контролировать только выход за границы выделенной области памяти, что и делается при каждом обращении к памяти.
        • –1

          Хм. Это как бы ни о чем. Ну да, простой байткод — надежный байткод, но:


          • значит ли это, что доступа у этого байткода никуда не будет? Ну т.е., страницы с других доменов, веб-камера, файлы, и все прочие ресурсы, которые в песочнице должны быть доступны не всем, и как правило только свои?
          • если доступ все же будет, то должна быть кроме простоты какая-то модель безопасности. А ее что-то не видно (я тут спрашиваю, а не утверждаю). Какие-то модели прав для источников кода — коду вот отсюда можно то и это, а коду отсюда — нельзя ничего.
          • а если не будет — то чем тогда байткод вообще будет заниматься?
          • +1
            WASM в его текущей реализации взаимодействует _только_ с JavaScript, а значит находится в рамках его ограничений по безопасности. К этому как бы сложно что-то добавить. При загрузке .wasm-файла на страницу действуют те же ограничения что для любых других ресурсов.
            Вообще я конечно не специалист по web security, может я просто не понимаю вопроса.
            Обратите внимание что в списке post-MVP features (т.е. то что сейчас в разработке) обозначена Web Content Security Policy.
            • 0

              Ну, в текущей много чего нет, включая по-моему и DOM...

            • +1
              При начальной движухе вебасм позиционировался чисто как средство для тяжёлых вычислений. Соответственно, простейшая модель безопасности при максимальной изоляции. Вроде вообще на самом старте говорилось исключительно о вызове функций, по сути о расширении стандартной библиотеки нативными (после копмиляции байт-кода) пользовательскими чистыми функциями. Даже возможность вызывать из вебасма джс позже добавили, кажется.
              • 0

                Ну, если это числодробилка — то с чего тут обещать безопасность? 2*2 и так всегда было безопасно :) Хотя если вдуматься, при наличии доступа к потокам и памяти устроить DoS уже должно быть возможно.

                • 0
                  2*2 и так всегда было безопасно :)

                  Не всегда :) Например, переполнение стэка может быть с занесением 2 в область с чувствительными данными или кодом.

                  • +1
                    WebAssembly тут строг и кидает ошибку.
                    • 0

                      Позаботились о безопасности для подобных случаев.

                      • 0

                        А кстати, ошибку… exceptions же вроде пока нет, это в каком смысле, в том что wasm не может по своей инициативе выкинуть? Т.е. что будет дальше, функция завершается, в javascript в месте вызова можно написать try/catch?

                        • 0
                          Программа завершается, JavaScript может об этом узнать. Никаких «обработчиков» не предусмотрено, так как это — нештатная ситуация.

                          Отчасти проблема безопасности Java заключалась в том, что она пыталась такие случаи отловить и дать программе шанс как-то восстановиться. Код получался сложным и в нём была куча дыр.

                          Код «если у нас всё плохо, то закрыть нафиг процесс не дав никому никаких шансов» — гораздо проще и, будем надеяться, правильнее и безошибочнее.
                          • 0
                            А предусмотрены ли хоть какие-то callback'и для обратной связи? А то сдох твой код и поминай как звали — ни callstack'а ничего.
                            • 0
                              В стандарте нет, в реализациях обычно можно отследить что-нибудь в консоли.

                              Как уже говорилось — очень вынушительный процент дыр в Java как раз в этом месте, так что в «боевом режиме» — это перебор.

                              А на тему «сдох твой код и поминай как звали» — так в Android'е и в ChromeOS, к примеру, твой процесс просто могут закрыть «без предупреждения» из-за того, что кто-то игрушку захотел запустить, так что ваша программа по-любому должна отрабатывать эту сутацию, а если она к ней готова — то зачем лишний, потенциально весьме небезопасный, код?
                              • 0
                                В стандарте нет, в реализациях обычно можно отследить что-нибудь в консоли.

                                Так это на клиентской машине, а мне-то, разработчику, как об этом узнать с подробностями в виде дампов всяких и тому подобного?

                                А на тему «сдох твой код и поминай как звали» — так в Android'е и в ChromeOS, к примеру, твой процесс просто могут закрыть «без предупреждения» из-за того, что кто-то игрушку захотел запустить, так что ваша программа по-любому должна отрабатывать эту сутацию, а если она к ней готова — то зачем лишний, потенциально весьме небезопасный, код?

                                Не, не в этом прикол. Если приложение убито из-за ошибки какой-то в твоем коде — как об этом узнать?
                                • 0
                                  Так это на клиентской машине, а мне-то, разработчику, как об этом узнать с подробностями в виде дампов всяких и тому подобного?
                                  От браузера зависит. ChromeOS предоставляет интерфейс, вроде у Microsoft'а тоже что-то такое есть.

                                  Не, не в этом прикол. Если приложение убито из-за ошибки какой-то в твоем коде — как об этом узнать?
                                  Запустить на своей машине? Самый надёжный метод, однако.
                                  • 0
                                    Запустить на своей машине? Самый надёжный метод, однако.

                                    Заканчивается это тем, что на твоей машине все ок, а у клиента — нет. (Ну, я из своего мира десктопных приложений сужу).
                          • 0
                            Т.к. мы приложение на C++ пишем, а потом компилируем через emscripten, то обычно все встает колом. Ошибка ловится через глобальный обработчик window.onerror и отправляется к нам на анализ.
            • 0
              А можно помучать нубскими вопросами? Я так и не понял: wasm- это компиляция javascript в байткод или преобразования кода c++ в байткод, понятный браузеру и javascript или возможно оба варианта? Скажем, есть проект на плюсах, который использует внутрисистемные библиотеки, как код будет выполняться на стороне клиента? полная конвертация в бинарник wasm вместе с библиотеками и выплевывание кода в браузере клиента или какие-то еще шаманские действия со стороны javascript будут выполняться?
              • 0
                WASM это просто байткод для виртуальной машины. Он появляется в результате компиляции.
                Из компиляторов самый продвинутый это Emscripten, он собирает WASM из C/C++. Кроме того, в Emscripten для WASM уже адаптировано много стандартных и популярных библиотек. При сборке кода в WASM происходит сборка как в варианте со «статической компиляцией» — весь используемый код всех библиотек помещается внутрь, размер WASM при этом конечно может получиться большим. Для «поддержки» работы WASM Emscripten также генерит кучу обёрток/клеевого кода на JavaScript.
                Помимо WASM, в качетве альтернативы, Emscripten умеет компилить в asm.js, результат работает так же как WASM (возможно, немного медленнее) и работает на бОльшем наборе браузеров.
                Есть и другие компиляторы кроме Emscripten, например, AssemblyScript компилирует в WASM из TypeScript. С деталями его работы я НЕ знаком, не приходилось использовать.
                • –1
                  Ага, значит получается, wasm- это просто технология исполнения кода в браузере… А как тогда дела обстоят с DOM? Если ли возможность обмена данными между wasm и javascript? Или все пока выглядит, как будто код исполняется в отдельном фрейме и он полностью изолирован от остальной структуры страницы и, соответственно, данных?
                  • 0
                    между wasm и javascript

                    спокойно вызывается

                    • +1
                      Да, изолирован.
                      Можно обращаться к DOM через JS, и это будет подтормаживать.
                      И это всё есть в статье :)
                      • 0
                        Через вызов JS всё можно что и в JS.
                        изначально акцента похоже на работе с DOM и т.п. не делалось — потому не только неубыстрит а и немного притормозит
                      • 0
                        Есть и другие компиляторы кроме Emscripten

                        Я бы сказал, что их уже довольно много. Rust вроде можно, под LLVM какая-то поддержка wasm как целевой платформы (а значит потенциально сразу много языков). Есть там всякие проблемы, типа той, что нет пока GC, и если каком-то языку это нужно — надо тащить реализацию с собой. Но в целом выглядит так, что как только реализация самой виртуальной машины устоится, есть шанс получить сразу много компиляторов.

                        • +1

                          Мы Emscripten'ом собираем сразу в asm.js и wasm, в зависимости от того, поддерживает браузер wasm, загружаем wasm или asm.js код.

                          • 0
                            Не могли бы вы рассказать о задачах, которые вы решаете с использованием этой технологии?
                            • 0
                              Все просто. Есть кросс-платформенное приложение на C++. Единый код под Windows XP/10, GNU/Linux, Mac OS X. Он же компилируется под Asm.js и WebAssembly и работает в браузере.
                          • 0
                            WASM это просто байткод для виртуальной машины.

                            Сама виртуальная машина — нативная или реализована на JS?
                            • 0
                              Сама виртуальная машина внезапно… виртуальная. потому что код для виртуальной машины сразу преобразуется в найтивный код процессора (компилируется).
                              • 0
                                Ясно, спасибо. Эту часть недопонял изначально.
                                • 0
                                  найтивный код процессора
                                  … Любопытно. И что, точнее как тогда, хотя всё-же что тогда обеспечивает кросплатформенность?
                                  • 0
                                    Код в WASM это код для виртуальной машины, найтивного кода там нет. Компиляция в найтивный код происходит в JS-движке в браузере на клиенте.
                                    • 0
                                      А есть какие-то инструменты для кэширования? Чтоб в следующий раз, когда грузится тот же самый код, не переводить его в нативный повторно?
                                      По хэшу там или по дате сравнивать и решать, обновлять перевод или старый прилетел?
                                      • 0
                                        В статье же описано это. При компиляции JS частоиспользуемые функции кэшируются. Если вы только не решите передать ему что-то не слишком подходящее и заставите деоптимизироваться.
                                        • 0
                                          Как я понял, вы про кеширование WASM-модулей. Я не разбирался в этом, но вот что-то тут есть: developer.mozilla.org/en-US/docs/WebAssembly/Caching_modules
                                  • +2

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

                                • 0
                                  Компиляция чего угодно в байт-код, который можно вызывать из джс.
                                  • 0
                                    Еще один нубский вопрос: wasm исполняется в среде интерпретатора javascript? Если да, то откуда берется производительность? За счет чего wasm будет работать быстрее, чем тот же код написанный на js?
                                    • +1
                                      WASM перед исполнением сразу весь целиком преобразуется в найтивный (родной) код вашего процессора. По сравнению с JS нет стадии парсинга текста. WASM это простая стековая машина, поэтому каждая инструкция WASM преобразуется всего в несколько инструкций реального процессора. отсюда и скорость.
                                  • –4
                                    Чем это принципиально лучше, чем Java Applets, которые так и не прижились в свое время?
                                    Почему потребовалось разрабатывать целиком заново, вместо того чтобы взять JVM и доработать с учетом безопасности необходимой для браузера?
                                    • +1
                                      Лучше/хуже — не знаю. Почему — не знаю :)
                                      Вот почему-то не захотелось им затаскивать Java runtime прямо в браузер.
                                      Google предлагал ещё NaCl и PNaCl — это по сути LLVM back-end затаскивается в браузер. Mozilla тоже сказала нам так не интересно.
                                      • +6
                                        Принципиально ничем не лучше. Если говорить о конкретике, то JVM это продукт от Sun, вещь в себе. Ещё в Java Applets за время существования как-то неприлично много дырок нашлось. Давным давно они выполнялись вообще молча. С каких-то пор начали выполняться молча, только если апплет подписан. Потом начали вылезать диалоговые окошки без альтернатив. В конце концов большинство браузеров тупо выпилили апплеты и всё. И это не от жизни хорошей, а от того, что за много лет Java так и не смогла сделать виртуальную машину, которой можно было бы запускать недоверенный код без опасения поймать вирус. Спецификация JVM огромная, просить Mozilla реализовать её нереально, JVM возможно сложней чем весь браузер. Брать как есть — очевидно не вариант, слишком некачественный продукт. Дорабатывать там нечего, в теории-то всё хорошо, только на практике не очень. Ну и сказались вечные проблемы с установкой и старыми версиями, уж не знаю, как Sun умудрились так накосячить, но разбираться, почему твой апплет не запускается у очередного пользователя приходилось нередко. С флешем, например, такой проблемы практически никогда не стояло.

                                        Если уж что и выбирать, так флеш. Правда он совсем проприетарный, так что хрен редьки не слаще, но по крайней мере работал нормально.

                                        В целом получается, что хорошей реализации просто нет. Про NaCl не знаю, не сталкивался, возможно там свои проблемы были. Поэтому решили просто начать с чистого листа. Кроме того, как я понимаю, webassembly во многом использует существующий JS движок, поэтому и с реализацией получается не всё так плохо.
                                        • 0
                                          Про NaCl не знаю, не сталкивался, возможно там свои проблемы были.
                                          NaCl — прекрасный пример того, как технически грамотные решения умирают из-за политики.

                                          Изначально — это было безопасное кроссплатформенное (но привязанное к конкретному CPU!) решение с прямым доступом к DOM и поддержкой legacy API.

                                          Потом Mozilla встала «в позу» и NaCl оказался привязан к Хрому.

                                          После этого Гугл охре-, нет оху-, или, пожалуй, офи-… ладно — решил убрать прямой доступ к DOM и legacy API, тоже. Под лозунгом «асинхронность — наше всё» продукт лишили почти всех фич, кроме возможности исполнять нативный код.

                                          После чего решили, что и этого — слишком много, так что нужно и эту возможность убрать тоже и оставить её только для ChromeOS.

                                          В результате получили кастрата без фич, но с кучей недостатоков. У которого оставался один мааааленький плюсик: возможность исполнять нативный код под ChromeOS. Когда ChromeOS получил поддержку APK этот плюс перестал котироваться тоже.

                                          Посмотрим как WASM закапывать будут…
                                          • +1
                                            Посмотрим как WASM закапывать будут…

                                            Это вряд ли. Unity поддерживает WASM и Asm.js. Так же это позволяет подключать библиотеки на C/C++.

                                          • 0
                                            А насколько Open Source/Royalty-Free был PNaCl?
                                            • 0
                                              Он был сделан на основе LLVM'а, так что и лицензия там была как у LLVM'а.

                                              Да и не в этом дело: Java вон вообще проприетарной долгое время была (как и .NET) — и ничего, вполне используется. Проблема была в том, что изначально постулировалось, что будет простое портирование старых программ, но в результате всем было предложено использовать только и исключительно асинхронный PPAPI.

                                              Технология портирования старых программ путём переписывания их на новый API — это круто, конечно, но в этом случае можно, как бы, и без PNaCl'а обойтись…
                                          • –1
                                            Если говорить о конкретике, то JVM это продукт от Sun, вещь в себе.

                                            Что, простите? Уже много лет как OpenJDK, направо и налево. Какая нафиг вещь в себе, когда исходники открыты по большей части, и давно?


                                            Против всего остального, впрочем, особых возражений нет.

                                          • 0

                                            Как минимум лучше тем, что в браузерах вебасм из коробки, не требует от пользователя дополнительных действий по установке, активации, обновлению и т. п. Есть подозрение, что более легковесная подсистема получится, по сравнению даже с урезанной JVM. Ну и нет привязки к корпорации одной известной.

                                            • 0
                                              Почему б тогда не ставить JVM сразу по умолчанию в стандартной поставке браузера? Или это вопрос лицензии?
                                              • +1
                                                И да и нет. В существующем виде JVM для этого не годится — в ней слишком много дыр. Но если бы Ларри не был таким жадным до денег

                                                Сейчас-то поезд уже ушел…
                                                • 0
                                                  Ну, а если JVM для подмножества Java, с ограничениями на возможные косяки (кстати, какие там дыры? Чисто из любопытства спрашиваю)? Все лучше, чем велосипед.
                                                  • +2
                                                    кстати, какие там дыры? Чисто из любопытства спрашиваю
                                                    Многочисленные. Во тут — 543 штуки. И это — только вершина айсберга, только то, что зарегистрировано как уязвимость. А уж сколько есть таких, которые проходят как «просто ошибка»… ни в сказке сказать, ни пером описать…

                                                    Ну, а если JVM для подмножества Java, с ограничениями на возможные косяки?
                                                    Так это Андроид и получится! Зачем нам ещё один?

                                                    Вот если бы это лет 10 назад сделали — в этом был бы смысл. А сейчас -у же нет.
                                            • 0

                                              Доработать с учетом безопасности далеко не так просто. А так, если уж совсем примитивно посмотреть — то лучше простотой байткода и реализации виртуальной машины. Что это даст в конечном счете — пока вопрос открытый.

                                            • 0
                                              В целом, у меня сложилось мнение, что нет такого что «в среднем WebAssembly обеспечивает 10-15% прирост скорости», нет никакого «в среднем», для каждого алгоритма нужно тестом определять, получите ли вы прирост скорости, применив WASM
                                              V8 интерпретирует js в байткод на этапе выполнения, а WASM — на этапе компиляции. Отсюда и потенциальный прирост скорости в 10-15%
                                              • +1
                                                1. теоретически — возможно, практически — бенчмарки показывают что результат может быть совсем другим.
                                                2. а откуда у вас именно 10-15%? или это просто из моего же текста? я кстати взял из одного из ответов со StackOverflow — чувак там очень авторитетно говорил про 10%, без всякого подтверждения фактами конечно.
                                                • 0

                                                  Следует отметить, что технология сырая, а значит инструментарий не оптимизирован.
                                                  Цифры взяты из цитаты, но они не сильно отличаются от реальных. Более подробно можно узнать здесь

                                                  • +1

                                                    Используем в продакшене, полет нормальный. На мобильных устройств получили улучшенную производительность.

                                              • +1
                                                Уже существует экспериментальный framework, который называется Blazor, исполняющий .NET код в браузере с помощью WebAssembly. Его разрабатывает Стивен Сандерсон, он делал доклад об этом на NDC Oslo. Сначала в качестве runtime использовался DNA, имеющий множество ограничений, но в ноябре вышла версия Blazor 0.3, использующая Mono в качестве runtime. Очень крутая штука.
                                                • 0
                                                  А вариант с NET.Core рассматривался?
                                                  • +1
                                                    Сейчас команда dotnet работает над компиляцией core runtime для WebAssembly, думаю, скоро .NET Core в браузере будет работать. Что касается Blazor на .NET Core (Blazor — личный проект Ствена, а не разработка Microsoft), ответить на вопрос будет ли он поддерживать Core, сможет только сам Стивен.
                                                  • 0

                                                    Уже есть Unity

                                                    • –2
                                                      Пока фреймворк не сделает Google или Microsoft Facebook, всем будет пофиг. Я уверен, что уже пилят, но не говорят, чтоб словить хайп.
                                                    • 0
                                                      я верно понимаю что взаимодействовать с железом на клиентской машине(например сканер отпечатков пальцев) с использованием webassembly не выйдет?
                                                      • 0

                                                        Вы можете использовать WebUSB в связке с WebAssembly. Но в целом, wasm не имеет доступа к OS, т.е. за пределы vm.

                                                        • +2
                                                          Если JS умеет, то можно и wasm прокинуть интерфейс. А так там даже файловая система виртуальная.
                                                        • +14

                                                          Я долгое время изучал WebAssembly и сделал свою подборку примеров. Постарался собрать в ней всё — от синтаксиса wast до подключения к webpack. Отлично подходит для первого знакомства с wasm.


                                                          Кроме того, у меня есть тест производительности wasm, попытался сравнить разные браузеры, а также мобильные девайсы. В тесте сравнивается производительность функции sha256, реализованной в webcrypto, wasm и на чистом js. Считаю, что такой тест сравнивает производительность лучше, примерчики вроде вычисления фибоначчи, т.к. тут происходит активная работа с памятью. Исходники тестов тут.

                                                          • 0

                                                            Обещает ли данная технология использование других языков программирования на фронте?
                                                            К примеру писать на Python, прогонять исходник через компилятор, который выдает на выходе бинарник WebAssembly?

                                                            • 0
                                                              Потенциально, в будущем — да.
                                                              Но сейчас пока предложенная модель выполнения довольно ограничена и лучше всего подходит для C/C++. В частности, пока нет сборщика мусора, реализацию которого конечно можно затащить внутрь WASM, что несколько увеличит его объём. Я не изучал подробно что ещё из других языков есть, но по-моему, большая часть это скорее эксперименты чем что-то production ready.
                                                              • +1

                                                                Все языки, которые могут собираться с помощью LLVM, могут использоваться на фронте. Уже сейчас вы можете писать на С/С++ или Rust, выше кинули ссылку на C#. С появлением GC, думаю и go подтянется.

                                                                • 0
                                                                  Все языки, которые могут собираться с помощью LLVM

                                                                  — вот тут вопрос допустим я хочу собирать Pascal-код, LLVM frontend давно есть, но мне же тут придётся городить свой toolchain, верно?
                                                                  • 0

                                                                    pascal -> llvm bytecode -> wasm


                                                                    Я читал где-то на форуме freepascal, что они всё ещё портируют его на llvm. Неужели закончили?

                                                                    • 0
                                                                      Честно говоря, не знаю состояние по Pascal, упомянул только для примера.
                                                                      Вопрос у меня не об этом. Для C/C++ Emscripten уже предоставляет всё готовое. Но для других языков (даже если они полностью поддерживаются LLVM) видимо придётся писать свои скрипты сборки?
                                                                      • –1

                                                                        Сложно сказать. Если условный компилятор может собирать llvm bytecode, то он вполне может добавить поддержку wasm. Например, rust умеет напрямую собирать wasm. Ничто не мешает условному паскалю сделать тоже самое. Тот же шланг тоже умеет напрямую собирать wasm. Кароч, это сложно предсказать, но toolchain уровня emscripten скорее всего писать не придётся.

                                                                        • –1
                                                                          Например, rust умеет напрямую собирать wasm.

                                                                          Вы про это?

                                                                • 0

                                                                  Лично у нас приложение написано на C++ и включает интерпретатор Lua.

                                                                • +2
                                                                  Есть такой новый проект AssemblyScript, который является симбиозом Typescript + WebAssembly
                                                                  • 0
                                                                    Интересно посмтореть, когда оно может работать на бэкенде с Node. Пока что на ум приходят задачи вида «быстро что-то посчитать или обработать какие-то жирные данные и отдать клиенту», сейчас эта проблема решается написанием отдельного сервиса на Go или C++, к которому Node будет обращаться через ZMQ или любым другим способом, wasm теоретически позволит обойтись без внешних частей и упростить проект.

                                                                    Можно еще в мобильных и десктопных приложениях на Cordova/Phonegap и Electron/NWjs использовать wasm для частей, критичных к производительности, но это уже из совсем диких идей.
                                                                    • +3

                                                                      При работе с нодой нужно иметь в виду, что wasm работает в том же потоке, что и js. Слишком тяжёлые вычисления будут блокировать IO.

                                                                      • 0
                                                                        В wasm собираются в ближайшем будущем треды завезти: github.com/WebAssembly/design/issues/1073
                                                                        • 0

                                                                          Да, но они завязаны на webworker`ы. Которых в ближайшее время не предвидится в ноде. Возможно, napa.js как-то разрешит ситуацию.

                                                                      • +1
                                                                        Постойте, постойте! Ведь Node.js давно поддерживает нативные модули. nodejs.org/dist/latest-v8.x/docs/api/addons.html
                                                                        • 0

                                                                          Нативные модули нужно компилировать для каждой платформы. С этим часто бывают проблемы.


                                                                          А WebAssembly — кроссплатформенный. Можно собрать его один раз и запускать на любой системе где есть Node.

                                                                          • +1
                                                                            Это, конечно хорошо для библиотек. Тут я с вами абсолютно согласен.

                                                                            Но, когда вы пишете свое приложение, то свой сервер вы обычно знаете, и платформа у вас выбрана одна.
                                                                            • +1

                                                                              Но она может поменяться. Например, хостер заявит "больше x86 не поддерживаем, только amd64"

                                                                            • 0

                                                                              При чём тут вообще Node к webassembly? Node — JavaScript рантайм, базирующийся на V8. А V8 — это движок ECMAScript, а вовсе не WASM.

                                                                              • 0
                                                                                Компиляция/запуск/взаимодействие WASM реализуется внутри движка JavaScript, поэтому как раз причём. WebAssembly уже давно можно запускать под NodeJS.
                                                                                • 0
                                                                                  А V8 — это движок ECMAScript

                                                                                  Там внутри есть компилятор JS в байткод. И исполняет он внутри байткод(V8 под капотом). Просто компилируем один байт код в другой и получаем профит.

                                                                                  • +1
                                                                                    V8 — это движок ECMAScript, а вовсе не WASM

                                                                                    Вы не правы. V8 также поддерживает WebAssembly.


                                                                                    Поэтому Node.js получает поддержку WASM практически бесплатно. В общем-то она уже есть, в качестве экспериментальной фичи за флагом

                                                                                    • 0
                                                                                      V8 поддерживает WASM.
                                                                              • 0
                                                                                Небольшая неточность: emcc — компилятор C-кода. Для C++ есть еще соответсвующий em++.

                                                                                Базовые либы std вполне работают, однако есть нюансы, вроде неработающего setlocale для компонент времени/чисел.
                                                                                • 0
                                                                                  Про emcc — я использовал его для компиляции C++ кода, и это работает. Вероятно, C/C++ определяется по расширению файла.
                                                                                  • 0
                                                                                    Да, возможно, не сильно всматривался в недра тулкита. Скорее всего сделано по аналогии с gcc, где g++ занимается обработкой плюсового кода, хотя параметры и передаются в gcc.
                                                                                • 0
                                                                                  del
                                                                                  • –3
                                                                                    Уменьшить время загрузки получается только по сравнению с асмжс, по сравнению с обычным жс время наоборот растет, так как приходится дополнительно грузить 1500 строк на жс для управления памятью (это может поменятся, если добавят сборщик мусора). Пока штука весьма полезная для портирования существующего кода в браузер (игры, криптография и т.п.) но весьма сомнительная для того, чтоб писать что-то с нуля для браузера. JS сейчас серьезно не хватает структур, целочисленная арифметика работает вполне сносно с помощью приведения Number к Int32 (a|0), плюс есть предложения как раз для арифметики (SIMD к сожалению пока в js решили не принимать и вернули на stage 1).
                                                                                    • 0
                                                                                      что то не пойму, вот есть код
                                                                                      in_array.cpp
                                                                                      #include <iostream>
                                                                                      #include <functional>
                                                                                      #include <algorithm>
                                                                                      #include <vector>
                                                                                      
                                                                                      using namespace std;
                                                                                      int in_array(const store[], const int storeSize, query) {
                                                                                         for (size_t i=0; i<storeSize; ++i) {
                                                                                            if (store[i] == query) {
                                                                                               return i;
                                                                                            }
                                                                                         }
                                                                                         return -1;
                                                                                      }
                                                                                      


                                                                                      экспортируем в
                                                                                      wast
                                                                                      (module
                                                                                      (table 0 anyfunc)
                                                                                      (memory $0 1)
                                                                                      (export "memory" (memory $0))
                                                                                      (export "in_array" (func $_Z8in_arrayPKiii))
                                                                                      (func $_Z8in_arrayPKiii (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
                                                                                      (local $3 i32)
                                                                                      (block $label$0
                                                                                      (block $label$1
                                                                                      (br_if $label$1
                                                                                      (i32.eqz
                                                                                      (get_local $1)
                                                                                      )
                                                                                      )
                                                                                      (set_local $3
                                                                                      (i32.const 0)
                                                                                      )
                                                                                      (loop $label$2
                                                                                      (br_if $label$0
                                                                                      (i32.eq
                                                                                      (i32.load
                                                                                      (get_local $0)
                                                                                      )
                                                                                      (get_local $2)
                                                                                      )
                                                                                      )
                                                                                      (set_local $0
                                                                                      (i32.add
                                                                                      (get_local $0)
                                                                                      (i32.const 4)
                                                                                      )
                                                                                      )
                                                                                      (br_if $label$2
                                                                                      (i32.lt_u
                                                                                      (tee_local $3
                                                                                      (i32.add
                                                                                      (get_local $3)
                                                                                      (i32.const 1)
                                                                                      )
                                                                                      )
                                                                                      (get_local $1)
                                                                                      )
                                                                                      )
                                                                                      )
                                                                                      )
                                                                                      (return
                                                                                      (i32.const -1)
                                                                                      )
                                                                                      )
                                                                                      (get_local $3)
                                                                                      )
                                                                                      )


                                                                                      пытаемся применить и использовать в nodejs 8.4
                                                                                      var wasmCode = new Uint8Array([0,97,115,109,1,0,0,0,1,136,128,128,128,0,1,96,3,127,127,127,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,157,128,128,128,0,2,6,109,101,109,111,114,121,2,0,16,95,90,56,105,110,95,97,114,114,97,121,80,75,105,105,105,0,0,10,190,128,128,128,0,1,184,128,128,128,0,1,1,127,2,64,2,64,32,1,69,13,0,65,0,33,3,3,64,32,0,40,2,0,32,2,70,13,2,32,0,65,4,106,33,0,32,3,65,1,106,34,3,32,1,73,13,0,11,11,65,127,15,11,32,3,11]);
                                                                                      
                                                                                      var wasmInstance = new WebAssembly.Instance(WebAssembly.Module(wasmCode));
                                                                                      exports.in_array = wasmInstance.exports._Z8in_arrayPKiii;
                                                                                      


                                                                                      подключаем хотим протестировать производительность
                                                                                      const array_helper = require('./lib/helpers/in_array/index');

                                                                                      let data = [1,876,324, 3424,234234,234234, 555];

                                                                                      var suite = new Benchmark.Suite;
                                                                                      console.log(array_helper.in_array(data, data.length, 234234)); // ответ всегда -1;
                                                                                      suite.add('test in array', function() {
                                                                                      array_helper.in_array(data, data.length, 234234) > -1;
                                                                                      }).add('indexof', function() {
                                                                                      data.indexOf(234234) > -1;
                                                                                      })
                                                                                      .on('cycle', function(event) {
                                                                                      console.log(String(event.target));
                                                                                      })
                                                                                      .run();

                                                                                      я конечно не шарю в с++ но сравнить а+б могу.
                                                                                      • +3

                                                                                        Вы вызываете поиск в массиве из 7 элементов сотни раз. Попробуйте сделать массив из десятков тысяч элементов и померить на нем


                                                                                        Операция вызова WASM кода из JS — дорогая. Чем меньше таких переходов, тем быстрее ваш код.

                                                                                        • –2

                                                                                          Ну для начала нужно понять почему поиск внутри цикла не работает, а дальше можно и на большом массиве проверить.


                                                                                          Пока не вижу плюсов в wasm, раз такая дорогая операция вызова, даже для массива не годится.


                                                                                          Я не использую обход массива на десятки и сотни тысяч элементов, эффективней будет сделать хэш массив.

                                                                                          • +4
                                                                                            Пока не вижу плюсов в wasm, раз такая дорогая операция вызова, даже для массива не годится.
                                                                                            Это примерно как сказать: пока не вижу смысла в аэробусах и боингах — на посадку нужно являться за 40 минут до вылета, а мне на дачу на машине ехать час. Почему с ними люди так носятся?

                                                                                            Если в вашей задаче нет «тяжёлых» вычислений и всё время уходит на общение с SQL-серверами или ещё чем-нибудь, то толку от wasm'а не будет, это правда.
                                                                                            • +3
                                                                                              Кроме тяжелых вычислений, wasm/asm.sj это способ писать на других языках(C/C++/Rust)
                                                                                              • –1

                                                                                                Использовать WebAssembly только для того, что бы писать бизнес логику для странички на любимом Rust вместо ненавистного джаваскрипта, кажется большим оверхедом.

                                                                                                • 0
                                                                                                  Странички или приложения? Для приложений самое то. Появились же Dart, TypeScript. А так же такие языки как nim, которые из коробки транслируются в JS.
                                                                                                  • 0

                                                                                                    Вот именно. Большинство языков транслируются в JS и сегодня, поэтому WebAssembly прорыва здесь не сделает. Перевод на нативный код ускоряет операции над примитивами, а коллбеки и вызовы DOM по определению будут медленными.


                                                                                                    Если перевести гипотетическое веб-приложение на WASM, то можно получить результат как у первого комментатора sanchezzzhak, когда расходы на прокидывание объектов туда и обратно сожрут все преимущество нативного кода.


                                                                                                    В Гитхабе WebAssembly есть issue Webasm can replace Javascript in browser?, в которой приводятся похожие соображения.

                                                                                                    • +4
                                                                                                      а коллбеки и вызовы DOM по определению будут медленными.

                                                                                                      Можно же не с DOM работать, а с виртуальным DOM как в ReactJS.


                                                                                                      В Гитхабе WebAssembly есть issue Webasm can replace Javascript in browser?, в которой приводятся похожие соображения.

                                                                                                      Никто никогда не говорил, что это замена JS. Asm.js был сделан именно для использования сторонних языков(C/C++) в браузере. WebAssembly пришел на замену Asm.js. И мы при использовании wasm получили 30 fps на iOS, в то время когда Asm.js выдавал 4fps.

                                                                                                      • 0
                                                                                                        Можно придумать класс приложений, где WebAssembly получит существенные преимущества. Пример: клиент для биржи, вывод списков/графиков на canvas/webgl, общение с сервером через websocket по бинарному протоколу (данные из websocket напрямую кидаем в WASM и расшифровываем уже там).
                                                                                                        • 0
                                                                                                          Мы как раз такое приложение делаем :) Очень увлекательно обрабатывать креши в C++ пот Asm.js/WASM)))
                                                                                                          • 0

                                                                                                            Не надо придумывать, этот класс вполне существует. Чем меньше нужно взаимодействовать с пользователем (кнопки, поля ввода), тем больше выгоды принесет WASM.


                                                                                                            Однако для типичного сценария "форма с валидацией и отправкой на сервер" WASM выглядит оверкиллом.

                                                                                                            • 0
                                                                                                              общение с сервером через websocket по бинарному протоколу (данные из websocket напрямую кидаем в WASM и расшифровываем уже там).

                                                                                                              Это и в JS неплохо делается.
                                                                                                            • 0
                                                                                                              Спасибо за ссылку в issue WASM, познавательно.

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