Linuxでの fork() は、 Copy on Writeの魅力にもかかわらず、かなり遅い操作です。 同種のタスクが多数ある場合、タスクごとに新しいプロセスを生成することは意味がありません。 したがって、 delayed_jobを使用することにしました 。これは、1サイクルですべてのタスクを順番に実行します。
利点は明らかです。ここで、欠点を解消して実装を高速化する方法に関するヒントをいくつか紹介します。 これらはかなりよく知られた事実だと思いますが、初心者にとっては役に立つはずです。
1つのトランザクションで大量のINSERTをラップする
delayed_jobは、新しいタスクが追加されるたびにdelay_jobsテーブルに挿入します。
ActiveRecordでは、 保存呼び出しはデフォルトでトランザクションにラップされます。 したがって、バックグラウンドタスクの大量作成中に大量のトランザクションを取得しないように、すべてを1つ以上のトランザクションにラップすることをお勧めします。
job_items.in_groups_of(500, false) do |group| ActiveRecord::Base.transaction do group.each do |job_item_id| JobRunner.delay.execute_job(job_item_id) end end end
詳細はこちら: www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance
シリアル化/逆シリアル化のオーバーヘッドを回避
delayed_jobは、タスクを作成するときにデータをシリアライズし、実行の直前にデシリアライズします。 バックグラウンドタスクのパラメーターとして、重いActiveRecordオブジェクトの代わりに、 Fixnum 、 String、またはHashクラスのオブジェクトを渡すことを常にお勧めします。
JobRunner.delay.send_activation_instructions(user.id)
よりもはるかに良い:
JobRunner.delay.send_activation_instructions(user)
コアの数ごとにdelay_jobワーカーを実行します
Rubyのマルチスレッド化には多くの要望が残されているため、通常は複数のプロセスを作成することですべてを並列化します。
例外なし、 delayed_job 。 たとえば、 top / htopに 4つのスレッドが表示されている場合、最高のパフォーマンスを実現するには、4つのワーカーを実行する必要があります。
script/delayed_job -i 0 start script/delayed_job -i 1 start script/delayed_job -i 2 start script/delayed_job -i 3 start
より多くのことができる場合もありますが、ここでは、プロセッサの使用状況を監視し、特定のタスクの詳細を考慮する必要があります。
ちなみに、 delayed_jobには、いくつかのワーカーをmonitで監視するための設定があります(contrib / delayed_job_multiple.monitrcファイルを参照)。
オプショナル
また、次の追加に注意する価値があります。
- github.com/SponsorPay/em-resque (ワーカーが非同期で作業できるようにします)
- github.com/Viximo/delayed_job_redis(Redisを使用するための実験的なバックエンド)
delays_job_redisがRails 3.2で開始できなかったことは注目に値します。