普通请求curl_normal.php使用时间:0.830scurl_multi并发curl_multi.php$ch){curl_multi_add_handle($mh,$ch);//2添加句柄}$ac略微=空;//需要优化的点://当$active>0时,执行curl_multi_exec($mh,$active)但是整个批处理句柄没有执行完,系统会继续执行curl_multi_exec()函数do{echo"跑步”;curl_multi_exec($mh,$active);//3执行批句柄}while($active>0);//4foreach($chArras$k=>$ch){$result[$k]=curl_multi_getcontent($ch);//5获取句柄的返回值curl_multi_remove_handle($mh,$ch);//6移除$mh中的句柄}curl_multi_close($mh);//7关闭所有句柄//print_r($result);$end_time=微时间(真);echosprintf("usetime:%.3fs",$end_time-$srart_time);?>usetime:0.259scurl_multi并发优化:上例中的curl_multi_select当$active>0时,执行curl_multi_exec($mh,$active)而整个批处理句柄没有执行完全,系统会一直执行curl_multi_exec()函数。这很容易导致CPU使用率过高。改变的方法是使用curl函数库中的curl_multi_select()函数,其函数原型如下:intcurl_multi_select(resource$mh[,float$timeout=1.0])阻塞直到有活动连接cURL批量连接。成功时返回描述符集中的描述符数。失败时,如果select失败则返回-1,否则返回超时(来自底层select系统调用)。我们使用我们的curl_multi_select()函数来达到在没有需要读取的程序时阻塞的目的。以下是优化部分的代码:curl_multi_select.php$active=null;做{回声“运行”;$mrc=curl_multi_exec($mh,$active);//3执行批句柄}while($mrc==CURLM_CALL_MULTI_PERFORM);//4//本次循环第一次处理$mh批处理中的$ch句柄,将$mh批处理的执行状态写入$active。当status值等于CURLM_CALL_MULTI_PERFORM时,表示数据还在写入或读取中,执行循环,当$ch句柄的数据第一次成功写入或读取时,status值变为CURLM_OK,跳转跳出这个循环,进入下面的大循环。//$active为真,即$mh批处理中还有一个$ch句柄待处理,$mrc==CURLM_OK,即最后一次对$ch句柄的读写已经完成。while($active&&$mrc==CURLM_OK){if(curl_multi_select($mh)!=-1){//$mh批处理中还有一个可执行的$ch句柄,curl_multi_select($mh)!=-1程序退出阻塞状态。do{$mrc=curl_multi_exec($mh,$active);//继续执行需要处理的$ch句柄。}while($mrc==CURLM_CALL_MULTI_PERFORM);}}这样执行的好处是$mh批处理中的$ch句柄在读取或写入数据($mrc==CURLM_OK)后会进入curl_multi_select($mh)阻塞阶段,而不是在执行过程中不断执行curl_multi_exec整个$mh批次,白白浪费CPU资源。运行结果:使用时间:0.325s耗时变化不大,但性能有所提升。curl_multi并发优化:上面的rolling例子还是有优化空间的。优化方法是在某个URL请求完成后尽快处理,边处理边等待其他URL返回,而不是等到最慢的接口返回后,才开始处理等工作,避免占用CPU闲散和浪费。只贴出修改部分:curl_multi_rolling.php$active=null;做{while(($mrc=curl_multi_exec($mh,$active))==CURLM_CALL_MULTI_PERFORM);如果($mrc!=CURLM_OK){中断;}//一个请求刚刚完成——找出哪一个while($done=curl_multi_info_read($mh)){//获取请求返回的信息和内容$info=curl_getinfo($done['handle']);$error=curl_error($done['handle']);$result[]=curl_multi_getcontent($done['handle']);//$responses[$map[(string)$done['handle']]]=compact('info','error','results');//删除刚刚完成的curl句柄curl_multi_remove_handle($mh,$done['handle']);curl_close($done['handle']);}//数据输入/输出块;错误处理由curl_multi_exec完成if($active>0){curl_multi_select($mh);}}while($active);usetime:0.267s参考1、PHP模拟发送POST请求之五curl基本使用和多线程序优化http://www.cnblogs.com/zhenbi...2、RollingcURL:PHP并发最佳实践https://www.oschina.net/quest...3.curl_multi_select解决curl_multi网页假死问题http://www.webkaka.com/tutori...
