詰まっているのはワーカーでなくパイプ? - @ledsun blog で、「Ractor間のデータ受け渡し時のコピーがボトルネックになっている」という仮説を立てました。 これを確認するために、Ractor間のデータの受け渡しをmoveにしてみます。
次のようにRactor#sendとRactor.yieldを使っている場所に move: true オプションをつけていきます。
pipe = Ractor.new do loop do msg = Ractor.receive Ractor.yield(msg, move: true) 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) m = a.map do |annotation| Annotation.align_annotations!(annotation, ref_text, aligner) end.flatten Ractor.yield([m, a], move: true) end end end Ractor.make_shareable(options) annotations_collection_with_doc = annotations_collection_with_doc.collect do |annotations, doc| ref_text = doc.original_body.nil? ? doc.body : doc.original_body ref_text.freeze pipe.send([annotations, ref_text, options], move: true) doc end
これを実行すると次の3つのエラーが起きるようになりました。 実行するといずれかのエラーがおきて止まります。
安易にmoveオプションをつければいいわけではなさそうです。
パターン1 no implicit conversion of Symbol into Integer (TypeError)
14:07:32 workor.1 | #<Thread:0x00007fda6a006788 run> terminated with exception (report_on_exception is true): 14:07:32 workor.1 | /home/ledsun/pubannotation/app/models/annotation.rb:466:in `[]': no implicit conversion of Symbol into Integer (TypeError) 14:07:32 workor.1 | from /home/ledsun/pubannotation/app/models/annotation.rb:466:in `align_annotations!' 14:07:32 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:767:in `block (3 levels) in store_annotations_collection' 14:07:32 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:766:in `map' 14:07:32 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:766:in `block (2 levels) in store_annotations_collection'
Rubyで一番苦手なエラーです。 ハッシュの代わりに配列が渡されているのでしょうか? エラーが起きている箇所は次のようなソースコードです。
def self.align_annotations!(annotations, ref_text, aligner) return [] unless annotations[:denotations].present? || annotations[:blocks].present?
この呼び出し元は最初のソースコードのAnnotation.align_annotations!(annotation, ref_text, aligner)
です。
いままでハッシュで呼び出していたはずが、配列に変わることがあるみたいです。
同じ変数に格納されている値が変わっているのでしょうか?
何が起きているのか、いまいち想像できません。
パターン2 wrong argument type false (expected Class) (TypeError)
14:21:16 workor.1 | #<Thread:0x00007fda69e0cf18 run> terminated with exception (report_on_exception is true): 14:21:16 workor.1 | <internal:ractor>:627:in `yield': wrong argument type false (expected Class) (TypeError) 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:757:in `block (2 levels) in store_annotations_collection' 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:755:in `loop' 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:755:in `block in store_annotations_collection' 14:21:16 workor.1 | #<Thread:0x00007fda69e0ca90 run> terminated with exception (report_on_exception is true): 14:21:16 workor.1 | <internal:ractor>:694:in `take': thrown by remote Ractor. (Ractor::RemoteError) 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:763:in `block (2 levels) in store_annotations_collection' 14:21:16 workor.1 | <internal:ractor>:627:in `yield': wrong argument type false (expected Class) (TypeError) 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:757:in `block (2 levels) in store_annotations_collection' 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:755:in `loop' 14:21:16 workor.1 | from /home/ledsun/pubannotation/app/models/project.rb:755:in `block in store_annotations_collection'
見慣れないエラーです。
起きている箇所は最初のソースコードのRactor.yield(msg, move: true)
です。
pipe役のRactorがデータを送ろうとしたところで、エラーが起きているようです。
https://github.com/ruby/ruby/blob/v3_1_2/ractor.c を見てみます。
ractor_yield(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move) { VALUE ret_r; ractor_select(ec, NULL, 0, obj, RTEST(move) ? true : false, &ret_r); return Qnil; }
Racter.yieldの引数はobjで、型エラーに引っかかりそうもありません。
どこかでそれらしい引数で rb_raise(rb_eArgError
しているのかというと、こっちもみつかりません。
このエラーはどこで何がおかしいのか、想像できません。
パターン 3 <OBJ_INFO:gc_mark_ptr@gc.c:6713> 0x00007fda6b47ec10 [2 M ] T_NONE
ながいのでgistにしました。 PubAnnotationでRactor#send move:true したときに起きたエラー · GitHub このエラーが起きたときは最終的にSIGIOTでSidekiqプロセスが終了します。 僕は、C言語レイヤーのエラーを上手く読み解けません。 gc_mark_ptr とあるので、GCの途中でエラーが起きているのでしょうか?