Тяжело в учении, сложно при внедрении, быстро в использовании

Павел Дадыкин, ROGII

Тяжело в учении,
сложно при внедрении,
быстро в использовании

Павел Дадыкин
ROGII

Обо мне

Павел Дадыкин

О чём доклад

 

Что за расчёты?

Эволюция продуктов ROGII

Проблемы

Цель

WebAssembly (WASM)​

Плюсы WASM

Минусы WASM

Доклады про WASM

Тяжело в учении​

Как же скомпилировать С++ в WASM?

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

Emscripten​

Документация Emscripten​

Дефолтной конфигурации Emscripten
не существует!

Флаги компиляции

          -s DYNAMIC_EXECUTION=0 -s ENVIRONMENT=worker
          -s MODULARIZE=1 -s ALLOW_MEMORY_GROWTH=1 --bind
      

Где же взять описание функций?

Генерация документации​

Doxygen

Как сделать удобной отладку ошибок?

Разные сборки (через cmake)

Debug

  • Большой вес файла
  • Работает медленнее
  • Детальное описание ошибок

Release

  • Маленький вес файла
  • Работает быстро
  • Сложно отлаживать

Утечки памяти

Как реализовать версионирование?

Версионирование

Emscripten на выходе даёт 2 файла:

Версионирование

Добавить в начало JS-файла комментарий

        /*
          Version: 1.3.0
          Commit: 681def4aefb99c9de5357617dc138b66e6ae1d0b ​
          Pipeline: 103990 ​
        */
      

Версионирование

        "dependencies": { ​
           "@nexus-npm/wasm": "0.9.0-Release", ​
        }​
      

Подключение WASM к проекту

Как настроить Webpack?

Webpack

webassembly-loader
wasm-loader

Webpack 4 file-loader​

        {
          test: /\.wasm$/,
          type: "javascript/auto",
          use: [{​​
          loader: "file-loader",​​​​
            options: {​ name: "wasm/[name].[hash].[ext]" }​​
          }]​​​​
        }​
    

Загрузка WASM в приложение​

        import wasm from 'math-js.wasm';
         
        const response = await client.get(wasm, {
            responseType: 'arraybuffer' ​​
        });
         
        const wasmBinary = response.data;​​
      

Webpack 5

Asset Modules на замену file-loader
syncWebAssembly / asyncWebAssembly

Как добавить типизацию?

Typescript

CSP Error

Refused to compile or instantiate WebAssembly module because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src https:".

        Content-Security-Policy: script-src 'wasm-unsafe-eval'
      

Как конвертировать данные JS ↔ WASM?

Конвертация JS ↔ WASM

        const pointer = instance._malloc(size * Float64Array.BYTES_PER_ELEMENT); 
         
        instance.HEAPF64.set(
          new Float64Array(size),
          ​pointer / Float64Array.BYTES_PER_ELEMENT,
        ); 
         
        instance._free(trajectory.mdArray.pointer); ​​
      

Добавление обёртки

Удобные функции

        convertToJSObject<WasmType, JSArrayType>(data)​
        convertFromJSObject<JSArrayType, WasmType>(data)
        freeCollection(data)
      

Undefined / NaN

В TypeScript мы можем написать

        type X = number | undefined
      

В C/C++ так нельзя!
Из функций расчёта в этом случае нам возвращается NaN

Undefined → NaN

        // Преобразование для передачи в модуль расчёта
         point.data ?? NaN 
         
         // Проверка на наличие значения
         if (!isNaN(point.data))
      

Batch запросов

Batch запросов

        for (const element of elements) {
          const point = calculatePoint(element.x);
          points.push(point);
        }​
      
        const xArray = elements.map((element) => element.x);
        const points = wasm.calculatePoints(xArray);
      

Как всё подружить с веб-воркерами?

Web workers

Web workers в StarLite​

Web workers & WASM​

Web workers & WASM​

Web workers & WASM​

Как тестировать WASM?

Тестирование

Jest

        import { readFileSync } from 'fs';
         
        const wasmBinary = readFileSync(
          'node_modules/path-to-wasm/math.wasm',​
        );
         
        instance = await createModule({ wasmBinary });
      

Результаты

Плюсы

Минусы

Когда стоит использовать WASM?

Пожалуйста, оставьте свой отзыв

Павел Дадыкин
ROGII

https://meloman4eg.github.io/wasm-fc-2024/

@meloman4eg