重复使用相同的卷曲手柄。性能大幅增加?

时间:2010-09-24 12:21:57

标签: php performance curl

在php脚本中,我正在为不同的URL做很多不同的cUrl GET请求(一百个)。

从curl_init重用相同的curl句柄会改善性能,还是与cURL请求的响应时间相比可以忽略不计?

我问的是,因为在当前的架构中,保持相同的cUrl句柄并不容易。

谢谢,

本杰明

6 个答案:

答案 0 :(得分:44)

Should I close cURL or not?转发,因为我认为它也与此相关。

我尝试使用每个请求的新句柄并使用相同的句柄和以下代码进行卷曲:

ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
for ($i = 0; $i < 100; ++$i) {
    $rand = rand();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "http://www.google.com/?rand=" . $rand);
    curl_exec($ch);
    curl_close($ch);
}
$end_time = microtime(true);
ob_end_clean();
echo 'Curl without handle reuse: ' . ($end_time - $start_time) . '<br>';

ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
$ch = curl_init();
for ($i = 0; $i < 100; ++$i) {
    $rand = rand();
    curl_setopt($ch, CURLOPT_URL, "http://www.google.com/?rand=" . $rand);
    curl_exec($ch);
}
curl_close($ch);
$end_time = microtime(true);
ob_end_clean();
echo 'Curl with handle reuse: ' . ($end_time - $start_time) . '<br>';

并得到以下结果:

  

没有句柄重用的卷曲:8.5690529346466
   卷柄重复使用:5.3703031539917

因此,重复使用相同的句柄实际上会在多次连接到同一服务器时提供显着的性能提升。我尝试连接到不同的服务器:

$url_arr = array(
    'http://www.google.com/',
    'http://www.bing.com/',
    'http://www.yahoo.com/',
    'http://www.slashdot.org/',
    'http://www.stackoverflow.com/',
    'http://github.com/',
    'http://www.harvard.edu/',
    'http://www.gamefaqs.com/',
    'http://www.mangaupdates.com/',
    'http://www.cnn.com/'
);
ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
foreach ($url_arr as $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_exec($ch);
    curl_close($ch);
}
$end_time = microtime(true);
ob_end_clean();
echo 'Curl without handle reuse: ' . ($end_time - $start_time) . '<br>';

ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
$ch = curl_init();
foreach ($url_arr as $url) {
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_exec($ch);
}
curl_close($ch);
$end_time = microtime(true);
ob_end_clean();
echo 'Curl with handle reuse: ' . ($end_time - $start_time) . '<br>';

得到以下结果:

  

没有手柄重复使用的卷曲:3.7672290802002
  卷柄重复使用:3.0146431922913

性能仍有相当大的提升。

答案 1 :(得分:16)

这取决于网址是否在同一台服务器上。如果是,则对同一服务器的并发请求将重用该连接。见CURLOPT_FORBID_REUSE。

如果网址有时位于同一服务器上,则需要对网址进行排序,因为默认连接缓存限制为十个或二十个连接。

如果它们位于不同的服务器上,则使用相同的句柄没有速度优势。

使用curl_multi_exec,您可以同时连接到不同的服务器(并行)。即使这样,你也需要一些排队才能不使用数千个同时连接。

答案 2 :(得分:7)

我有类似的情况,我将数据发布到服务器。它被分成大约100行的请求,因此它产生了很多请求。在基准测试中,我比较了12.614行的两种方法(需要127个请求)加上认证和另一个内务处理请求(总共129个请求)。

请求通过网络传输到同一国家/地区的服务器,而不是现场。它们受到TLS 1.2的保护(握手也会造成损失,但鉴于HTTPS越来越成为默认选择,这甚至可能使它与您的场景更相似)。

重复使用cURL: $curlHandle一次curl_init()一次CURLOPT_URL,然后仅使用CURLOPT_POSTFIELDSRun 1: ~42.92s Run 3: ~41.52s Run 4: ~53.17s Run 5: ~53.93s Run 6: ~55.51s Run 11: ~53.59s Run 12: ~53.76s Avg: 50,63s / Std.Dev: 5,8s TCP-Conversations / SSL Handshakes: 5 (Wireshark) 进行修改

curl_init

没有cURL重用: 每个请求一个Run 2: ~57.67s Run 7: ~62.13s Run 8: ~71.59s Run 9: ~70.70s Run 10: ~59.12s Avg: 64,24s / Std. Dev: 6,5s TCP-Conversations / SSL Handshakes: 129 (Wireshark)

Lauren

它不是最大的数据集,但可以说所有“重用”运行都比所有“init”运行都快。平均时间差异大约为14秒。

答案 3 :(得分:2)

这取决于您将要提出多少请求 - 关闭&amp;重新开放每个都是可以忽略不计的,但是当做一千个?可能是几秒钟或更长时间。

我相信curl_multi_init是最快的方法。

整个事情取决于你需要做多少次请求。

答案 4 :(得分:1)

检查一下


try {
    $pool = new HttpRequestPool(
        new HttpRequest($q1),
        new HttpRequest($qn)
    );
    $pool->send();

    foreach($pool as $request) {

      $out[] = $request->getResponseBody();

    }
} catch (HttpException $e) {
    echo $e;
}


答案 5 :(得分:0)

虽然这个问题回答正确,但我想添加一个警告,不要将 curl 重用于 POST 或 PUT 请求,因为重置并不总是完全完成。

我刚刚遇到以下问题,导致我的数据库中的数据损坏。 :-(

由于某些记录中的一些损坏的 ascii 代码,请求帖子仍然是空的,我的脚本没有检查:-((我当然会解决这个问题) curl 似乎有来自上一个记录的请求帖子,然后将其传递了出去。没有返回错误。

如果为每个请求初始化 curl 就不会发生这种情况。在这种情况下,不会有任何可用的预加载数据,因此服务器会以空错误响应。

所以我的建议是,安全快速更好:总是使用 curl 实例,除了获取外部数据 em>.

更新: 我刚刚发现我没有使用 php 函数 STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'compressor.finders.CompressorFinder', 'sass_processor.finders.CssFinder', ) 。根据将重置一切的手册。现在我更喜欢使用 curl_reset()curl_close() ;-)

希望我解释的够清楚,有不清楚的请追问! 问候