実際のプロジェクトや独自のガジェット (ニュース集計、商品価格監視、価格比較など) を作成するプロセスでは、通常、URL キューを処理する必要がある場合、サードパーティの Web サイトまたは API インターフェイスからデータを取得する必要があります。パフォーマンスを向上させるために、cURL が提供する関数のcurl_multi_* ファミリを使用して、単純な同時実行性を実装できます。
この記事では、2 つの具体的な実装方法について説明し、さまざまな方法の簡単なパフォーマンス比較を行います。
1. 古典的な cURL 同時実行メカニズムとその既存の問題
古典的な cURL 実装メカニズムはオンラインで簡単に見つけることができます。たとえば、PHP オンライン マニュアルの次の実装方法を参照してください。
関数 classic_curl($urls, $lay) {
$queue =curl_multi_init();
$map = array();
foreach ($urls として $url) {
// cURL リソースを作成します
$ch =curl_init();
// URL とその他の適切なオプションを設定します
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
// ハンドルを追加
curl_multi_add_handle($queue, $ch);
$map[$url] = $ch;
}
$active = null;
// ハンドルを実行します
{
を実行します
$mrc =curl_multi_exec($queue, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active > 0 && $mrc == CURLM_OK) {
if (curl_multi_select($queue, 0.5) != -1) {
{
を実行します
$mrc =curl_multi_exec($queue, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
$responses = array();
foreach ($map as $url=>$ch) {
$responses[$url] = callback(curl_multi_getcontent($ch), $lay);
curl_multi_remove_handle($queue, $ch);
curl_close($ch);
}
curl_multi_close($queue);
$responses を返します;
}
まず、すべての URL を並行キューにプッシュして並行処理を実行し、すべてのリクエストを受信した後にデータ解析などの後続の処理を実行します。実際の処理プロセスでは、ネットワーク送信の影響により、コンテンツの内容が異なります。一部の URL は他の URL よりも優先されますが、従来の cURL 同時実行では、処理を開始する前に最も遅い URL が返されるまで待機する必要があります。URL キューが短い場合、このアイドル状態と無駄は依然として残ります。ただし、キューが非常に長い場合、この種の待ち時間と無駄は許容できなくなります。
2. ローリング cURL 同時実行方式の改善
慎重に分析した結果、従来の cURL 同時実行性を最適化する余地がまだあることがわかります。最適化方法は、URL リクエストの完了後にできるだけ早く処理し、処理中に他の URL が返されるのを待つことです。最も遅いインターフェイスを待つのではなく、CPU のアイドル状態や無駄を避けるために、処理やその他の作業を開始します。
関数 rolling_curl($urls, $delay) {
$queue =curl_multi_init();
$map = array();
foreach ($urls として $url) {
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
curl_multi_add_handle($queue, $ch);
$map[(string) $ch] = $url;
}
$responses = array();
{
を実行します
while (($code =curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;
if ($code != CURLM_OK) { ブレーク }
// リクエストが完了しました -- どのリクエストかを調べてください
while ($done =curl_multi_info_read($queue)) {
// リクエストで返された情報とコンテンツを取得します
$info =curl_getinfo($done['handle']);
$error =curl_error($done['handle']);
$results = callback(curl_multi_getcontent($done['handle']), $lay);
$responses[$map[(string) $done['handle']]] = Compact('info', 'error', 'results');
// 完了したばかりのカール ハンドルを削除します
curl_multi_remove_handle($queue, $done['handle']);
curl_close($done['ハンドル']);
}
// 出力データのブロックは、curl_multi_exec
によって行われます。
if ($active > 0) {
curl_multi_select($queue, 0.5);
}
} while ($active);
curl_multi_close($queue);
$responses を返します;
}
3. 2 つの同時実装のパフォーマンス比較
改善前後の性能比較テストはLINUXホスト上で実施しました。テスト時に使用した同時キューは以下のとおりです。http://item.taobao.com/item.htm?id=14392877692
http://item.taobao.com/item.htm?id=16231676302
http://item.taobao.com/item.htm?id=17037160462
http://item.taobao.com/item.htm?id=5522416710
http://item.taobao.com/item.htm?id=16551116403
http://item.taobao.com/item.htm?id=14088310973
実験計画の原理とパフォーマンス テスト結果の形式を簡単に説明します。結果の信頼性を確保するために、1 回の実験で各セットの実験が 20 回繰り返され、同じインターフェイス URL セットが与えられました。古典的な同時実行メカニズム) とローリング (改良された同時実行メカニズムを参照) は、2 つの同時実行メカニズムのうち時間 (秒単位) がかかるものとして個別に測定され、時間が短い方が勝ち (勝者)、節約された時間を計算します。 Excellence (秒単位) とパフォーマンス改善率 (Excel. %) 実験をシンプルに保ちながら、実際のリクエストにできるだけ近づけるために、返された結果に対して単純な正規表現のマッチングのみを実行し、他の複雑な処理は実行しませんでした。さらに、結果処理のコールバックを決定するために、パフォーマンス比較テストの結果に影響を与えるために、usleep を使用して、実際のより責任のあるデータ処理ロジック (抽出、単語の分割、ファイルやデータベースへの書き込みなど) をシミュレートできます。 .)。
パフォーマンス テストで使用されるコールバック関数は次のとおりです:
関数コールバック($data, $lay) {
preg_match_all('/(.+)
/iU', $data, $matches);
usleep($delay);
return Compact('data', 'matches');
}
データ処理コールバックに遅延がない場合: Rolling Curl の方が若干優れていますが、パフォーマンス向上効果は明らかではありません。
------------------------------------------------------------------------------------------------ Delay: 0 micro seconds, equals to 0 milli seconds ------------------------------------------------------------------------------------------------ Counter Classic Rolling Winner Excellence Excel. % ------------------------------------------------------------------------------------------------ 1 0.1193 0.0390 Rolling 0.0803 67.31% 2 0.0556 0.0477 Rolling 0.0079 14.21% 3 0.0461 0.0588 Classic -0.0127 -21.6% 4 0.0464 0.0385 Rolling 0.0079 17.03% 5 0.0534 0.0448 Rolling 0.0086 16.1% 6 0.0540 0.0714 Classic -0.0174 -24.37% 7 0.0386 0.0416 Classic -0.0030 -7.21% 8 0.0357 0.0398 Classic -0.0041 -10.3% 9 0.0437 0.0442 Classic -0.0005 -1.13% 10 0.0319 0.0348 Classic -0.0029 -8.33% 11 0.0529 0.0430 Rolling 0.0099 18.71% 12 0.0503 0.0581 Classic -0.0078 -13.43% 13 0.0344 0.0225 Rolling 0.0119 34.59% 14 0.0397 0.0643 Classic -0.0246 -38.26% 15 0.0368 0.0489 Classic -0.0121 -24.74% 16 0.0502 0.0394 Rolling 0.0108 21.51% 17 0.0592 0.0383 Rolling 0.0209 35.3% 18 0.0302 0.0285 Rolling 0.0017 5.63% 19 0.0248 0.0553 Classic -0.0305 -55.15% 20 0.0137 0.0131 Rolling 0.0006 4.38% ------------------------------------------------------------------------------------------------ Average 0.0458 0.0436 Rolling 0.0022 4.8% ------------------------------------------------------------------------------------------------ Summary: Classic wins 10 times, while Rolling wins 10 times
データ処理コールバック遅延 5 ミリ秒: Rolling Curl が勝利し、パフォーマンスが約 40% 向上しました。
<span style="font-size: 14px; "><span style="font-family: Arial, Helvetica, sans-serif; ">------------------------------------------------------------------------------------------------ Delay: 5000 micro seconds, equals to 5 milli seconds ------------------------------------------------------------------------------------------------ Counter Classic Rolling Winner Excellence Excel. % ------------------------------------------------------------------------------------------------ 1 0.0658 0.0352 Rolling 0.0306 46.5% 2 0.0728 0.0367 Rolling 0.0361 49.59% 3 0.0732 0.0387 Rolling 0.0345 47.13% 4 0.0783 0.0347 Rolling 0.0436 55.68% 5 0.0658 0.0286 Rolling 0.0372 56.53% 6 0.0687 0.0362 Rolling 0.0325 47.31% 7 0.0787 0.0337 Rolling 0.0450 57.18% 8 0.0676 0.0391 Rolling 0.0285 42.16% 9 0.0668 0.0351 Rolling 0.0317 47.46% 10 0.0603 0.0317 Rolling 0.0286 47.43% 11 0.0714 0.0350 Rolling 0.0364 50.98% 12 0.0627 0.0215 Rolling 0.0412 65.71% 13 0.0617 0.0401 Rolling 0.0216 35.01% 14 0.0721 0.0226 Rolling 0.0495 68.65% 15 0.0701 0.0428 Rolling 0.0273 38.94% 16 0.0674 0.0352 Rolling 0.0322 47.77% 17 0.0452 0.0425 Rolling 0.0027 5.97% 18 0.0596 0.0366 Rolling 0.0230 38.59% 19 0.0679 0.0480 Rolling 0.0199 29.31% 20 0.0657 0.0338 Rolling 0.0319 48.55% ------------------------------------------------------------------------------------------------ Average 0.0671 0.0354 Rolling 0.0317 47.24% ------------------------------------------------------------------------------------------------ Summary: Classic wins 0 times, while Rolling wins 20 times</span></span>
上記のパフォーマンス比較から、URL キューの同時実行を扱うアプリケーション シナリオでは、同時実行が非常に大きい (1000 以上) 場合、同時キューの最大長を制御できるため、ローリング cURL がより適切な選択肢となるはずです。 、20 など。URL が返されて処理されるたびに、まだリクエストされていない URL がすぐにキューに追加されます。この方法で記述されたコードはより堅牢になり、同時実行数が大きくなりすぎることはありません。詳細な実装については、http://code.google.com/p/rolling-curl/
を参照してください。