Основная идея была в сравнении скорости чтения/скачивания файлов через многопоточный 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) . ' сек.';