Web assembly

10 януари 2023

Административни неща

Административни неща

Административни неща

Web assembly

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

Източник: https://webassembly.org/

Web assembly

Web assembly

Web assembly

Web assembly

Web assembly

Web assembly

Web assembly

Поддръжка

Компилация на rust до wasm

Компилация на rust до wasm

Компилация на rust до wasm

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

Компилация на rust до wasm

Крос компилация

1
rustup target add wasm32-unknown-unknown

Компилация на rust до wasm

Крос компилация

Има и още няколко web assembly target tuple-а:

Компилация на rust до wasm

Крос компилация

Има и още няколко web assembly target tuple-а:

Компилация на rust до wasm

Крос компилация

Има и още няколко web assembly target tuple-а:

Компилация на rust до wasm

Крос компилация

Има и още няколко web assembly target tuple-а:

Компилация на rust до wasm

std и no_std

Компилация на rust до wasm

std и no_std

Компилация на rust до wasm

std и no_std

Компилация на rust до wasm

std и no_std

Компилация на rust до wasm

std и no_std

Компилация на rust до wasm

std и no_std

Пример 1

Rust до Wasm

Cargo.toml

1 2
[lib]
crate-type = ["cdylib"]

Трябва проекта да се компилира като библиотека.
Тази библиотека ще се зареди от javascript код и ще се използват функциите дефинирани в нея.

Пример 1

Rust до Wasm

src/lib.rs

1 2 3 4
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

Функцията add ще бъде достъпна от javascript

Пример 1

Rust до Wasm

1
cargo build --release --target wasm32-unknown-unknown

Това ще генерира target/wasm32-unknown-unknown/release/example_01.wasm

Пример 1

Изпълняване в уеб браузър

Пример 1

Изпълняване в уеб браузър

Пример 1

Изпълняване в уеб браузър

Пример 1

Изпълняване в уеб браузър

Пример 1

Изпълняване в уеб браузър

Пример 1

Изпълняване в уеб браузър

Сървъра ще връща следните файлове:

1 2
cp target/wasm32-unknown-unknown/release/example_01.wasm \
    wasm_lib.wasm

Пример 1

Изпълняване в уеб браузър

index.html

1 2 3 4 5 6 7 8 9 10
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello wasm!</title>
  </head>
  <body>
    <script src="./index.js" type="module"></script>
  </body>
</html>

Пример 1

Изпълняване в уеб браузър

index.js

1 2 3 4 5 6
WebAssembly.instantiateStreaming(fetch('./wasm_lib.wasm'), {})
    .then(wasm => {
        // през `instance.exports` можем да достъпваме функциите,
        // които сме дефинирали в нашата библиотека.
        console.log("add(1, 2) = ", wasm.instance.exports.add(1, 2))
    })

Пример 1

Ограничения

Пример 1

Ограничения

Пример 1

Ограничения

Пример 1

Ограничения

Пример 1

Wasm-bindgen

Пример 1

Wasm-bindgen

Пример 1

Wasm-bindgen

Пример 1

Wasm-bindgen

Пример 1

Wasm-bindgen

Пример 1

Wasm-bindgen

Wasm bindgen

Необходима е програмата wasm-bindgen, която може да се инсталира през cargo

1
cargo install wasm-bindgen-cli

Необхидима е и библиотеката wasm-bindgen. Cargo.toml:

1 2
[dependencies]
wasm-bindgen = { version = "0.2.69", features = ["serde-serialize"] }

Wasm bindgen

Използване

1 2 3 4 5
cargo build --release --target wasm32-unknown-unknown

wasm-bindgen target/wasm32-unknown-unknown/release/wasm_lib.wasm \
    --out-dir pkg \
    --target web

Пример 2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add_i32(a: i32, b: i32) -> i32 {
    a + b
}

#[wasm_bindgen]
pub fn add_u32(a: u32, b: u32) -> u32 {
    a + b
}

#[wasm_bindgen]
pub fn greet() -> String {
    "hello wasm".to_string()
}

// `wasm_bindgen` атрибута позволява да подаваме структурата
// на JS код като opaque тип, т.е. указател
#[wasm_bindgen]
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct User {
    name: String,
    age: u32,
}

#[wasm_bindgen]
impl User {
    // В този случай `User` е opaque type
    pub fn new(name: String, age: u32) -> User {
        User { name, age }
    }

    pub fn to_js_value(&self) -> JsValue {
        // Сериализира структурата до JSON и я подава на JS,
        // където ще се десериализира до JS обект
        JsValue::from_serde(self).unwrap()
    }
}

Пример 2

1 2 3 4 5 6 7 8 9 10 11 12
import { add_i32, add_u32, greet, User, default as init } from './pkg/wasm_lib.js'

init('./pkg/wasm_lib_bg.wasm')
    .then(_wasm => {
        console.log(greet())
        console.log("add_i32(-1, -2) = ", add_i32(-1, -2))  // -3
        console.log("add_u32(-1, -2) = ", add_u32(-1, -2))  // 4294967293

        const user = User.new("Иванчо", 10)
        console.log(user)               // Object { ptr: 1114144 }
        console.log(user.to_js_value()) // Object { name: "Иванчо", age: 10 }
    })

Импортиране на функции

Wasm модул има достъп единсвено до функции, които са му подадени експлицитно от страна на JS при създаването му.

Rust

1 2 3
extern "C" {
    pub fn myStuff();
}

Javascript

1 2 3 4 5 6 7 8 9 10 11
function myStuff() { /* ... */ }

const importObject = {
    env: { myStuff }
}

WebAssembly
    .instantiateStreaming(fetch('./wasm_lib.wasm'), importObject)
    .then(wasm => {
        /// ...
    })

Импортиране на функции

Или чрез wasm-bindgen

Rust

1 2 3 4
#[wasm_bindgen(module = "/exports.js")]
extern "C" {
    pub fn myStuff();
}

Javascript

1 2 3 4
// exports.js
export function myStuff(msg) {
    console.log("myStuff called");
}

Връзка с браузърни API-та

js-sys и web-sys


Връзка с браузърни API-та

Можем да използваме браузъра като мощна "библиотека" за графичен интерфейс.
Canvas, бутони, форми, input полета, …

1 2 3
<body>
    <canvas id="the_canvas_id"></canvas>
</body>
1 2 3
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id("the_canvas_id").expect("Can't find canvas");
// ...

Frontend библиотеки

Yew

Примери

Статична търсачка

Примери

Игри

Инструменти за wasm

wasm-pack

Инструменти за wasm

wasm-pack

Инструменти за wasm

wasm-pack

Инструменти за wasm

wasm-pack

Инструменти за wasm

wasm-pack

Оптимизации

Aко ще добавяме wasm към web страница обикновено размера на модула е по-важен критерий от скоростта му

Оптимизации

Aко ще добавяме wasm към web страница обикновено размера на модула е по-важен критерий от скоростта му

1 2 3 4
[profile.release]
opt-level = "z"
lto = "thin"
codegen-units = 1

Оптимизации

Aко ще добавяме wasm към web страница обикновено размера на модула е по-важен критерий от скоростта му

1 2 3 4
[profile.release]
opt-level = "z"
lto = "thin"
codegen-units = 1

Оптимизации

Aко ще добавяме wasm към web страница обикновено размера на модула е по-важен критерий от скоростта му

1 2 3 4
[profile.release]
opt-level = "z"
lto = "thin"
codegen-units = 1

Wasm извън браузъра

Въпреки, че wasm е създаден с идеята да се използва за уеб, намира и други приложения.
Web assembly като формат притежава някои удобни свойства:

Wasm извън браузъра

Въпреки, че wasm е създаден с идеята да се използва за уеб, намира и други приложения.
Web assembly като формат притежава някои удобни свойства:

Wasm извън браузъра

Въпреки, че wasm е създаден с идеята да се използва за уеб, намира и други приложения.
Web assembly като формат притежава някои удобни свойства:

Wasm извън браузъра

Въпреки, че wasm е създаден с идеята да се използва за уеб, намира и други приложения.
Web assembly като формат притежава някои удобни свойства:

Wasm извън браузъра

Въпреки, че wasm е създаден с идеята да се използва за уеб, намира и други приложения.
Web assembly като формат притежава някои удобни свойства:

Wasm извън браузъра

Въпреки, че wasm е създаден с идеята да се използва за уеб, намира и други приложения.
Web assembly като формат притежава някои удобни свойства:

Wasm извън браузъра

wasm_docker_tweet

Wasmtime

Примери

Watt

Примери

Vscode tree sitter plugin

Примери

Wasm-4

Въпроси