当前位置:首页 > PHP教程 > php高级应用 > 列表

php使用curl_init()和curl_multi_init()多线程的速度比较详解

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-25 14:11:00 浏览: 评论:0 

这篇文章主要介绍了php使用curl_init()和curl_multi_init()多线程的速度比较,结合实例形式详细分析了curl_init()和curl_multi_init()的具体使用方法及相关效率比较,需要的朋友可以参考下。

本文实例讲述了php使用curl_init()和curl_multi_init()多线程的速度比较。分享给大家供大家参考,具体如下:

php中curl_init()的作用很大,尤其是在抓取网页内容或文件信息的时候,例如之前文章《php使用curl获取header检测开启GZip压缩》就介绍到curl_init()的强大。

curl_init()处理事物是单线程模式,如果需要对事务处理走多线程模式,那么php里提供了一个函数curl_multi_init()给我们,这就是多线程模式处理事务的函数。

curl_init()与curl_multi_init()的速度比较

curl_multi_init()多线程能提高网页的处理速度吗?今天我通过实验来验证一下这个问题。

今天我的测试很简单,那就是要抓取www.webkaka.com网页的内容,要连续抓5次,分别用curl_init()和curl_multi_init()函数来完成,记录两者的耗时,比较得出结论。

首先,用curl_init()单线程连续抓5次www.webkaka.com网页的内容。

程序代码如下:

  1. <?php 
  2. $mtime = explode(" ", microtime()); 
  3. $mtime = $mtime[1].($mtime[0] * 1000); 
  4. $mtime2 = explode("."$mtime); 
  5. $mtime = $mtime2[0]; 
  6. echo $mtime
  7. echo "<br>"
  8. for($i=1; $i<=5; $i++){ 
  9. $szUrl = 'http://www.webkaka.com/'
  10. $curl = curl_init(); 
  11. curl_setopt($curl, CURLOPT_URL, $szUrl); 
  12. curl_setopt($curl, CURLOPT_HEADER, 0); 
  13. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
  14. curl_setopt($curl, CURLOPT_ENCODING, ''); 
  15. $data=curl_exec($curl); 
  16. echo $data
  17. echo "<br>"
  18. $mtime_ = explode(" ", microtime()); 
  19. $mtime_ = $mtime_[1].($mtime_[0] * 1000); 
  20. $mtime2_ = explode("."$mtime_); 
  21. $mtime_ = $mtime2_[0]; 
  22. echo $mtime_
  23. echo "<br>"
  24. echo $mtime_ - $mtime
  25. ?> 

然后,用curl_multi_init()多线程连续抓5次www.webkaka.com网页的内容。

代码如下:

  1. <?php 
  2. echo date("Y-m-d H:m:s",time()); 
  3. echo " "
  4. echo floor(microtime()*1000); 
  5. echo "<br>"
  6. $mtime = explode(" ", microtime()); 
  7. $mtime = $mtime[1].($mtime[0] * 1000); 
  8. $mtime2 = explode("."$mtime); 
  9. $mtime = $mtime2[0]; 
  10. echo $mtime
  11. echo "<br>"
  12. $urls = array
  13. 'http://www.webkaka.com'
  14. 'http://www.webkaka.com'
  15. 'http://www.webkaka.com'
  16. 'http://www.webkaka.com'
  17. 'http://www.webkaka.com'); 
  18. print_r(async_get_url($urls)); // [0] => example1, [1] => example2 
  19. echo "<br>"
  20. echo date("Y-m-d H:m:s",time()); 
  21. echo " "
  22. echo floor(microtime()*1000); 
  23. echo "<br>"
  24. $mtime_ = explode(" ", microtime()); 
  25. $mtime_ = $mtime_[1].($mtime_[0] * 1000); 
  26. $mtime2_ = explode("."$mtime_); 
  27. $mtime_ = $mtime2_[0]; 
  28. echo $mtime_
  29. echo "<br>"
  30. echo $mtime_ - $mtime
  31. function async_get_url($url_array$wait_usec = 0) 
  32.   if (!is_array($url_array)) 
  33.     return false; 
  34.   $wait_usec = intval($wait_usec); 
  35.   $data  = array(); 
  36.   $handle = array(); 
  37.   $running = 0; 
  38.   $mh = curl_multi_init(); // multi curl handler 
  39.   $i = 0; 
  40.   foreach($url_array as $url) { 
  41.     $ch = curl_init(); 
  42.     curl_setopt($ch, CURLOPT_URL, $url); 
  43.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return don't print 
  44.     curl_setopt($ch, CURLOPT_TIMEOUT, 30); 
  45.     curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'); 
  46.     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect 
  47.     curl_setopt($ch, CURLOPT_MAXREDIRS, 7); 
  48.     curl_multi_add_handle($mh$ch); // 把 curl resource 放进 multi curl handler 里 
  49.     $handle[$i++] = $ch
  50.   } 
  51.   /* 执行 */ 
  52.   do { 
  53.     curl_multi_exec($mh$running); 
  54.     if ($wait_usec > 0) /* 每个 connect 要间隔多久 */ 
  55.       usleep($wait_usec); // 250000 = 0.25 sec 
  56.   } while ($running > 0); 
  57.   /* 读取资料 */ 
  58.   foreach($handle as $i => $ch) { 
  59.     $content = curl_multi_getcontent($ch); 
  60.     $data[$i] = (curl_errno($ch) == 0) ? $content : false; 
  61.   } 
  62.   /* 移除 handle*/ 
  63.   foreach($handle as $ch) { 
  64.     curl_multi_remove_handle($mh$ch); 
  65.   } 
  66.   curl_multi_close($mh); 
  67.   return $data
  68. ?> 

为了避免随机性,我分别测了5次(用CTRL+F5强行刷新的方式),数据如下:

curl_init():

第一次 第二次 第三次 第四次 第五次 平均

耗时(ms) 3724 3615 2540 1957 2794 2926

curl_multi_init():

第一次 第二次 第三次 第四次 第五次 平均

耗时(ms) 4275 2912 3691 4198 3891 3793

从测试结果来看,我们发现两种方法的耗时差不了太多,只有700多毫秒。很多人原本以为多线程比单线程耗时会短很多,实际上并不是这样的,从数据来看,多线程反而比单线程耗时更多了一点,不过,对于某些事务来说,用多线程来处理不一定是为了追求速度,这个是需要注意的。

关于curl_multi_init()

一般来说,想到要用curl_multi_init()时,目的是要同时请求多个url,而不是一个一个依次请求,否则就要curl_init()了。

不过,在使用curl_multi的时候,你可能遇到cpu消耗过高、网页假死等现象,可以看看《PHP使用curl_multi_select解决curl_multi网页假死问题》

使用curl_multi的步骤总结如下:

第一步:调用curl_multi_init

第二步:循环调用curl_multi_add_handle

这一步需要注意的是,curl_multi_add_handle的第二个参数是由curl_init而来的子handle。

第三步:持续调用curl_multi_exec

第四步:根据需要循环调用curl_multi_getcontent获取结果

第五步:调用curl_multi_remove_handle,并为每个字handle调用curl_close

第六步:调用curl_multi_close

各函数作用解释:

curl_multi_init()

初始化一个curl批处理句柄资源。

curl_multi_add_handle()

向curl批处理会话中添加单独的curl句柄资源。curl_multi_add_handle()函数有两个参数,第一个参数表示一个curl批处理句柄资源,第二个参数表示一个单独的curl句柄资源。

curl_multi_exec()

解析一个curl批处理句柄,curl_multi_exec()函数有两个参数,第一个参数表示一个批处理句柄资源,第二个参数是一个引用值的参数,表示剩余需要处理的单个的curl句柄资源数量。

curl_multi_remove_handle()

移除curl批处理句柄资源中的某个句柄资源,curl_multi_remove_handle()函数有两个参数,第一个参数表示一个curl批处理句柄资源,第二个参数表示一个单独的curl句柄资源。

curl_multi_close()

关闭一个批处理句柄资源。

curl_multi_getcontent()

在设置了CURLOPT_RETURNTRANSFER的情况下,返回获取的输出的文本流。

curl_multi_info_read()

获取当前解析的curl的相关传输信息。

实例

请看本文里async_get_url()的写法。

Tags: curl_init curl_multi_init

分享到: