Основная идея была в сравнении скорости чтения/скачивания файлов через многопоточный cUrl (curl_multi_init) с однопаточными cUrl и copy / file_get_contents
Сравнение способов скачивания файлов на php
09.09.2019
Чистый тест сделать было сложно, т.к. из-за нагрузки сети повторение одного и того же теста давало разное время.
Но в целом картина такая: 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) . ' сек.';