読んだ: 詳解 Rustアトミック操作とロック
ちょっとしたご縁があり読む機会がありました。感想を残しておきます。あと、1ヶ月に1回は技術ブログ記事書かな〜ということで...*1。
最初に全体的な感想を残しておくと、この本は僕のように漠然と型を書き、 Clone::clone() を呼び、深く考えずに Rc<RefCell<T>> なメンバを増やしていたようなRustプログラマが次のステップに行くに当たって、重要なことが書かれているように思います。
一読で全てを理解するのは難しいのでは?とも思うのですが、マイルストーンとなる本なのは間違いないと思います。
*1:今月は会社の方には書いたんですよ: https://tech.smarthr.jp/entry/2025/05/19/122754
Component Model対応したruby.wasmをビルドする方法
あまり公式にアナウンスされていない気がするが*1、 ruby.wasm は実はComponent Model対応が済んでいる。
多分この辺から。なので、RubyKaigi 2024の段階ではComponent Model対応したものを動かせていた。スライドで言うとこの辺 *2。
この記事では簡単にビルドの仕方をまとめておく。
command でビルドする
以下の内容の Gemfile を使って:
source "https://rubygems.org" gem "ruby_wasm", "~> 2.7"
以下のコマンドでビルドすればOK*3。
$ RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING=1 bundle exec rbwasm build -o rubyp2.wasm --target wasm32-unknown-wasip2
witを見ると以下の感じになっている(抜粋)。
package root:component;
world root {
import wasi:cli/exit@0.2.0;
import wasi:clocks/wall-clock@0.2.0;
import wasi:random/random@0.2.0;
import wasi:cli/environment@0.2.0;
import wasi:io/error@0.2.0;
import wasi:io/poll@0.2.0;
import wasi:io/streams@0.2.0;
import wasi:clocks/monotonic-clock@0.2.0;
import wasi:cli/stdin@0.2.0;
import wasi:cli/stdout@0.2.0;
import wasi:cli/stderr@0.2.0;
import wasi:cli/terminal-input@0.2.0;
import wasi:cli/terminal-output@0.2.0;
import wasi:cli/terminal-stdin@0.2.0;
import wasi:cli/terminal-stdout@0.2.0;
import wasi:cli/terminal-stderr@0.2.0;
import wasi:filesystem/types@0.2.0;
import wasi:filesystem/preopens@0.2.0;
export wasi:cli/run@0.2.0;
}
こうなので、成果物は wasmtime でそのまま実行できる。
$ wasmtime rubyp2.wasm --version ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [wasm32-wasi]
reactor でビルドする
Gemfile に js gemを含む必要があるらしい。参照
source "https://rubygems.org" gem "ruby_wasm", "~> 2.7" gem "js"
コマンドは同じでOK。
$ RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING=1 bundle exec rbwasm build -o rubyp2-reactor.wasm --target wasm32-unknown-wasip2
wit が結構変わっていて、 ruby:js/js-runtime を必要とし、 ruby:js/ruby-runtime を export している。
package root:component;
world root {
import wasi:cli/exit@0.2.0;
import wasi:clocks/wall-clock@0.2.0;
import wasi:random/random@0.2.0;
import ruby:js/js-runtime;
import wasi:cli/environment@0.2.0;
import wasi:io/error@0.2.0;
import wasi:io/poll@0.2.0;
import wasi:io/streams@0.2.0;
import wasi:clocks/monotonic-clock@0.2.0;
import wasi:cli/stdin@0.2.0;
import wasi:cli/stdout@0.2.0;
import wasi:cli/stderr@0.2.0;
import wasi:cli/terminal-input@0.2.0;
import wasi:cli/terminal-output@0.2.0;
import wasi:cli/terminal-stdin@0.2.0;
import wasi:cli/terminal-stdout@0.2.0;
import wasi:cli/terminal-stderr@0.2.0;
import wasi:filesystem/types@0.2.0;
import wasi:filesystem/preopens@0.2.0;
export ruby:js/ruby-runtime;
}
これらは js.gem の方でwitを置いている 。したがって、JS側でどういう関数を用意して、Rubyの機能としてはどういうものが使えるのかが大変わかりやすくなっている。
僕はこう思ったっス
すでにComponent化して import/export で何を切り出すか調整できる状態になってそうだし、そもそもComponentなので薄いアダプターComponentをいい感じに作れば、 componetize-rb は普通にできるっぽい。wasmcloudで頑張って動かすというのをやるとかはいいと思った。Go、Rust、TypeScriptしかない ので、Pythonが追加される前に...。
で、そうすると、純粋にjsじゃないreactor版が欲しい感じがする。