Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Multithreading WebAssembly by Rust

Multithreading WebAssembly by Rust

Fukuoka.rs vol.6 〜LT会〜
https://fukuokars.connpass.com/event/151353/

petamoriken / 森建

November 08, 2019
Tweet

More Decks by petamoriken / 森建

Other Decks in Programming

Transcript

  1. 2 自己紹介まわり • 主にフロントエンドエンジニア • ECMAScript や WHATWG DOM を追うのが好き

    • WebAssembly をほどほど追ってる • 最近引っ越してネット回線がない状態が続いていて 辛い 11/20(水) 19:30~ Three.js Meetup Tokyo #0 サテライト会場を福岡でやるのでよければどうぞ https://connpass.com/event/154480/ petamoriken 課題解決部
  2. 3 WebAssembly とは • アセンブリでないバイトコード • 豊富な実行環境がある ◦ モダンブラウザ Chrome

    / Firefox / Safari / Edge ◦ Node.js v8 以降(AWS Lambda, BigQuery など) ◦ Wasmer というランタイムを使えば Rust / C / Go / Ruby などで実行できる • ECMAScript と似た策定プロセスを取っている
  3. 4 WebAssembly W3C の策定プロセス • Phase 1 Feature Proposal ◦

    機能追加が承認される • Phase 2 Proposed Spec Text Available ◦ 最初の Spec テキストが作られる • Phase 3 Implementation Phase ◦ Spec テキストが完成し、レビューが完了する • Phase 4 Standardize the Feature ◦ 1つのツールチェイン、2つ以上の実行環境が作られ、承認される
  4. ブラウザにおけるスレッドは SharedArrayBuffer と Web Workers API を用いる • SharedArrayBuffer (Atomics

    API) ◦ スレッド間で共有できる特別な ArrayBuffer(バイト列) ◦ Atomics API を使って割り込みが起きないようにする ◦ Spectre 脆弱性の影響で現在 Desktop Chrome のみ扱える • Web Workers API ◦ スレッドを作る DOM API ◦ もちろん SharedArrayBuffer を共有することができる 6 Phase 2 Threads
  5. • 先程の Chrome の記事では C で pthread を使ったコード例が載っている ◦ Emscripten

    を使ってビルドする ◦ ビルドすると Wasm とグルーコードの JavaScript が出力される • Rust で似たコードを書いてビルドすればスレッドが扱えるのでは!? 7 Phase 2 Threads emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c
  6. 8 int main(int argc, char *argv[]) { int fg_val =

    54; int bg_val = 42; pthread_t bg_thread; // Create the background thread if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) { perror("Thread create failed"); return 1; } // Calculate on the foreground thread fg_val = fibonacci(fg_val); // Wait for background thread to finish if (pthread_join(bg_thread, NULL)) { perror("Thread join failed"); return 2; } // Show the result from background and foreground threads printf("Fib(42) is %d, Fib(54) is %d\n", bg_val, fg_val); return 0; }
  7. 9 extern "C" { fn console_log(num: f64); } #[no_mangle] pub

    extern "C" fn main() { let normal = 54; let background = 42; let handler = std::thread::spawn(move || fibonacci(background)); let normal = fibonacci(normal); let background = handler.join().expect("Unsupported Thread"); unsafe { console_log(normal as f64); console_log(background as f64); } }
  8. 10

  9. • std::thread::spawn を使ったコードは unreachable に変換されてしまう • 調べてみると Phase 2 Threads

    は Atomics のみの提案だった ◦ ブラウザの SharedArrayBuffer は扱えるが Web Workers API は扱えない • Emscripten の場合 JavaScript のグルーコード内でスレッドを作っている https://git.io/JeVk0 11 Multithreading WebAssembly by Rust // Allow HTML module to configure the location where the 'worker.js' file will be loaded from, // via Module.locateFile() function. If not specified, then the default URL 'worker.js' relative // to the main html file is loaded. pthreadMainJs = locateFile(pthreadMainJs); var newWorkers = []; for (var i = 0; i < numWorkers; ++i) { newWorkers.push(new Worker(pthreadMainJs)); } return newWorkers;
  10. • Rust でスレッドを扱おうと思ったら ◦ 複数の Wasm に分割し、それぞれに対して JavaScript のグルーコードを書く ◦

    wasm-bindgen で JavaScript のグルーコードを自動生成 ▪ 公式の demo があるがうまく実行できてなさそう? • 将来的には Phase 1 Interface Types によってグルーコードが不要に ◦ wasm-bindgen で直接 DOM API を触るようになって JavaScript のグルーコードを 生成しなくなる? ◦ wasm32-web, wasm32-node のようにビルドターゲットが増える? 14 Multithreading WebAssembly by Rust
  11. • WebAssembly でのマルチスレッドはまだ厳しい ◦ そもそもまだ仕様策定中 ◦ Wasm の実行環境でスレッドを作り、その中で Wasm を実行する必要がある

    ◦ ブラウザに限って言うとまだ Desktop Chrome でしか扱えない • Phase 1 Interface Types が来たら世界が変わる(はず) ◦ フロントエンド開発でグルーコードも含めて JavaScript が不要になる 15 まとめ