curl_init()和curl_multi_init()多线程的速度比较
來源:http://www.webkaka.com/tutorial/php/2013/102843/
-  php中curl_init()的作用很大,尤其是在抓取網(wǎng)頁內(nèi)容或文件信息的時候,例如之前文章curl獲得header檢測GZip壓縮的源代碼就介紹到curl_init()的強(qiáng)大。 curl_init()處理事物是單線程模式,如果需要對事務(wù)處理走多線程模式,那么php里提供了一個函數(shù)curl_multi_init()給我們,這就是多線程模式處理事務(wù)的函數(shù)。 curl_init()與curl_multi_init()的速度比較 curl_multi_init()多線程能提高網(wǎng)頁的處理速度嗎?今天我通過實(shí)驗(yàn)來驗(yàn)證一下這個問題。 今天我的測試很簡單,那就是要抓取www.webkaka.com網(wǎng)頁的內(nèi)容,要連續(xù)抓5次,分別用curl_init()和curl_multi_init()函數(shù)來完成,記錄兩者的耗時,比較得出結(jié)論。 首先,用curl_init()單線程連續(xù)抓5次www.webkaka.com網(wǎng)頁的內(nèi)容。 程序代碼如下: <?php 
 $mtime = explode(" ", microtime());
 $mtime = $mtime[1].($mtime[0] * 1000);
 $mtime2 = explode(".", $mtime);
 $mtime = $mtime2[0];
 echo $mtime;
 echo "<br>";
 for($i=1; $i<=5; $i++){
 $szUrl = 'http://www.webkaka.com/';
 $curl = curl_init();
 curl_setopt($curl, CURLOPT_URL, $szUrl);
 curl_setopt($curl, CURLOPT_HEADER, 0);
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($curl, CURLOPT_ENCODING, '');
 $data=curl_exec($curl);
 echo $data;
 echo "<br>";
 $mtime_ = explode(" ", microtime());
 $mtime_ = $mtime_[1].($mtime_[0] * 1000);
 $mtime2_ = explode(".", $mtime_);
 $mtime_ = $mtime2_[0];
 echo $mtime_;
 echo "<br>";
 echo $mtime_ - $mtime;
 }
 ?>然后,用curl_multi_init()多線程連續(xù)抓5次www.webkaka.com網(wǎng)頁的內(nèi)容。 代碼如下: <?php 
 echo date("Y-m-d H:m:s",time());
 echo " ";
 echo floor(microtime()*1000);
 echo "<br>";
 $mtime = explode(" ", microtime());
 $mtime = $mtime[1].($mtime[0] * 1000);
 $mtime2 = explode(".", $mtime);
 $mtime = $mtime2[0];
 echo $mtime;
 echo "<br>";
 $urls = array(
 'http://www.webkaka.com',
 'http://www.webkaka.com',
 'http://www.webkaka.com',
 'http://www.webkaka.com',
 'http://www.webkaka.com');
 print_r(async_get_url($urls)); // [0] => example1, [1] => example2
 echo "<br>";
 echo date("Y-m-d H:m:s",time());
 echo " ";
 echo floor(microtime()*1000);
 echo "<br>";
 $mtime_ = explode(" ", microtime());
 $mtime_ = $mtime_[1].($mtime_[0] * 1000);
 $mtime2_ = explode(".", $mtime_);
 $mtime_ = $mtime2_[0];
 echo $mtime_;
 echo "<br>";
 echo $mtime_ - $mtime;
 
 function async_get_url($url_array, $wait_usec = 0)
 {
 ??? if (!is_array($url_array))
 ??????? return false;
 ??? $wait_usec = intval($wait_usec);
 ??? $data??? = array();
 ??? $handle? = array();
 ??? $running = 0;
 ??? $mh = curl_multi_init(); // multi curl handler
 ??? $i = 0;
 ??? foreach($url_array as $url) {
 ??????? $ch = curl_init();
 ??????? curl_setopt($ch, CURLOPT_URL, $url);
 ??????? curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return don't print
 ??????? curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 ??????? curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
 ??????? curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect
 ??????? curl_setopt($ch, CURLOPT_MAXREDIRS, 7);
 ??????? curl_multi_add_handle($mh, $ch); // 把 curl resource 放進(jìn) multi curl handler 里
 ??????? $handle[$i++] = $ch;
 ??? }
 ??? /* 執(zhí)行 */
 ??? do {
 ??????? curl_multi_exec($mh, $running);
 ??????? if ($wait_usec > 0) /* 每個 connect 要間隔多久 */
 ??????????? usleep($wait_usec); // 250000 = 0.25 sec
 ??? } while ($running > 0);
 ??? /* 讀取資料 */
 ??? foreach($handle as $i => $ch) {
 ??????? $content? = curl_multi_getcontent($ch);
 ??????? $data[$i] = (curl_errno($ch) == 0) ? $content : false;
 ??? }
 ??? /* 移除 handle*/
 ??? foreach($handle as $ch) {
 ??????? curl_multi_remove_handle($mh, $ch);
 ??? }
 ??? curl_multi_close($mh);
 ??? return $data;
 }
 ?>為了避免隨機(jī)性,我分別測了5次(用CTRL+F5強(qiáng)行刷新的方式),數(shù)據(jù)如下: curl_init(): ? 第一次 第二次 第三次 第四次 第五次 平均 耗時(ms) 3724 3615 2540 1957 2794 2926 curl_multi_init(): ? 第一次 第二次 第三次 第四次 第五次 平均 耗時(ms) 4275 2912 3691 4198 3891 3793 從測試結(jié)果來看,我們發(fā)現(xiàn)兩種方法的耗時差不了太多,只有700多毫秒。很多人原本以為多線程比單線程耗時會短很多,實(shí)際上并不是這樣的,從數(shù)據(jù)來看,多線程反而比單線程耗時更多了一點(diǎn)。不過,對于某些事務(wù)來說,用多線程來處理不一定是為了追求速度,這個是需要注意的。 關(guān)于curl_multi_init() 一般來說,想到要用curl_multi_init()時,目的是要同時請求多個url,而不是一個一個依次請求,否則就要curl_init()了。 不過,在使用curl_multi的時候,你可能遇到cpu消耗過高、網(wǎng)頁假死等現(xiàn)象,可以看看如何解決curl_multi導(dǎo)致網(wǎng)頁假死的問題 使用curl_multi的步驟總結(jié)如下: 第一步:調(diào)用curl_multi_init 
 第二步:循環(huán)調(diào)用curl_multi_add_handle
 這一步需要注意的是,curl_multi_add_handle的第二個參數(shù)是由curl_init而來的子handle。
 第三步:持續(xù)調(diào)用curl_multi_exec
 第四步:根據(jù)需要循環(huán)調(diào)用curl_multi_getcontent獲取結(jié)果
 第五步:調(diào)用curl_multi_remove_handle,并為每個字handle調(diào)用curl_close
 第六步:調(diào)用curl_multi_close各函數(shù)作用解釋: curl_multi_init() 
 初始化一個curl批處理句柄資源。curl_multi_add_handle() 
 向curl批處理會話中添加單獨(dú)的curl句柄資源。curl_multi_add_handle()函數(shù)有兩個參數(shù),第一個參數(shù)表示一個curl批處理句柄資源,第二個參數(shù)表示一個單獨(dú)的curl句柄資源。curl_multi_exec() 
 解析一個curl批處理句柄,curl_multi_exec()函數(shù)有兩個參數(shù),第一個參數(shù)表示一個批處理句柄資源,第二個參數(shù)是一個引用值的參數(shù),表示剩余需要處理的單個的curl句柄資源數(shù)量。curl_multi_remove_handle() 
 移除curl批處理句柄資源中的某個句柄資源,curl_multi_remove_handle()函數(shù)有兩個參數(shù),第一個參數(shù)表示一個curl批處理句柄資源,第二個參數(shù)表示一個單獨(dú)的curl句柄資源。curl_multi_close() 
 關(guān)閉一個批處理句柄資源。curl_multi_getcontent() 
 在設(shè)置了CURLOPT_RETURNTRANSFER的情況下,返回獲取的輸出的文本流。curl_multi_info_read() 
 獲取當(dāng)前解析的curl的相關(guān)傳輸信息。實(shí)例 
 請看本文里async_get_url()的寫法。
-  Tags:?curl_init??curl_multi_init??curl_multi??
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的curl_init()和curl_multi_init()多线程的速度比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: PHP实现多线程抓取网页
- 下一篇: 银行卡营销代码是什么意思
