Ractor#send move:true したときに出た3つのエラー - @ledsun blog にて、ディープコピーを減らすためにmoveオプションを使いました。 ところがエラーがでました。またエラーの内容が難解で対応出来そうにありません。 そこで、ディープコピーを減らすための別の方法を考えます。
仮説
ドキュメントを見ると次の記述があります。
ruby/ractor.md at master · ruby/ruby · GitHub
There are 3 ways to send an object as a message (1) Send a reference: Sending a shareable object, send only a reference to the object (fast)
a shareable object は参照のみをコピーです。 ソースコードでは次の箇所が該当しそうです。
https://github.com/ruby/ruby/blob/v3_1_2/ractor.c#L930-L937
else if (rb_ractor_shareable_p(obj)) { basket->type = basket_type_ref; basket->v = obj; } else if (!RTEST(move)) { basket->v = ractor_copy(obj); basket->type = basket_type_copy; }
今回のRactorの構成では、次のように2回Ractor間のデータの受け渡しがあります。
main Ractor -> pipe Ractor -> worker Ractor
ディープコピーが2回走っているはずです。 これを次の振る舞いに変更します。
- main Ractorで送信データをshareableにする
- workerで受信データをディープコピーしてから編集する
これでコピー回数が減り、処理時間が短くなるはずです。
実装
pipe = Ractor.new do loop do msg = Ractor.receive Ractor.yield(msg) end end workers = (1..4).map do Ractor.new pipe do |pipe| while msg = pipe.take a, ref_text, o = msg aligner = TextAlignment::TextAlignment.new(ref_text, o) copy_a = Marshal.load(Marshal.dump(a)) m = copy_a.map do |annotation| Annotation.align_annotations!(annotation, ref_text, aligner) end.flatten result = [m, copy_a] Ractor.yield(result, move: true) end end end annotations_collection_with_doc = annotations_collection_with_doc.collect do |annotations, doc| ref_text = doc.original_body.nil? ? doc.body : doc.original_body msg = [annotations, ref_text, options] Ractor.make_shareable(msg) pipe.send(msg) doc end
ポイントは次の2点です。
main Ractorで送信データをshareableにします。
Ractor.make_shareable(msg) pipe.send(msg)
workerで受信データをディープコピーします。
copy_a = Marshal.load(Marshal.dump(a)) m = copy_a.map do |annotation| Annotation.align_annotations!(annotation, ref_text, aligner) end.flatten
検証
この実装で処理時間が短くなるか確かめてみます。
ディープコピーを減らした結果、処理時間は短くなりました。 期待していたよりは効果は薄く見えます。 また、詰まっているのはワーカーでなくパイプ? - @ledsun blogで掲載したグラフと特徴が異なります。 特に並列数1で処理時間が短くなっていない点が異なります。
前回の計測は、次の2点が異なります。
- AWSではなくローカルPCで計測している。CPUやメモリの性能が異なる。
- DBへのインサート処理をスキップしていない。処理時間中のRactorの動作時間は減っている。
考察
ディープコピーを減らすと処理時間が減ることがわかりました。 しかし、仮説「Ractor間のデータ受け渡し時のコピーがボトルネックになっている」までは確認できませんでした。
つぎの2つに挑戦してみます。
- AWSで性能計測する。ディープコピー削減の影響に関する情報を増やす
- 処理内容をみなおす。ディープコピーをなくす。