Сравнение способов скачивания файлов на php

09.09.2019

Основная идея была в сравнении скорости чтения/скачивания файлов через многопоточный cUrl (curl_multi_init) с однопаточными cUrl и copy / file_get_contents

Чистый тест сделать было сложно, т.к. из-за нагрузки сети повторение одного и того же теста давало разное время.

Но в целом картина такая: copy / cUrl (в один поток) скачивали картинки за 12-25 секунд. А cUrl в 10 потоков за 3-5.

Листинг:

 
<?
$start = microtime(true);
$aPhotos = json_decode(file_get_contents('phpshop_foto.json'));

function copy1($from, $to) // 14 - 18
{
  copy($from, $to);
}

function copy2($from, $to) // 16 - 22
{
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $from);
  curl_setopt ($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    $response = curl_exec($ch);
    file_put_contents($to, $response);
  curl_close($ch);
}

function copy3($aIn) // 3 - 4
{
  $aHandels = [];
  $mh = curl_multi_init();  
  foreach($aIn as $aItem)
  {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $aItem->from);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    curl_multi_add_handle($mh, $ch);
    $aHandels[] = $ch;
  }



  do {
    $status = curl_multi_exec($mh, $active);

    if ($active) {
      // Ждем какое-то время для оживления активности
      curl_multi_select($mh);
    }
  } while ($active && $status == CURLM_OK);


  $i = 0;
  foreach($aHandels as $ch)
  {
    file_put_contents($aIn[$i]->to, curl_multi_getcontent($ch));
    curl_multi_remove_handle($mh, $ch);
    $i++;
  }

  curl_multi_close($mh);
}

/*
$i = 0;
foreach($aPhotos[2]->data as $oRow)
{
  $sName = 'https://oddler.ru/'.$oRow->name;
  copy2($sName, __DIR__.'/out/'.basename($sName));
  
  $i++;
  if($i > 100)
  {
    break;
  }
}
*/



$i = 0;
$aTMP = [];
foreach($aPhotos[2]->data as $oRow)
{
  $sName = 'https://oddler.ru/'.$oRow->name;
  $oTMP = new stdClass();
  $oTMP->from = $sName;
  $oTMP->to = __DIR__.'/out/'.basename($sName);
  
  $aTMP[] = $oTMP;
  if (count($aTMP) > 10)
  {
    copy3($aTMP);
    $aTMP = [];
  }

  $i++;
  if($i > 100)
  {
    break;
  }
}


$finish = microtime(true);

$delta = $finish - $start;

echo round($delta, 2) . ' сек.';


Категории: PHP
Яндекс.Метрика