Ractorに入門してみた - 基本的なところでハマった編 -
背景
ruby で書き始めたちょっとしたツールで、処理する対象量の都合で並列実行したいな、となり、できればやはり複数 CPU 使いたいなということで、Ruby って Process 以外で今って何かできるんだっけと見たら Ractor というのがあるんですね。
Ractor 自体は
などなど見てもらうのが良いと思います。なんせ、まだ私はわからないことだらけなので。
で experimental ということですが、作ろとしているツールは1回ぽっきり的なので、それなら勉強がてら(最近この手のもので新しいことを使う機会が少ないこともあり)使ってみようと思い手を付けてみました。
この記事は、やってみて、適当な理解なせいでしばらくハマった内容を書いたものです。 ちゃんと考えればわかるでしょ、的な自戒な意味を込めた記事。
なお、rubyのバージョンは以下。
$ ruby --version ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-darwin19]
間違い実装
Consumers - Producer 的な感じなものを実装したくて、プロタイピング的になんとなくで書いてみました。(dame.rb
とします)
def main producer = Ractor.new do get_data.each do |d| Ractor.yield Ractor.make_shareable(d, copy: true) end Ractor.yield :term end consumer = Ractor.new producer do |producer| loop do d = producer.take break if d == :term puts "consumer: #{d['value']}" end end # producer 完了待ち producer.take # consumer 完了待ち consumer.take end def get_data [ { 'id' => 1, 'value' => 'aaa'}, { 'id' => 2, 'value' => 'bbb'}, { 'id' => 3, 'value' => 'ccc'}, { 'id' => 4, 'value' => 'ddd'}, ] end main
- producer からデータ流して、
- consumer で受け取って何か処理
- 後は終了待ち
みたいなやつです。
これ実行すると
$ ruby dame.rb <internal:ractor>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. consumer: bbb consumer: ccc consumer: ddd
みたいな感じで、一個データが consumer に渡っていなんですよ。 これにしばらく悩みました。。。
原因は
# producer 完了待ち
producer.take
これ。
当然ですよね。。。
producer.take
するってことは producer
が Ractor.yield
したやつを受け取るので、ここに1つ producer
から流されたデータが渡ってきていた、というだけ。
終了待ちは take
だからという適当な理解で書いてしまった、というオチです。
動くようにしたもの
動くようにするには、この実装だと最後の待ちの順番を入れ替えるだけ。
# consumer 完了待ち consumer.take # producer 完了待ち producer.take
これだと期待通り。
$ ruby ok.rb <internal:ractor>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. consumer: aaa consumer: bbb consumer: ccc consumer: ddd
さて、動いていはいるけど、これで本当に良いのか全く自信なし。
:term
みたいなメッセージ投げるのが正しいのだろうか、というのも。
make_shareable
のところはこの記事的なところだと copy: true
必要はないけど、今後予定のことを考えてそうしてはいます。
まだまだ理解に乏しいけど、実装しながら学んでいくことにします!!
(初めから〇〇言語で書けば、というのはあるが...それは置いとく)