PHP的echo
http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2011/1216/9503.html
 
作为一个行走江湖多年的老中医,今天受命去解决一例前端页面展现缓慢的问题。问题页的情况如下:
 
  apache + php
 
  使用smarty模板输出内容
 
  页面最终输出内容较大,80k+
 
  页面执行时间在500ms以上
 
  祭出法宝xhprof对问题页面做了细致检查,发现页面的瓶颈竟然是模板(编译后的)中的一个echo语句,这个echo语句输出的字符串比较大,大概是50k+字节,花费时间为400多毫秒,占整个页面执行时间的80%。这样的echo输出在站点首页中其实是很常见的事情,没有数据库操作,按道理执行时间不应该这么长。
 
  于是猛力使用搜索技能,最终在php手册的echo部分找到了一些蛛丝马迹,早在2003年就有前辈认为通过echo输出大字符串到客户端会引起服务器的性能问题,据我测试,在这个场景下使用print其实也是一样的慢。建议的解决办法是把字符串切割成更小的字符串输出,展现速度会有提升,输出函数如下:
 
  <?php
  function echobig($string, $bufferSize = 8192) {
 
  $splitString = str_split($string, $bufferSize);
 
  foreach($splitString as $chunk)
 
  echo $chunk;
 
  }
 
  ?>
 
  但是上面的处方不太对症,整个echobig的输出时间仍然在400毫秒左右,没有太大改善。
 
  考虑到是输出大量内容到客户端比较慢,于是检查了apache的配置,原来还没打开deflate进行压缩,遂启用之。再次使用xhprof进行检查,这条echo的输出时间降低到5ms左右。
 
  400ms到5ms,一个配置问题会产生80倍的差距,还真是省老钱了。这个故事告诉我们,压缩输出真的很重要。
 
相关:
加速你的echo
http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2011/1127/9361.html
你也许注意到过, 在PHP中使用ECHO输出大段字符串的时候, 执行时间会明显的长, 也就会有朋友认为PHP的ECHO性能很差.
 
  我在之前的文章中, 已经解释过了原因, 也希望能纠正”PHP的ECHO性能差”的这个误会.
 
  然而之前的文章, 也仅仅是给出了原因, 并没有介绍如何避免这个问题, 在今天公司内的某个产品线(Apache with PHP)发现了一个问题, 有用户在短时间内大量发起下载请求, 导致http连接数和数据库连接数剧增,
 
  而数据库连接数剧增的原因是因为数据库的连接是单列模式, 一直到请求处理结束, 才会释放数据库链接. 这样就有了一个问题, 如果请求处理时间过长, 就会造成大量的数据库链接存在.
 
  而这个用户的网速很慢, 这也就意味着, ECHO的”性能”很差~, 下载时间很长~. 如下图所示:
 
  
 
 
 
 
  ECHO执行示意图
 
  这也就引出了今天我要谈的这个问题, 如何让ECHO变快, 让PHP的请求处理过程, 尽快结束…
 
  我们知道, 之所以ECHO慢, 是在等待”写数据”成功返回, 那么一个比较简单的办法, 就是打开输出缓存,
 
  编辑php.ini
 
  output_buffering = 4096 //bytes
 
  当然, 你也可以在脚本中, 显示的调用ob_start():
 
  ob_start();echo $huge_string;//其他的逻辑.ob_end_flush();
 
  这里, 有一个要注意的地方, ob_start将会开辟一块4096大小的buffer, 所以, 如果huge_string大于4096, 将不会起到加速的作用.
 
  现在, 我们的ECHO就会”立即”执行成功, 返回. 因为数据暂时写到了我们的输出缓存当中. 如果buffer足够大, 那么内容会等到脚本的最后, 才一次性发送给客户端(严格来说, 是发送给WebServer).
 
  但这样并不能解决我们今天遇到的这个问题, 因为这些数据到最后, 还是需要PHP去把它们发送给客户端(此时不考虑WebServer的Output buffer), 这个过程不结束, 请求不会关闭, PHP也不会执行DB的析构函数~
 
  那么, 既然做梦, 那就再做大点, 我们可以使用Apache的输出缓存. 也就是改变成如下的执行流程:
 
  
 
 
 
 
  加速ECHO示意图
 
  假设, 我们的PHP要输出100K的数据, 那么, 我们Apache的的输出缓存就必须大于100K, 否则当Apache的输出缓存满了以后, 就会真正的发送给客户端, 而这个过程中, 当时执行的ECHO就会阻塞等待.
 
  那么, 如何修改Apache的输出缓存呢? 我们可以在apache的配置文件中, 使用SendBufferSize配置指令:
 
  SendBufferSize 4096 //注意是byte
 
  具体的SendBufferSize的说明, 参看http://httpd.apache.org/docs/2.0/en/mod/mpm_common.html#sendbuffersize
 
  注: 其他的Webserver with php-cgi的模式, 请翻阅相关Webserver的手册, 寻找类似配置.
 
  现在, PHP的ECHO, 将直接把内容交给Apache, PHP在执行完成后, 不再等待内容发送给客户端完成, 而直接退出. 而内容会在PHP处理完成以后, 由Apache发送给客户端. 从而加速了ECHO的执行效率.
 
  废话一句: printf, print, file_put_contents(“php://output”)…等等, 和ECHO都是一样的.
 
  最后要说明, 这样做, 只是把原来ECHO的等待时间, 转移给了Apache, 并没有真正的减少客户端获取到内容的时间. 它只是加速了PHP的处理过程, 提前了PHP的退出时机, 从而能减少PHP对资源的占用时间, 间接增加资源的占用率.