Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
非同期処理を活用しながらRust製wasmとJSを連携する方法(wasm-bindgenを使...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
uhyo
August 24, 2024
Technology
5.4k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
非同期処理を活用しながら Rust製wasmとJSを連携する方法(wasm-bindgenを使いたくない人向け)
2024-08-24 フロントエンドカンファレンス北海道
uhyo
August 24, 2024
More Decks by uhyo
See All by uhyo
Reactの設計論
uhyo
24
13k
型があると何が嬉しいか
uhyo
3
140
Baseline対応のDOMの型定義を作った
uhyo
3
940
AIのReact習熟度を測る
uhyo
2
1k
React、まだ楽しくて草
uhyo
7
5k
TypeScript 7.0の現在地と備え方
uhyo
6
3.8k
React 19時代のコンポーネント設計ベストプラクティス
uhyo
20
11k
型定義でAIと会話する:型を通じてAIに意図を伝えるテクニック
uhyo
1
120
タグ付きユニオン型を便利に使うテクニックとその注意点
uhyo
3
1.2k
Other Decks in Technology
See All in Technology
あけおめLINE 傾向とその対策
nasa9084
0
110
バイブコーディング時代のWebアプリ開発入門~Cloud Runで学ぶセキュアなビルドとデプロイ
waiwai2111
1
130
品質と信頼性を地続きにする
grimoh
0
470
Azure Serverless 2026:Production-ready な AI エージェント基盤 / Azure Serverless 2026: Production-Ready AI Agent Platform
miyake
1
140
作って終わりじゃないサーバーレス 〜9年運用する大規模EC物流API基盤の設計・運用のリアル〜
zozotech
PRO
0
110
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
2k
作品が生態系になった ─ Mini Tokyo 3D から世界へ
nagix
0
190
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
190
データ_AIの事業の勝敗をわけるもの
nek0128
0
390
安心して変更できるWebフロントエンドの作り方
pirosikick
5
2.6k
人間はどの意思決定を手放せるのか
kawasima
14
7.1k
日経電子版を支えていく Kasane Design System/fec_fukuoka
nikkei_engineer_recruiting
0
1.6k
Featured
See All Featured
Game over? The fight for quality and originality in the time of robots
wayneb77
1
280
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
410
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
WENDY [Excerpt]
tessaabrams
14
39k
Utilizing Notion as your number one productivity tool
mfonobong
4
590
The SEO identity crisis: Don't let AI make you average
varn
0
560
The agentic SEO stack - context over prompts
schlessera
0
940
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
2.9k
RailsConf 2023
tenderlove
30
1.5k
Transcript
非同期処理を活用しながら Rust製wasmとJSを連携する方法 (wasm-bindgenを使いたくない人向け) 2024-08-24 フロントエンドカンファレンス北海道
発表者紹介 uhyo 株式会社カオナビ フロントエンドエキスパート 好きなプログラミング言語は TypeScriptとRust。
宣伝 株式会社カオナビはフロントエンドカンファ レンス北海道のゴールドスポンサーです 午前中にスポンサーLTもありました
このトークのテーマ: WASM JavaScriptエンジンに処理系が組み込まれており、 フロントエンドからも利用可能な実行可能形式。 多くの言語からコンパイルターゲットとして 利用可能であり、JS以外で書いたコードを フロントエンドで動かす有力な手段である。
WASMの進化 WASMは基本機能がすでに標準化されて各処理系 に組み込まれているが、 さらなる進化が提案・検討されている。 WebAssembly proposals https://github.com/WebAssembly/proposals
WASMと非同期処理 非同期処理に関する機能はまだ完成していない。 関連するプロポーザル: • Threads • Stack Switching • JS
Promise Integration (JSPI)
現状のWASMは同期処理である 現状のWASMの実行モデルは単純であり、 呼び出し側(JS側)から見たら同期関数に見える。 つまり、JSとWASMでコールスタックを共有する。
コールスタック共有の例 WASM側のコードはRustで示します 呼び出し
コールスタック共有の例 JS→WASM→JSのように関数呼び出しをした場合、 このように同じコールスタックに混ざる。 JSの関数もWASMの関数も 同期関数として振る舞っている。 JS JS WASM
現状のWASMと非同期処理の問題 JS側で非同期処理が発生した場合、 WASM側が「待つ」方法が現状存在しない。 WASM JS これやって (関数呼び出し) ちょっと待ってね (Promise返し) え?
何これ
このトークの内容 JS側で非同期処理を使いつつ、 WASMと連携する方法を2つ解説。 ① JSPIを使う方法 用意されたAPIを使えば簡単にできる ② 自前のイベントループを用意する方法 WASM側でRustのasync/awaitを使える! 「JS側の非同期処理を.awaitする」とかできる
補足: wasm-bindgen このトークではwasm-bindgenは扱いません。 Rustに組み込みのWASM対応のみ使用。 wasm-bindgen不使用 wasm-bindgen使用 WASM Rust コンパイル WASM
Rust コンパイル JS Promise対応とかもあるらしい
JSPI (JS Promise Integration)
JSPI JS側の非同期処理が完了するまで、WASM側を 止めておくことができる仕様。 実験的機能としてChromeに実装されている。
JSPIの例 WASM側は、JS側から getA, getB, getCを インポートする。 runが実行されると、 3つの関数を実行して 結果を足した値を 返す。
JSPIの例 getAとかは実はJS側では非同期関数になっている。 WebAssembly.SuspendingでラップしてWASM側に渡す ことで、WASM側から同期関数に見える。
JSPIの例 WASMのエントリーポイントとなる関数を、 WebAssembly.promisingでラップする必要がある。 ラップしたら返り値がPromiseになる。
JS JSPI図解 WASM サスペンド可能な世界 JS promisingでラップ した関数を呼出 Suspendingでラップした関数が Promiseを返した場合、 解決するまでWASMの実行が止まる
(非同期処理がWASM側からは同期に見える) Promiseが返る (処理が全部 終わったら解決)
JSPI図解 promisingを介してWASMを実行することで、 WASMがasync関数みたいになる。 JS側が返したPromiseは自動的にawaitする。 JS WASM JS async await await
await
WASMの並行実行 promisingを介して実行した場合、 WASMを複数並行して実行することができる。 (JSのasync関数を複数同時に実行するのと同じ) 複数同時に並列実行され ることはない。 JSと同じ実行モデル。 JS WASM JS
JSPIの利点・欠点 利点 WASM側に非同期処理の知識は一切不要。 WASM側では従来通りの同期的な処理を書きつつ、 JavaScript側では非同期処理を利用できる。 欠点 WASM側から複数の非同期処理を並行的に開始す ることはできない。(複雑なアプリの実装に不向き)
自前のイベントループを 用意する
背景 Rust製のCLIツールをWASMにコンパイルして Node.js経由で実行する形でnpmで配布している。 一部の処理をNode.js側に移譲しており、Node.js 側の処理を待つ間もWASM側を実行し続けたい。 (JSPIでは難しいユースケース)
WASM側中心のアーキテクチャ WASMがメインのアーキテクチャ(WASIも活用) なので、非同期処理もWASM側で取り扱いたい。 具体的には、Rustのasync/.awaitを使いたい。 JS側の非同期処理をRustのFutureとして扱いたい。 (FutureはJSのPromiseみたいなやつです)
Rustの非同期処理の例 JSの実行をNode.jsに任せているところ 非同期処理
自前のイベントループ コード実行 非同期処理発生 Node.jsに処理を発注 結果受け取り処理 タスクを 登録 Node.js側で処理完了 JS WASM
コード実行 自前のイベントループ(別視点) コード実行 非同期処理 発生 Node.jsに処理を発注 結果受け取り 処理 Node.js側で処理完了 起動
非同期処理 発生 Node.jsに処理を発注 同期実行 同期実行 WASMの同期実行は、 できるタスクが無くなったら returnしてJSに制御を戻す。 非同期処理が完了したら、 JS側からWASMを呼び出して できるようになった タスクを走らせる。 JSのイベントループ (マイクロタスク)と 考え方は同じ。 関数呼び出し return 呼出 return
Rustの非同期ランタイム Rustでのasync/.awaitの実務は 非同期ランタイムが担当する。 Tokioなどが知られており、 WASM対応もされている。 https://tokio.rs/
Rustの非同期ランタイム WASM含むシングルスレッドの環境では、 非同期ランタイムの実態はイベントループになる。 しかし、今回の要件にはTokioは採用できなかった。
Tokioを採用できない理由 Tokio(のようなハイレベルなランタイム)では、 イベントループを回すイベントが 決め打ちされている。 (ネットワークIO、ファイルIO、タイマー) 「Node.js側で非同期処理が終わったとき」 のようなイベントは作れない。
ローレベルな非同期ランタイムを使う 今回はasync-executorを採用。 「タスクを積む」「イベントループを1週回す」 というローレベルなAPIを提供しており、 Node.js側で非同期処理が完了したらイベント ループが再開する挙動を実装できる。 https://github.com/smol-rs/async-executor
JS側とWASM側の通信 ① WASMからJSにコード実行を依頼 WASM JS execute_node コード文字列とハンドル(i32)を JS側に渡す JS側で非同期的 にコードを実行
JS側とWASM側の通信 ② JSからWASMに実行結果を渡す WASM JS execute_node_ret ハンドルと実行結果を渡す そのままWASM側の イベントループ再開 タスクが無くなったら
制御が戻る
JS側とWASM側の通信 コード実行 非同期処理発生 Node.jsに処理を発注 結果受け取り処理 タスクを 登録 Node.js側で処理完了 execute_node execute_node_ret
JS側のイベントループとの統合 この構成は、JSのイベントループの一部として WASMのイベントループを動かしているという見 方もできる。 コード実行 非同期処理発生 結果受け取り 処理 JSイベント ループ
非同期処理
実際のコード (JS側) やっていることは、 渡された文字列を読む →非同期的に 実行する (w.run) →結果が出たら WASM側に送る (execute_node_ret)
単純!
WASM側のコード(Rust)もチラ見せ 非同期処理を表す構造体に Futureを自前実装
WASM側のコード(Rust)もチラ見せ JS側から非同期処理の 結果を受け取る 結果をメモリに記録 イベントループを回す この処理を待っている Futureを起こす
今後の展望 現在、Node.js側に非同期処理として任せている のはJSの実行のみ。 ファイル読みこみなどはWASIで行っている。 (=非同期にはなっていない) ここも非同期化できたら面白そう。 しかし独自実装が増えるので大変。
まとめ Rust製のWASMでJS側の非同期処理を待つ、 しかもそれをRustのasync/.awaitで表現する ためには、 ローレベルな非同期ランタイムを用いて自前の イベントループを実装し、 WASMのイベントループをJSのイベントループの 一部として扱えばいい。 ※2024年8月現在の情報です。
宣伝 今回お話ししたアイデアが実際に実装されている ソースコードはこちらで見ることができます。 https://github.com/uhyo/nitrogql