2025/05/26 21:49 Unlocking Ractors: class instance variables in Ruby

ロボ子、今日のITニュースはRubyのRactorに関するものじゃ。Ractorって並列処理を可能にする仕組みのことじゃけど、クラスインスタンス変数が原因で競合が起きて、思ったより速くならない問題があったみたいじゃぞ。

なるほど、RactorはRuby VMのグローバルロックが必要な操作があって、並列実行の効果を邪魔してしまうんですね。クラスインスタンス変数とクラス変数が競合の要因になるとのことですが、具体的にはどういうことでしょうか?

そうじゃな。クラスはグローバルじゃから、そのインスタンス変数もグローバルなんじゃ。メインRactorだけがクラスインスタンス変数を設定できて、セカンダリRactorは読み込むことしかできない。しかも、格納されたオブジェクトは共有可能である必要があるんじゃ。

セカンダリRactorで書き込みができないのは、競合を防ぐためですね。でも、読み込みだけでもVMロックが必要になるのはなぜですか?

インスタンス変数は連続した配列に格納されていて、Shapeが各変数のオフセットを追跡しておる。セカンダリRactorでは、Shapeとフィールドの一貫性を保つためにVMをロックする必要があるんじゃ。

Shapeとフィールドの一貫性を保つ、ですか。難しそうですね。

大丈夫じゃ、ロボ子!簡単に言うと、インスタンス変数の場所や種類を管理する情報がShapeで、そのShapeがズレないようにロックが必要ってことじゃ。

なるほど!それで、どうやって競合を減らしたんですか?

インスタンス変数をクラスやモジュールに直接格納する代わりに、Objectに格納するようにしたんじゃ。そして、書き換えるときには、現在の状態をコピーして、安全に書き換えて、最後にフィールドオブジェクト参照をアトミックに交換するんじゃ。

アトミックな操作を使うことで、Shapeの更新前に新しいフィールドが他のスレッドから見えることを保証するんですね。それによって、ロックの必要がなくなった、と。

その通り!その結果、クラスインスタンス変数周りのロックが削除されて、マイクロベンチマークのRactor版がシングルスレッド版より約3倍も速くなったんじゃ!Ruby 3.4と比較すると13倍以上じゃぞ!

すごい!大幅な改善ですね。でも、別のオブジェクトにインスタンス変数を格納すると、メモリ使用量が増えませんか?

そこは大丈夫!別のオブジェクトに格納しても、メモリ使用量は増えない可能性があるんじゃ。それに、ネームスペース機能に関連するバグとパフォーマンスの低下も修正できたみたいじゃぞ。

それは素晴らしいですね!Ractorの性能が向上することで、Rubyの並列処理がもっと活用できるようになりますね。

そうじゃな!これでロボ子も、もっと速くお手伝いできるぞ!…って、ロボットだから元々速かったか!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。