Ruby 並行・並列くらべ 2 - @ledsun blog でRactorの並列化とプロセスの並列化が大体同じような性能がでることがわかりました。 Ractorに絞ってもっと性能が出ないか試してみます。 Ractorを作る数を制限していないので、物理コアをこえる数のスレッドを作っています。 それで非効率になっているのでしょうか?
https://github.com/ruby/ruby/blob/master/doc/ractor.md#worker-pool を参考にしてWorker poolを実装して確認してみましょう。
Ractor.make_shareable(TextAlignment::CHAR_MAPPING) Ractor.make_shareable( TextAlignment::LCSMin::PLACEHOLDER_CHAR) pipe = Ractor.new do loop do Ractor.yield Ractor.receive end end workers = (1..4).map do Ractor.new pipe do |pipe| while msg = pipe.take a, d, o = msg m = Annotation.prepare_annotations!(a, d, o) Ractor.yield [m, a] end end end annotations_collection_with_doc = annotations_collection_with_doc.collect do |annotations, doc| pipe << [annotations, doc.dup, options] doc end.map do |doc| _r, (error_messages, annotations) = Ractor.select(*workers) messages += error_messages [annotations, doc] end
Worker poolをいれなかったときは次のソースコードでした。
Ractor.make_shareable(TextAlignment::CHAR_MAPPING) Ractor.make_shareable( TextAlignment::LCSMin::PLACEHOLDER_CHAR) ractors = annotations_collection_with_doc.collect do |annotations, doc| r = Ractor.new do a, d, o = Ractor.receive m = Annotation.prepare_annotations!(a, d, o) Ractor.yield [m, a] end r.send [annotations, doc.dup, options] [r, doc] end annotations_collection_with_doc = ractors.map do |r, doc| error_messages, annotations = r.take messages += error_messages [annotations, doc] end
なかなか複雑になってきました。 実行してみます。
1m 26sです。 Worker pool導入前は1m 32sでした。 7%位の差です。 他に何か原因がありそうです。