【问题标题】:CURL slower than fread while streaming file? how to speed up CURL流式传输文件时,CURL 比 fread 慢?如何加快 CURL
【发布时间】:2013-10-17 05:25:56
【问题描述】:

我正在尝试制作一个脚本来下载文件的一部分。 只需使用 CURL 和 fread 进行测试,我意识到流式处理过程中的 CURL 比 fread 慢。 为什么?如何加快 curl 流式传输文件? 我不喜欢使用 fread , fopen 因为我在流式处理过程中需要有限的时间。

这是我的示例代码。

$start = microtime(true);
$f = fopen('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg','r');
$response = fread($f, 3); echo $response.'<br>';
$response = fread($f, 3); echo $response.'<br>';
$response = fread($f, 3); echo $response.'<br>';
$response = fread($f, 3); echo $response.'<br>';
$response = fread($f, 3); echo $response.'<br>';

$stop = round(microtime(true) - $start, 5);
echo "{$stop}s";
exit();

fread / fopen 仅需 1.1s

$start = microtime(true);
$curl = curl_init('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg');
curl_setopt($curl, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($curl, CURLOPT_RANGE, "0-2");
$response = curl_exec($curl);echo $response.'<br>';

curl_setopt($curl, CURLOPT_RANGE, "3-5");
$response = curl_exec($curl);echo $response.'<br>';

curl_setopt($curl, CURLOPT_RANGE, "6-8");
$response = curl_exec($curl);echo $response.'<br>';

curl_setopt($curl, CURLOPT_RANGE, "9-11");
$response = curl_exec($curl);echo $response.'<br>';

curl_setopt($curl, CURLOPT_RANGE, "12-14");
$response = curl_exec($curl);echo $response.'<br>';
curl_close($curl);

$stop = round(microtime(true) - $start, 5);
echo "{$stop}s";
exit();

curl 大约需要 2.5 秒。 如果我采取更多步骤来下载文件的更多部分。 curl 会更慢。

为什么 curl 比较慢?什么解决方案?

【问题讨论】:

  • 我在下面更新了我的答案,您似乎在比较单个请求与许多不公平的部分范围请求

标签: php curl stream fread


【解决方案1】:

它总是较慢,因为您添加了额外的 HTTP 调用往返。每个 curl_exec 都是一个 HTTP 请求。

【讨论】:

    【解决方案2】:

    您的问题是关于有许多部分请求或关于同一请求的增量缓冲读取。

    fopen/fread 实现触发单个 HTTP 请求并逐段读取多次。

    另一方面,curl 实现会触发许多 HTTP 请求,每个请求一个 (see partial range requests)。 所以我们在比较苹果和橘子

    公平地说,fopen/fread 看起来像这样

    $start = microtime(true);
    $f = fopen('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg','r');
    $response = fread($f, 3); echo $response.'<br>';
    fclose($f)
    $f = fopen('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg','r');
    fseek($f, 3);
    $response = fread($f, 3); echo $response.'<br>';
    fclose($f)
    $f = fopen('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg','r');
    fseek($f, 6);
    $response = fread($f, 3); echo $response.'<br>';
    fclose($f)
    $f = fopen('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg','r');
    fseek($f, 9);
    $response = fread($f, 3); echo $response.'<br>';
    fclose($f)
    $f = fopen('http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg','r');
    fseek($f, 12);
    $response = fread($f, 3); echo $response.'<br>';
    fclose($f)
    $stop = round(microtime(true) - $start, 5);
    echo "{$stop}s";
    exit();
    

    更新:我已经重写了我的答案

    【讨论】:

      【解决方案3】:

      您可以使用curl_getinfo 来查看需要多长时间。

      缓慢可能是由于 curl 库的 DNS 查找。 您是否尝试过使用 IP 地址而不是域作为请求 url?

      编辑: 或者,您可以将 CURLOPT_DNS_USE_GLOBAL_CACHE 设置为 true 并将 CURLOPT_DNS_CACHE_TIMEOUT 设置为更长的值(例如 1 小时) - 默认为 2 分钟。

      源:http://php.net/manual/en/function.curl-setopt.php

      【讨论】:

      • 不,dns无所谓,这个东西是fopen打开文件一次,然后curl,我认为它打开文件多次得到文件的一小部分
      【解决方案4】:

      尝试在第一个curl_exec之前设置Keep-Alive标头,例如300秒这样的方式:

      $headers = array("Keep-Alive: 300");
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      

      【讨论】:

      • 我没有更好。我不认为这是因为保持连接。
      【解决方案5】:

      您可以尝试以下解决方案:

      curl_setopt($curl, CURLOPT_RANGE, "0-2, 3-5, 6-8, 9-11, 12-14");
      $response = curl_exec($curl);echo $response.'<br>';
      curl_close($curl);
      $stop = round(microtime(true) - $start, 5);
      echo "{$stop}s";
      exit();
      

      【讨论】:

        猜你喜欢
        • 2013-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 2018-06-09
        • 2011-01-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多