速度优化HHVM篇

确定的第一个速度优化的项目:

从PHP5.4切换到HHVM^why-not-php7,为什么?因为这个方案效果是已知的好,省CPU,明显提升速度!实践起来简单(不用改代码就能有提升),并且在公司内部也已经经过多年使用,兼容性会有但问题不大。

HHVM是什么,介绍的文章太多了,这里就不叙述了,参见多益大神^duoyi文章,另外厂内HHVM维护者志广的博客 也可以看看,虽然不怎么更新了。

HHVM的使用情况

HHVM在百度内部的情况使用这篇博客有介绍,
最重要的几个产品线在13年末14年初基本都实现了PHP到HHVM的切换工作,并且有大量的产品线正在使用。好奇我们为啥当时没用,建议以后都默认使用HHVM除了PHP7之外都不要考虑Zend-PHP了。

HHVM能带来什么提升

一个词形容就是“节省”,省时间(php执行速度加快)、省内存、省CPU。

这里罗列下基础调研数据

外部情况

  1. Wikimedia:维基百科部署了 HHVM 后,CPU 的负载从50%降到了10%,用户提交编辑时的平均响应时间减少到原来的一半,页面的平均加载时间从原来的1.3秒降到了0.9秒。
  2. Etsy: Etsy 的工程师对比了HHVM 和 PHP5.4 的性能,发现 HHVM 每秒可以处理280个服务器请求,而对于 PHP5.4,如果每秒的请求数超过了190次,服务器的响应时间就会急剧增加。

内部情况

  1. 检索模板渲染用HHVM处理,处理时间减少一半(对比PHP-FPM+eAccelerator),资源消耗上PHP-CGI用3.2G,HHVM用1G
  2. 广告模板系统渲染时间下降60%,整体响应时间下降50%

我们自己的实践数据

  1. 栋哥在优化后端接口性能的时候发现,发现始终有20ms不知道哪占的,最后发现是框架占的,使用HHVM之后,这20ms被压缩到1ms,效果明显

HHVM的问题

  1. 我所知道的最大的问题是有内存泄露问题,流量大的情况下,需要定期重启,不然HHVM自己重启,流量又没切走,会造成拒绝的问题,这个虽然在不断修复,不过今年在搜索还是有
  2. 插件的问题,插件不兼容,需要重新开放,不过常用的插件都有HHVM的版本了,我们没有这个问题
  3. 不兼容的问题,HHVM和PHP还不是100%兼容,虽然主流的PHP项目都对HHVM做了兼容,但是那也是针对官方HHVM而言,公司内的HHVM可能还有问题

HHVM和PHP的DIFF问题

hhvm传超过一个参数时精度丢失的问题

1
2
3
4
5
6
7
8
9
10
<?php
$a1 = array('rate'=>4/3);
$a2 = array('col'=>4,'rate'=>4/3);

function getit($r) {
echo ( 4 * (6+17) - 17 ) * $r['rate'] ;
echo "\n";
}
getit($a1);
getit($a2);

HHVM输出

100
99.999999997

PHP输出

100
100

hhvm htmlspecialchars对传参的限制问题

1
2
3
4
<?php
$string = array('str'=>'aaa');
$str = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
echo ( $str );

HHVM输出

Array

PHP无输出

mb库默认编码问题

1
2
3
4
5
6
7
8
9
10
<?php
$search = "日";
$subject = "21日";
$replace = "";

#mb_regex_encoding('UTF-8');
#mb_internal_encoding("UTF-8");
$parts = mb_split(preg_quote($search), $subject);
$subject = implode($replace, $parts);
echo $subject."\n";

HHVM输出

21日

PHP输出

21

preg_match和魔术函数共用导致的死循环问题

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class MM{
function getVar(){
return $this;
}
function __get($name){
return NULL;
}
};

$t = new MM();
echo preg_match_all("/./", 'some', $t->getVar()->value);
echo "\n";

rawurlencode 转义~线的问题

HHVM支持的是PHP5.4,所以使用rawurlencode时不将~转义为%7E保持原有的~(PHP5.3以上都是如此支持),我们公司默认使用的是php 5.2.17,5.2.17将~转义为%7E,为了保持一致公司的HHVM Patch掉了这个,所以和我们用PHP5.4的又不兼容了。。。