Upgrade to Pro — share decks privately, control downloads, hide ads and more …

20210825_ossx

chikoski
September 16, 2021

 20210825_ossx

chikoski

September 16, 2021
Tweet

More Decks by chikoski

Other Decks in Technology

Transcript

  1. カテゴリー 利用例 説明 Web アプリ Acrobat PDF 編集ツール Autocad CAD

    Lightroom 画像編集 Squoosh 画像圧縮、変換ツール Zoom ビデオミーティング サーバーレス環境 Cloudflare Workers Compute@Edge Envoy Service Proxy Istio Service mesh。Envoy を利用 Krustlet Kubernetes 上で動く Wasm 実行環境
  2. • Shopify App • Microsoft Flight Simulator • Envoy /

    Proxy-Wasm • Vector by Datadog プラグイン としての Wasm
  3. Shopify “Shopify is a subscription-based software that allows anyone to

    set up an online store and sell their products”, What is Shopify
  4. 0061736D01000000010A026000006002 7F7F017F030302000104050170010101 05030100020615037F01418088040B7F 00418088040B7F004180080B072B0406 6D656D6F727902000B5F5F686561705F 6261736503010A5F5F646174615F656E 6403020361646400010A0C0202000B07 00200120006A0B0020046E616D650119 0200115F5F7761736D5F63616C6C5F63 746F72730103616464

    #define WASM_EXPORT __attribute__((visibility("default"))) WASM_EXPORT int add(int a, int b) { return a + b; } #[no_mangle] pub extern fn add(x: i32, y: i32) -> i32 { x + y } export function add(x: i32, y: i32): i32 { return x + y; }
  5. 0061736D01000000010A026000006002 7F7F017F030302000104050170010101 05030100020615037F01418088040B7F 00418088040B7F004180080B072B0406 6D656D6F727902000B5F5F686561705F 6261736503010A5F5F646174615F656E 6403020361646400010A0C0202000B07 00200120006A0B0020046E616D650119 0200115F5F7761736D5F63616C6C5F63 746F72730103616464

    (module (type $t0 (func)) (type $t1 (func (param i32 i32) (result i32))) (func $__wasm_call_ctors (type $t0)) (func $add (export "add") (type $t1) (param $p0 i32) (param $p1 i32) (result i32) get_local $p1 get_local $p0 i32.add) (table $T0 1 1 anyfunc) (memory $memory (export "memory") 2) (global $g0 (mut i32) (i32.const 66560)) (global $__heap_base (export "__heap_base") i32 (i32.const 66560)) (global $__data_end (export "__data_end") i32 (i32.const 1024)))
  6. 1 + 2 + 3 = ? i32.const 1 i32.const

    2 i32.const 3 i32.add i32.add
  7. 1 + 2 + 3 = ? i32.const 1 i32.const

    2 i32.const 3 i32.add i32.add 1
  8. 1 + 2 + 3 = ? i32.const 1 i32.const

    2 i32.const 3 i32.add i32.add 1 2
  9. 1 + 2 + 3 = ? i32.const 1 i32.const

    2 i32.const 3 i32.add i32.add 1 2 3
  10. 1 + 2 + 3 = ? i32.const 1 i32.const

    2 i32.const 3 i32.add i32.add 1 5
  11. 1 + 2 + 3 = ? i32.const 1 i32.const

    2 i32.const 3 i32.add i32.add 6
  12. 関数定義と関数呼び出し (i32.const 2) (i32.const 1) (call $add) (func $add (param

    $p0 i32) (param $p1 i32) (result i32) local.get $p0 local.get $p1 i32.add)
  13. 関数定義と関数呼び出し (i32.const 2) (i32.const 1) (call $add) (func $add (param

    $p0 i32) (param $p1 i32) (result i32) local.get $p0 local.get $p1 i32.add) 2
  14. 関数定義と関数呼び出し (i32.const 2) (i32.const 1) (call $add) (func $add (param

    $p0 i32) (param $p1 i32) (result i32) local.get $p0 local.get $p1 i32.add) 2 1
  15. 関数定義と関数呼び出し (i32.const 2) (i32.const 1) (call $add) (func $add (param

    $p0 i32) (param $p1 i32) (result i32) local.get $p0 local.get $p1 i32.add) 2 1
  16. 関数定義と関数呼び出し (i32.const 2) (i32.const 1) (call $add) (func $add (param

    $p0 i32) (param $p1 i32) (result i32) local.get $p0 local.get $p1 i32.add) 3
  17. 関数定義と関数呼び出し (i32.const 2) (i32.const 1) (call $add) (func $add (param

    $p0 i32) (param $p1 i32) (result i32) local.get $p0 local.get $p1 i32.add) 3
  18. 線形メモリー • バイト単位でのアクセス • ページ単位でメモリを増やせる • 1ページ = 64KiB 単位

    • data section で初期状態を記述 64KiB 最大サイズは 実行時に指定可
  19. pub struct Item{ pub id: u32, pub price: i32, }

    #[no_mangle] pub extern fn add(item_a: &Item, item_b: &Item) -> i32 { item_a.price + item_b.price } (func $add ($param $p0 i32) (param $p1 i32) (result i32) local.get $p1 i32.load offset=4 local.get $p0 i32.load offset=4 i32.add)
  20. (func $add ($param $p0 i32) (param $p1 i32) (result i32)

    local.get $p1 i32.load offset=4 local.get $p0 i32.load offset=4 i32.add) 1 0 0 0 10 0 0 0 2 0 0 0 2 3 0 0 0 8 メモリー スタック
  21. (func $add ($param $p0 i32) (param $p1 i32) (result i32)

    local.get $p1 i32.load offset=4 local.get $p0 i32.load offset=4 i32.add) 1 0 0 0 10 0 0 0 2 0 0 0 2 3 0 0 0 8 メモリー スタック 0
  22. (func $add ($param $p0 i32) (param $p1 i32) (result i32)

    local.get $p1 i32.load offset=4 local.get $p0 i32.load offset=4 i32.add) 1 0 0 0 10 0 0 0 2 0 0 0 2 3 0 0 0 8 メモリー スタック 10
  23. (func $add ($param $p0 i32) (param $p1 i32) (result i32)

    local.get $p1 i32.load offset=4 local.get $p0 i32.load offset=4 i32.add) 1 0 0 0 10 0 0 0 2 0 0 0 2 3 0 0 0 8 メモリー スタック 10 8
  24. (func $add ($param $p0 i32) (param $p1 i32) (result i32)

    local.get $p1 i32.load offset=4 local.get $p0 i32.load offset=4 i32.add) 1 0 0 0 10 0 0 0 2 0 0 0 2 3 0 0 0 8 メモリー スタック 10 770
  25. const stream = await fetch('some.wasm'); const wasmFile = await stream.arrayBuffer();

    const instance = WebAssembly.instantiate(wasmFile); const value = instance.exports.add(1, 2);
  26. const wasm = WebAssembly.instantiate(wasmFile); const memory = new Uint32Array(wasm.exports.memory.buffer); memory[0]

    = 0; // id for the first item memory[1] = 10; // price of the first item memory[8] = 2; // id for the first item memory[9] = 770; // the second item’s price wasm.exports.add(0, 8);
  27. #[wasm_import_module = "mod"] extern{ fn discount() -> u32; } #[no_mangle]

    pub extern fn price(item: &Item) -> u32{ unsafe{ item.price - discount() } } (import "mod" "discount" (func $discount (type $t2))) (func $price (export "price") (type $t0) (param $p0 i32) (result i32) local.get $p0 i32.load offset=4 call $discount i32.sub)
  28. const imports = { mod: {discount: () => 50} };

    const wasm = WebAssembly.instantiate(wasmFile, imports); const memory = new Uint32Array(wasm.exports.memory.buffer); memory[8] = 2; // id for the first item memory[9] = 770; // the second item’s price wasm.exports.price(8); // returns 720
  29. • インスタンス化が必要 • export ◦ ホスト側に参照できる値 ◦ メモリーも export できる

    • import ◦ ホスト側から与えられる値 ◦ メモリーも与えられる Wasm の実行 https://rsms.me/wasm-intro
  30. • プラグインとは第三者のコード ◦ Security vs flexibility ◦ 信頼の実現は難しい • 安全にコードを実行するには

    ◦ サンドボックス内での実行 ◦ 安全なコードの生成 • 信頼できないコードの実行を 考慮して設計されている 1 0 0 0 10 0 0 0 2 0 0 0 2 3 0 0 0 8 第三者のコードの実行 x86 ARM
  31. • i32, i64, f32, f64 については規定がある • それ以外は規定がない ◦ 配列、リスト

    ◦ 文字、文字列 ◦ レコード(構造体、共用体) • 線形メモリ上に、なんとかして置いている → 置き方は処理系に任せられている。 データ表現に関する規定があまりない
  32. バージョン名を返すAPIを例に考えると extern char* get_version_code(); void do_something(){ char *code = get_version_code();

    if (strncmp("pre", code, 3)){ work_with_prelease(); }else{ work(); } } (type $t0 (func (result i32))) (import "env" "get_version_code" (func $get_version_code (type $t0)))
  33. extern { fn get_version_code() -> String; } fn do_something(){ unsafe{

    if get_version_code() == "pre"{ work_with_prerelease(); }else{ work(); } } } バージョン名を返すAPIを例に考えると (type $t3 (func (param i32))) (import "env" "get_version_code" (func $get_version_code (type $t3)))
  34. 文字列の表現が異なる H e l l o , w o r

    l d ! \0 H e l l o , w o r l d ! 0 0 表現A:(0) 表現B:(0, 12) 0 12
  35. char* id(char* value) { return value; } (type $t1 (func

    (param i32) (result i32))) (func $id (export "id") (type $t) (param $p0 i32) (result i32) local.get $p0)
  36. #[no_mangle] pub extern fn id(value: &str) -> &str{ value }

    (type $t2 (func (param i32 i32 i32))) (func $id (export "id") (type $t2) (param $p0 i32) (param $p1 i32) (param $p2 i32) local.get $p0 local.get $p2 i32.store offset=4 local.get $p0 local.get $p1 i32.store)
  37. • 策定中の仕様で、次の 3 つが目的 ◦ Language neutral なインターフェイスの定義を可能にする ◦ Web

    API 呼び出しの最適化 ◦ Wasm モジュールの再利用性の向上 • 内容 ◦ Interface type の定義 ◦ Adapter ◦ Lifting and Lowering Instructions Interface Types