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

Rustハンズオン第5回 WebAssembly編

68dad178ea4fa6aa86862b3a66a15306?s=47 Yuki Toyoda
May 15, 2021
1.8k

Rustハンズオン第5回 WebAssembly編

2021/05/12に開催した社内向けハンズオンの資料です。

68dad178ea4fa6aa86862b3a66a15306?s=128

Yuki Toyoda

May 15, 2021
Tweet

Transcript

  1. Rust ハンズオン第 5 回 WebAssembly 編 1

  2. 目次 1. Yew で体験する Rust によるフロントエンド開発 2. Web Assembly とは何か?

    2
  3. 本日の免責事項 WebAssembly はとくに詳しいわけでも専門ではありません。 Rust コミュニティにいると WebAssembly の話を近くで聞くことが多いので、聴いた話 を元に情報をまとめ直しています。 誤り等ありましたら Slack

    で教えて下さい。 3
  4. Yew で体験する Rust によるフロントエンド開発 1. Yew とは 2. 裏の仕組み 3.

    動かす前の事前準備 4. カウンタアプリを書いて、動かしてみる 4
  5. Yew とは WebAssembly によってマルチスレッドな Web アプリケーションのフロントエンドを作 ることができるフレームワーク。 Elm や React

    に使い心地は似ている。 5
  6. 裏の仕組み Rust のビルドターゲットを WebAssembly にすることで、wasm を吐き出せるのでそれ を利用している。 6

  7. 動かす前の準備 wasm-pack のインストール miniserve のインストール 7

  8. 動かす前の準備 wasm-pack cargo install wasm-pack 8

  9. 動かす前の準備 miniserve cargo +nightly install miniserve 9

  10. カウンタアプリを書いて、動かしてみる プロジェクトを作成しましょう cargo new --lib coutner-app && cd counter-app 10

  11. カウンタアプリを書いて、動かしてみる Yew と wasm-bindgen を追加する Cargo.toml に追加してください。 [dependencies] yew =

    "0.17" wasm-bindgen = "0.2" 11
  12. カウンタアプリを書いて、動かしてみる crate-type を変える Cargo.toml に追加してください。 [lib] crate-type = ["cdylib", "rlib"]

    12
  13. カウンタアプリを書いて、動かしてみる use wasm_bindgen::prelude::*; use yew::prelude::*; struct Model { link: ComponentLink<Self>,

    value: i64, } enum Msg { AddOne, } impl Component for Model { type Message = Msg; type Properties = (); fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self { Self { link, value: 0, } } fn update(&mut self, msg: Self::Message) -> ShouldRender { match msg { Msg::AddOne => self.value += 1 } true } fn change(&mut self, _props: Self::Properties) -> ShouldRender { false } fn view(&self) -> Html { html! { <div> <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button> <p>{ self.value }</p> </div> } } } #[wasm_bindgen(start)] pub fn run_app() { App::<Model>::new().mount_to_body(); } 13
  14. カウンタアプリを書いて、動かしてみる static というディレクトリを作る。 下記を含む index.html を書く。 <!DOCTYPE html> <html lang="en">

    <head> <meta charset="utf-8" /> <title>Yew Sample App</title> <script type="module"> import init from "./wasm.js"; init(); </script> </head> <body></body> </html> 14
  15. カウンタアプリを書いて、動かしてみる 起動してみましょう wasm-pack build --target web --out-name wasm --out-dir ./static

    miniserve ./static --index index.html 15
  16. カウンタアプリを書いて、動かしてみる Component トレイトが実質の処理の中心になっている。 16

  17. カウンタアプリを書いて、動かしてみる Component トレイト 重要な内容を取り出して説明します。 pub trait Component: Sized + 'static

    { type Message: 'static; type Properties: Properties; fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self; fn update(&mut self, msg: Self::Message) -> ShouldRender; fn change(&mut self, _props: Self::Properties) -> ShouldRender; fn view(&self) -> Html; } 17
  18. カウンタアプリを書いて、動かしてみる Message コンポーネントによって処理され、何らかの副作用を引き起こすことができるさまざま なメッセージを表す。 API リクエストをトリガーしたりなどを行う。 今回は「 AddOne 」という命令を enum

    の variant として定義しておき、カウンタを増 加させる実装をしている。 18
  19. カウンタアプリを書いて、動かしてみる Properties React などの Properties と同じ。 親からコンポーネントに渡される情報を表す。 今回は実装していないが、 Properties トレイトというものがあり、使用する際はそれ

    を実装している必要がある。 19
  20. カウンタアプリを書いて、動かしてみる create ライフサイクルフックの一つ。 コンポーネントの初期化などを行う。 Properties の受け取りは React と同じように。 ComponentLink は、コンポーネントに登録可能なコールバックを管理したり、コンポ

    ーネントの更新の範囲を制御したりする際に使用できる機能。 fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self { Self { link, value: 0, } } 20
  21. カウンタアプリを書いて、動かしてみる update メッセージを受け取り、副作用のあるコンポーネント内の状態更新を行う。 ShouldRender はレンダリングし直すかどうかを制御できる型。 fn update(&mut self, msg: Self::Message)

    -> ShouldRender { match msg { Msg::AddOne => self.value += 1 } true } 21
  22. カウンタアプリを書いて、動かしてみる change 親コンポーネントから再レンダリングを要求された場合の動作を制御できる。 新しくプロパティの内容を受け取り、その内容を元に再レンダリングさせるといった手 が取れる。 fn change(&mut self, _props: Self::Properties)

    -> ShouldRender { false } 22
  23. カウンタアプリを書いて、動かしてみる view HTML を書いて UI を宣言できる。 html! マクロにより素の HTML が書ける

    ← 黒魔術すぎてすごい fn view(&self) -> Html { html! { <div> <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button> <p>{ self.value }</p> </div> } } 23
  24. 増やしたカウンタを減らす実装を追加してみましょう Msg に SubOne 命令を追加する。 update 関数のパターンマッチングで、 SubOne 命令を受け取るパターンマッチの腕 を追加し、カウントを

    1 減らす処理を書く。 view に -1 と表記されたボタンを追加する。 24
  25. 使ってみての疑問 CSS とかどうするの? 現時点では外部 css に定義するしかなさそう? ごめんなさい調べ中です。 個人的には React にそろえてくれると嬉しい。

    25
  26. WebAssembly とは何か? 26

  27. WebAssembly とは何か ブラウザ上で実行できるバイナリ形式のこと。 ユーザーは作り方を知らなくてよいくらい隠蔽されている。 WebAssembly は JavaScript の置き換えを意図してはいない。 27

  28. https://blog.logrocket.com/webassembly-how-and-why-559b7f96cd71/ 28

  29. wasm と wat WebAssembly はバイナリフォーマットなので、(なれていない限り)読むことはでき ない。 WebAssembly Text Format に直すと読める。

    wasm2wat というツールを使うか、 ブラウザで: https://webassembly.github.io/wabt/demo/wasm2wat/ wat は S 式で表現される形式。 先ほど作った Yew の wasm を wat にして見てみましょう。 29
  30. ブラウザで動くとはどういうことか? https://forge.autodesk.com/ja/node/1434 30

  31. WebAssembly の良さ JavaScript と比較すると処理速度が安定的で実行速度を制御しやすい JavaScript よりも速くなるケースがある 安全である WebAssembly そのものがひとつの規格になっていて、ポータビリティがある 31

  32. JavaScript と比較すると処理速度が安定的で実行速度を制御しやすい 実行時の最適化をあまり伴わない。 コンパイルタイムで最適化が走る。 ブラウザによっては JIT を用いるものもあるらしい。 ただしいずれにせよ最適化は事前に行われる。 気まぐれな速度向上や低下が起きにくくなる。 32

  33. JavaScript よりも速くなるケースがある コンパイルタイムでバイナリを生成し、最適化まで行った状態にするため。 JavaScript と比べると機械語に近くなる。 コンパイルそのものはストリーミングで行う。コードが届いたタイミングで逐一コンパ イルが行われ、バイナリに直される。 それを可能にするようなバイナリフォーマットを持っている。 興味のある方向け: https://livebook.manning.com/book/webassembly-in-

    action/chapter-2/15 33
  34. https://medium.com/@tydxapp/this-article-is-the-third-part-of-a-series-of-posts-about- our-journey-on-webassembly-8d1fafdc4b98 34

  35. 安全である WebAssembly はサンドボックス化された実行環境上で動作するように設計されてい る。 WebAssembly はホスト側のメモリには直接アクセスしないように設計されている。代 わりに線形メモリと呼ばれるバイト列を使用してメモリを管理する。 35

  36. WebAssembly そのものがひとつの規格になっていて、ポータビリティがある これは後ほど話をするが、WebAssembly ランタイムというものを作って、さまざまな 環境で使用できる実行環境として使っていく策が模索されている。 36

  37. WebAssembly はどこで使われているの? Google Meet のぼかし機能: https://zenn.dev/kounoike/articles/google-meet-bg- features Google Earth: https://medium.com/google-earth/google-earth-comes-to-more-

    browsers-thanks-to-webassembly-1877d95810d6 eBay のバーコード読み取り: https://medium.com/ebaytech/webassembly-at-ebay-a- real-world-use-case-ef888f38b537 弊社でも利用した記事を見つけた。mp3 エンコーダを WebAssembly 化して使用すると いう手: https://developers.cyberagent.co.jp/blog/archives/20506/ vim.wasm: https://github.com/rhysd/vim.wasm 画像処理関係、音声関係(Google Meet では雑音抑制にも使われているらしい)での利 用事例が多い。あるいは、ブラウザゲームでの利用が期待されると言われている。 37
  38. ブラウザ外の WebAssembly 38

  39. ブラウザの外で WebAssembly を使うってどういうこと? ブラウザの中で、ファイルアクセスやネットワークが扱えるのはなんとなくわかる。 でも、ブラウザの外でそれを可能にするには一体どうやるの…? 39

  40. WASI: WebAssembly System Interface WebAssembly でファイルアクセスやネットワークを扱えるようにするもの。 ただ、OS に直接アクセスさせるわけではなく、間に wasm が入る。ので、安全。

    POSIX みたいなもの。 まだ開発途上。 40
  41. WebAssembly ランタイムという存在 WASI に対応した WebAssembly ランタイムが作られている。 ランタイムをインストールした環境であればどこでも実行可能ということ。 代表的なものは下記。 Wasmer: サポート言語やコンパイラバックエンドが広い。

    Wasmtime: 小さいのがウリらしい。 Lucet: Fastly 社が作っている。 WebAssembly を出力可能な言語なら、この上で普通に動かせる。Go でも C でも Rust でも Swift でも…! 41
  42. Web の外の WebAssembly の具体的な利用例 Proxy-Wasm: プロキシサーバと拡張機能との間の ABI を定義するもの。たとえば Envoy に使用されているものが最近話題。

    Krustlet: Kubernetes 上で wasm コンテナを実現するプロジェクト Kernel-wasm: Linux カーネル上でコンテキストスイッチなしで wasm バイナリを動かせ る。 42
  43. まとめ WebAssembly はブラウザ上で動かせるバイナリ形式のフォーマットだった。 が、近年ではそのポータビリティによって、ブラウザの外で動かすランタイムとしての 使い方が模索されている。 発展途上の技術なので、これからの動向は引き続き注視する必要がある。 43