本人翻译的一篇文章,首发于伯乐在线。
【补充信息】HipHop for PHP是一系列PHP脚本语言的程式码转换器的集合,它包含HPHPc、HPHPi、HPHPd以及HHVM,这四个脚本引擎各有所不同,但是他们共用相同的执行时期(Runtime)及工具集(Toolset)。HipHop是由Facebook所建立,他们用它来节省服务器的资源。HipHop 由 C++ 和 C 语言所编写,发布时代码量已高达60万行,它以自由软件发布,采用PHP许可证3.01版。(摘自维基百科)
2013年11月4日开始,HHVM团队进行了为期三周的“性能与兼容性封闭开发”。此次封闭开发于11月22日正式结束。总体来看,封闭开发获得了成功。衡量成功的三要素如下:
- 1. 对21款开源框架做测试后,我们是否达到了平均单测通过率为99%的目标。
- 2. 我们是否获得了15%的性能提升收益。
- 3. 团队成员是否能坚持三周不刮胡子。
HHVM团队在封闭开发结束后的聚会上
兼容性
封闭开发伊始,团队认识到,仅仅拥有优异的性能还不足以使HHVM成为可靠的、可供大范围使用的PHP运行环境。它必须能运行实际的、现成的PHP代码。所以,我们将这一点视为头号工作任务(它将持续进行至2014年)。首先,我们在GitHub上通过“星标”数来寻找那些正被大多数人使用的热门PHP项目,并确保这些项目的单元测试可顺利运行于HHVM之上。
兼容性成果
先来看一些数字。下图是超过125次文件修改之后,取得的兼容性方面的部分成果。
封闭开发后的单元测试兼容性成果
框架 |
封闭开发前 % |
封闭开发后 % |
Delta % |
均值 |
89.96 |
99.58 |
9.62 |
assetic |
77.94 |
100 |
22.06 |
codeigniter |
88.24 |
100 |
11.76 |
composer |
98.79 |
98.89 |
0.10 |
doctrine2 |
92.4 |
99.95 |
7.55 |
drupal |
98.61 |
100 |
1.39 |
facebookphpsdk |
100 |
100 |
0 |
idiorm |
100 |
100 |
0 |
joomla |
94.09 |
97.92 |
3.83 |
laravel |
99.23 |
100 |
0.77 |
magento2 |
97.66 |
98.74 |
1.08 |
mediawiki |
98.91 |
99.98 |
1.07 |
paris |
100 |
100 |
0 |
pear |
Fatal |
92.66 |
92.66 |
phpbb3 |
94.58 |
99.5 |
4.92 |
phpmyadmin |
96.15 |
94.16 |
-1.99 |
phpunit |
96.29 |
97.03 |
0.74 |
slim |
100 |
100 |
0 |
symfony |
86.53 |
96.67 |
10.14 |
twig |
99.23 |
100 |
0.77 |
yii |
78.08 |
99.11 |
21.03 |
zf2 |
92.4 |
95.49 |
3.09 |
正如图表及delta列所示,我们在努力下,近乎完全的成功改进了单元测试的兼容性。
- 1. 团队使可在HHVM上100%跑通单元测试的开源项目数量翻了一番(从4个到8个),并且有另外4个项目的通过率在99%以上。
- 2. Assetic,Symfony,Yii和CodeIngiter四个项目的兼容性提升了10%以上。
- 3. 全部21款框架的单元测试通过率均在90%以上。
大部分文件更改已包含在HHVM 2.3版本中,以下是一些对单元测试结果有显著影响的关键改进:
- 1. 不要使数组成为Traversable接口的实例
- 2. 国际化支持
- 3. PDO::sqliteCreateFunction()方法实现
- 4. 开始支持真实的php.ini文件。
无论怎样,我相信你对我们的成果还有一些好奇:
1. 为什么phpMyAdmin的兼容性下降了呢? 这并不是“由于我们改动代码造成单元测试失败”这个维度上的下降。这实际上可能是我们的测试框架脚本在最初未能正确的载入全部测试用例造成的。我们修复了这个问题。尽管如此,我们正在调查这个下降的根本原因,以防我们破坏了某些东西。
2. 为什么在11月24日左右有一个垂直跌落。我们提交了一处修改,本想将测试框架推向完美,但却在运行时遭遇段异常。这个错误很快被修复了。
测试框架
正如前文所述,用来提升单测兼容性的21款开源项目是根据流行程度挑选出来的。不过,挑选还基于他们是否使用PHPUnit以及他们在我们的框架上运行的如何。举例来说,这些项目的单元测试数量,Symfony和ZF2各有超过一万个测试用例,我们需要一个能以较快方式运行所有项目单元测试用例的测试框架。因此,我们开发了一个可并行下载、安装和运行所有单元测试的脚本。这个脚本仍然在完善中,但它已帮助我们在30分钟到一个小时内运行五万个以上的单元测试用例并且可连续运行很多个小时。这个脚本位于:HHVM Github repository
可能你已经注意到,你所喜爱的开源项目并未出现在上面的名单中。这是由于以下几个原因造成的:首先,我们不可能在3周时间内覆盖所有的开源项目。其次,虽然诸如CakePHP这样的开源项目很重要,我们也计划将它们加入测试框架,但由于一些安装和配置方面的的问题(例如,要求数据库)使我们无法在短时间内完成这一工作。
最后,正如我们在封闭开发前发表的博文中所述,HHVM团队创建了很多“便利贴”来指引项目。便利贴显示两项内容:与便利贴上所述任务相关的失败测试用例数及已开发天数。所以,我们通常按从左上角到右下角的顺序工作,以使我们取得最大回报。
假设与警告
指出与上述统计值相关的假设及警告是很有必要的。
1. 整体单元测试通过百分比(98.5%)是简单的,未加权平均数(即,所有百分比相加除以21).因此,类似Paris这种只含有50个单元测试用例的项目和类似Symfony这种包含一万单元测试用例的项目拥有相同的权重。如果我们加权 (其中 Symfony 和 Zf2 会得到比Pair和 Idiorm更多的权重)计算这些百分比,整体通过百分比会有极小的跌幅 (绩效跌幅的原因是因为在所有开源资源项目的通过百分比方差小)
2. 某些在HHVM上运行失败的测试用例,同样无法在PHP 5.5.x环境中运行。我们称其为“小丑”同时在我们的测试框架中忽略他们。
3. 某些单元测试会导致我们的测试框架脚本出错(例如,死锁)。我们屏蔽了这些测试用例并把它们归为失败用例。
已提交的相关项目的Pull Requests
为了能成功运行所有开源项目的单元测试,我们对它们的代码做了多次修改。例如,一些修改是为了支持我们的并行测试框架。在其他一些情况下,单元测试用例中实际bug。令人惊喜的是,就在我们封闭期间,那些项目维护者就审查了代码,并在大多数情况下接受了我们的pull requests。以下是一些pull request的实例:
框架 & pull request链接 |
描述 |
Pear |
Support different style error messages |
Doctrine2 |
Support the HHVM requirement of implementing methods of interfaces |
Joomla |
Support the definition usort() on equal values |
phpbb3 |
Support our parallel testing framework |
Slim |
Support a string check in hash_hmac |
Twig |
Better use of strings instead of large integers in certain parsing scenarios |
PHPUnit |
Support HHVM in PHP_BINARY checks |
Symfony |
Support HHVM as one of the possible PHP executables |
与Travis集成
HHVM 2.3版本公告中提到了与Travis CI集成。现在,我们开始持续的通过开源项目的单元测试,一些开源项目已把HHVM加入它们的Travis CI构建(棒极了)。以下是把HHVM加入CI构建的开源框架:
- PHPUnit
- Yii
- Doctrine 2
- Laravel
感谢以上项目能如此之快的支持我们。同样,我们对其他项目也提交了很多类似的优秀pull request
性能
性能团队的封闭开发目标是提升15%,最终获得了16%的提升。
封闭开发后的性能成果
这意味着其他php代码也会有很大的提升空间。性能方面的收获来自于大量的小改进和少量的大改动。以下是一些重大的修改:
1. 为特殊的函数调用方式生成代码。HHVM已经为普通函数和方法调用生成优质的代码,所以一些不常见的调用方式已经出现在我们的性能配置数据中。两个最大的改动点是 call_user_func()和static::方法调用已被解释器处理。现在HHVM可为每种调用类型生成优化过的机器代码。
2. 优化HHVM二进制的布局。HHVM是一套庞大的程序:编译后的HHVM时钟C++代码略低于100MB。当最频繁调用的代码占用空间少而不是分散在地址空间中时,CPU缓存才工作的更好。所以,我们把最常用函数集合在一起作为二进制的一部分。为了提升页表缓存性能,我们使用一个巨大的页来映射这个部分。
3. 使用解释器检测热点函数。HHVM解释最初的几个请求,以免浪费时间和空间去编译启动代码。我们为解释器加入了寻找热点函数并将其编译为转换缓存一部分的功能。就像最后一个优化,这一项优化针对动态生成的代码,改进了代码位置。
4. 升级了我们的正则表达式库。新版PCRE加入了针对正则表达式的JIT编译器,这为HHVM带来了一个令人兴奋的性能提升。
个人卫生
我确信你在想:”所有的这些收益和统计很很好,但是胡子呢?! ? “没错,你还记得我们再封闭开发前的博文:”剃须即失败”。我很高兴的宣告,我们在封闭开发中同样成功地维持一个最低限度的面部卫生。这里有一些图片来证明这一点。
HHVM团队人手一把剃须刀,准备对面部做清理
我们达到目标了么?
还记得我们在前文提到的成功三要素么?
- 1. 对21款开源框架做测试后,我们是否达到了平均单测通过率为99%的目标。
- 2. 我们是否获得了15%的性能提升收益。
- 3. 团队成员是否能坚持三周不刮胡子。
答案是:
- 1. 接近完成
- 2. 完美完成
- 3. 完成。
未来(2014)
性能改进将永远是HHVM团队关注的核心。兼容性优先级将为1A。我们非常关心开源和PHP社区。我们将在2014年竭尽全力让HHVM在性能与兼容性两方面成为一流,让越来越多得开源项目及框架的单元测试(被)通过。大规模的真实php代码测试。请继续关注我们的进展和计划。最后,祝大家新年快乐。
原文链接: HHVM 翻译: 伯乐在线 - TechZi 译文链接: http://blog.jobbole.com/58097/ |