4

多くの URL (数万) を保持するデータベースを使用しています。特定のドメインを解決しようとするリゾルバーをマルチスレッド化しようとしています。成功すると、結果を現在データベースにあるものと比較します。異なる場合は、結果が更新されます。失敗した場合も更新されます。

当然、これにより膨大な量のデータベース呼び出しが生成されます。ある種の非同期負荷分散を実現する最善の方法についての私の混乱を明確にするために、次の質問があります (Perl にはまだかなり慣れていません)。

  1. ワークロードを分散するための最適なオプションは何ですか? なんで?
  2. スポーンする前に解決する URL を収集するにはどうすればよいですか?
    • 比較するデータでドメインのハッシュを作成することは、私にとって最も理にかなっているようです。次に、それを分割し、子を起動し、子が変更を親に返す
  3. 親にデータを返すことは、クリーンな方法でどのように処理する必要がありますか?

私はよりpythonicな方法で遊んでいます(Pythonでの経験が豊富であるため)が、何らかの理由でブロッキングが不足しているため、まだ機能していません。その問題を除けば、スレッド化は単に各スレッドの CPU 時間が (不足している) ため、最良の選択肢ではありません (さらに、スレッドを使用するために Perl チャネルで何度も十字架につけられました:P と正当な理由で)

以下は、多かれ少なかれスレッドで遊んでいる疑似コードです (これは、何よりも、私が達成しようとしていることの説明の補足として使用する必要があります)。

# Create children...
for (my $i = 0; $i < $threads_to_spawn; $i++ )
{
    threads->create(\&worker);
}

次に、親はループ内に座って、ドメインの共有配列を監視します。空になると、ロックして再設定します。

4

1 に答える 1

3

あなたのコードは永続的なワーカー モデルの始まりです。

use threads;
use Thread::Queue 1.03 qw( );

use constant NUM_WORKERS => 5;

sub work {
   my ($dbh, $job) = @_;
   ...
}

{
   my $q = Thread::Queue->new();

   for (1..NUM_WORKERS) {
      async {
         my $dbh = ...;
         while (my $job = $q->dequeue()) 
            work($dbh, $job);
         }
      };
   }

   for my $job (...) {
      $q->enqueue($job);
   }

   $q->end();
   $_->join() for threads->list();
}

パフォーマンスのヒント:

  • システムとワークロードのワーカー数を微調整します。
  • 小さなジョブを大きなジョブにグループ化すると、オーバーヘッドが減り、速度が向上します。
于 2013-06-17T23:17:46.980 に答える