あらすじ
tl;dr
- 自作WASM Runtimeでグレースケール処理を動かした
- グレースケール処理はRustで書いたもの
- WebAssembly specificationはテストケース付きで公開されてるので便利
Wardite
というWASM Runtimeを作っていました。
今の所、「RustでWasm Runtimeを実装する」の内容を一通り実装した段階です。
fibまで動くようになったので、ゴリラさんのコースの範囲は一旦完成
— Uchio Kondo💥 (@udzura) 2024年10月28日
あとはwasm坂を登り続けるだけだ... pic.twitter.com/65m8qbSvap
以下のようなwasmプログラムを動かせます。
(module (func $fib (export "fib") (param $n i32) (result i32) (if (i32.lt_s (local.get $n) (i32.const 2)) (then (return (i32.const 1))) ) (return (i32.add (call $fib (i32.sub (local.get $n) (i32.const 2))) (call $fib (i32.sub (local.get $n) (i32.const 1))) ) ) ) )
$ gem install wardite $ wat2wasm fib.wat $ wardite ./fib.wasm fib 20 return value: 10946続きを読む
wasmの可能性を「理解」したくてwasmCloudをさわってみている。動かしてみたメモや感想などを晒しておく
wasmCloud公式のGetting Startedに書いてあるレベルのことしかしていないので、これから学ぶ人は直接そっちを読んだほうがいいと思う。
この記事は単に「副読本」というぐらいの認識でいいかなという感じ。
multipassでセットアップした Ubuntu 22.04 (まだ24にしてない) カーネルの更新もサボってる...。
ubuntu@primary:~$ uname -a Linux primary 5.15.0-118-generic #128-Ubuntu SMP Fri Jul 5 09:30:28 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux
wash はすぐにインストールできる。
まず必要なプロセスを立ち上げるらしい。
$ wash up >>> ⡋⠁ Starting wadm ... Downloading new wadm from https://github.com/wasmcloud/wadm/releases/download/v0.14.0/wadm-v0.14.0-linux-aarch64.tar.gz >>> ⠈⢙ Starting wadm ... Saved wadm to /home/ubuntu/.wash/downloads/wadm 🏃 Running in interactive mode. 🎛️ To start the dashboard, run `wash ui` 🚪 Press `CTRL+c` at any time to exit 2024-08-25T09:19:54.778375Z INFO async_nats_wrpc: event: connected 2024-08-25T09:19:54.780084Z INFO async_nats_wrpc: event: connected 2024-08-25T09:19:54.785723Z INFO wasmcloud_host::wasmbus: created bucket with 1 replica bucket=LATTICEDATA_default 2024-08-25T09:19:54.787211Z INFO wasmcloud_host::wasmbus: created bucket with 1 replica bucket=CONFIGDATA_default 2024-08-25T09:19:54.790602Z INFO wasmcloud_host::wasmbus: wasmCloud host started host_id="NAM6TTXMMZNG5VLQTE3JMIPCPNXYGCWC45E4VCEYJGHAGLX4CZ7EW4NA"
ドキュメントの通りNATSと、wadmというプロセスが立ち上がった。
\_ wash up \_ /home/ubuntu/.wash/downloads/nats-server -js --addr 127.0.0.1 --port 4222 --pid /home/ubuntu/.wash/downloads/nats.pid --config /home/ubuntu/.wash/downloads/nats.conf \_ /home/ubuntu/.wash/downloads/wadm --nats-server 127.0.0.1:4222 \_ /home/ubuntu/.wash/downloads/v1.2.0/wasmcloud_host
NATS は汎用メッセージングサーバー。仕事でも使ったことがあるが、極めて安定していて使いやすい(特にGoからだとライブラリが整備されていて使いやすい)、その上パフォーマンスが出る、みたいなOSSのPub/Subサーバで、個人的に今回採用されたのも納得。
ちょっと性質が違うけど例えば昔ZeroMQとかを使ったことがある人は、同じような感じで使えたりするので別途試してもいいと思います。
ちなみに NATS はembedded NATS serverという、組み込んで使うより便利なやり方もあるんだけど、これはGoでしかできなくて(NATS serverはGo製のため)、wadmの言語はRustなのでNATSは別立てになっているのだろう。
多分NATSは本当にメッセージの仲介しかしていないはずで、ポイントはwadmにありそう。
READMEを見ると、
が責務ですよと言っており、Kubernetesで言うコントロールプレーン+Kubelet相当を1台で引き受ける、簡易版インスタンスマネージャーといったところだろうか。wasmのインスタンス?ワーカー?は lattice(格子模様) という単位でまとめられているらしい。あと、wadm自身だけでクラスタリング等ができるかは調べていない。
あと、 wasmcloud_host
と言うプロセスが立ち上がってる。これは何。
それぞれのwasmインスタンスはActorという単位で管理される、HostはそれらとOSをWASIで繋ぎます、みたいに読める。では実はこっちがKubelet相当? ちょっと色々いじりながら理解したい感じ。
さて、washを使ってプロジェクトのスケルトンが作れそうなので作る。今回はRust。
$ wash new component hello --template-name hello-world-rust 🔧 Cloning template from repo wasmCloud/wasmCloud subfolder examples/rust/components/http-hello-world... 🔧 Using template subfolder examples/rust/components/http-hello-world... 🔧 Generating template... [ 1/62] Done: .gitignore [ 2/62] Done: Cargo.toml [ 3/62] Done: README.md [ 4/62] Done: local.wadm.yaml [ 5/62] Skipped: project-generate.toml [ 6/62] Done: src/lib.rs [ 8/62] Done: wadm.yaml [ 9/62] Done: wasmcloud.toml [10/62] Done: wit/deps/cli/command.wit [11/62] Done: wit/deps/cli/environment.wit [12/62] Done: wit/deps/cli/exit.wit ✨ Done! New project created /home/ubuntu/hello
結構色々なものがつくられるのだが、Cargo.tomlを見るとdependencyに wit-bindgen = "0.30"
が勝手に入ることとなる。
生成された src.rs はこういう感じで:
wit_bindgen::generate!({ generate_all }); use exports::wasi::http::incoming_handler::Guest; use wasi::http::types::*; struct HttpServer; impl Guest for HttpServer { fn handle(_request: IncomingRequest, response_out: ResponseOutparam) { let response = OutgoingResponse::new(Fields::new()); response.set_status_code(200).unwrap(); let response_body = response.body().unwrap(); ResponseOutparam::set(response_out, Ok(response)); response_body .write() .unwrap() .blocking_write_and_flush(b"Hello from Rust!\n") .unwrap(); OutgoingBody::finish(response_body, None).expect("failed to finish response body"); } } export!(HttpServer);
これはパブリッククラウドのFunction as a Serviceのコードを彷彿とさせる。こういう感じのプラットフォームをOSSで動かせるというのは期待が持てるなと思う。
で、wit_bindgenの generate_all
は多分生成されたwitを自動で読んで色々やってくれる感じか? 例えばこういうファイルが生成されている。
package wasi:cli@0.2.0; world command { include imports; export run; }
あと生成された wasmcloud.toml
には
[component] wit_world = "hello" wasm_target = "wasm32-wasi-preview2"
こういう記述もある。なのでここもビルド時に? 参照しそう。
一旦ビルドして動かしてみる(cargoはセットアップすること)。
$ wash build ... Component built and signed and can be found at "/home/ubuntu/hello/build/http_hello_world_s.wasm"
wit/world.wit
というのが生成されたっぽい、これが「関数」のエントリポイントとなりそう。
package wasmcloud:hello; world hello { export wasi:http/incoming-handler@0.2.0; }
デプロイはこう。即で終わる。
$ wash app deploy wadm.yaml Deployed application "rust-hello-world", version "01J64FG1JQ4Y0YRAH4NGK7N636" $ wash app list Name Deployed Version Status rust-hello-world 01J64FG1JQ4Y0YRAH4NGK7N636 Deployed └ HTTP hello world demo in Rust, using the WebAssembly Component Model and WebAssembly Interfaces Types (WIT)
$ curl localhost:8080 Hello from Rust!
できました。
wadm.yaml
をみると、レプリカ数などのKube感あるパラメータを発見できるので、今度色々いじってみよう。
もう一つポイントは、Pythonはすでにサポートされている。これはcomponentize-pyベースでやってるらしいのでバイナリサイズが大きいのかもしれないが、とにかく動くには動くらしい(次回試します)。
If you prefer working in a language that isn't listed here, let us know!
そうなりますよね。
正直、 mruby/edge 的なアプローチじゃなく、 MRI のコア部分(コアとは)をwasmにした後でcomponentize-pyみたいなアプローチでくっつける方も掘り進みがいがあるんだろうなと思うが、いずれにせよ理解の解像度が低い(componentize-pyって何してるの?から)。
RubyKaigi 2024二日目(16th, May)に登壇します。
本ブログで前々から言っている mruby/edge に関する発表です。
構想自体ははっきり言って去年のRubyKaigi CfPオープンぐらいからあって、地道な素振りをしていた。懐かしい。
発表は英語で行うらしい。日本語で事前情報がある方が頭に入りやすい方も多いかと思うので、メモがてら話そうとしていることを残しておく。無論当日までに変わる可能性もある*1。
*1:翻訳者向け事前提出がない英語発表者のアドを全力で活かすスタイル
mec v0.3.0 より、mruby/edgeでimportするJavaScript(など)の関数、あるいはexportするRuby側のトップレベルメソッドの引数や戻り値で、Stringを扱えるようにした。
ここで、WebAssembly(WASM)においては現状文字列を扱うのはトリックが必要なので、その辺踏まえた仕様と使い方をまとめておきたい。
English version will show up on RubyKaigi...
続きを読む