delay_jobを使用して多数のタスクを処理する

私はresqueの大ファンですが、 Redisをリポジトリとして使用していますが、多数のバックグラウンドタスクをすばやく実行する必要がある場合、場合によっては、新しいタスクが実行されるたびにfork()を呼び出さないため、 delayed_jobがより効率的に機能します。



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オブジェクトの代わりに FixnumString、または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ファイルを参照)。



オプショナル


また、次の追加に注意する価値があります。





delays_job_redisがRails 3.2で開始できなかったことは注目に値します。



All Articles