並列処理だとparalellが有名だけど、これは最初に決まった数のタスクがたくさんあって、mapやeachするとその部分がスレッド化してわーっと一斉にやるような感じなので、ちょっと自分が求めているものとは違った。
今回欲しかったのはそういうのではなくて、ちょうどWebサーバみたいな感じにぽつぽつとタスクがやってきてそれをワーカースレッドに割り振って処理させるようなやつ。
で、rubygems.orgやruby-toolbox.comを見て良さそうだなと絞ったのが上記のふたつ(これのほうがいいよ!とかあったら教えて下さい)。
RubyのQueueははじめからスレッド間のFIFOとして設計されているので、これを使えば自分でも簡単にワーカースレッドパターンは作れるのだけど、アプリケーション終了時のワーカーの安全な停止だとか色々な部分に気を配り始めると結構面倒なことになってくるので、それならすでにあるgemを使うほうがいいな、と。
workers
workersは何種類かの並列処理パターンを提供していて使い勝手が良さそうに思った。目当てのワーカースレッドの他にもparallelと同じようなmap処理や周期的なタイマー処理もあったりして、わりと色々なことができる。
それぞれの分かりやすい使用例が1ページのドキュメントまとまっているので、ここにサンプルコードを書くよりはそっちを見てもらったほうがよいかも。
Workers
http://rubydoc.info/gems/workers/0.2.2/frames
thread
標準ライブラリともろかぶりな名前のこちらは、require "thread/pool"
のようにして組み込みのThreadクラスを拡張する形でスレッドプールやfuture/promise/delayといったいくつかの並列処理パターンを実現してくれる。Everyを使えばworkersのタイマー処理と同じこともできる。これも各パターンの使用例が1ページにまとまっているので見てもらったほうがよい。
thread
http://rubydoc.info/gems/thread/0.1.3/frames
celluloid
上記の他にcelluloidという、いわゆるアクターモデルによる並列処理をするgemもあるんだけど、ちょっと自分には巨大すぎて扱える気がしなかったのでパスした。ちょうどcelluloidを利用している別のライブラリで不可解な動きにハマった経験もあったので、容易には手を出すべきではないな、と。
今回はworkersを使ってみた
threadはちょこっと並列処理をするにはシンプルでよいと思うんだけど、今回の用途としてはちょっとシンプル過ぎたのでworkersを採用してみた。workersはsynchronizeがあったり、リトライがあったり、成功と失敗をグループ分けできたりと色々な機能がついてるのがちょっと嬉しかった。
そのうちpromiseとかパイプライン的な処理がしたくなったりしたらthreadを使ってみるのもいいかなーと思っている。
0 件のコメント:
コメントを投稿