[翻译] Facebook HHVM 团队封闭开发三周成果展
本人翻译的一篇文章,首发于伯乐在线。
【补充信息】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 |
77.94 |
100 |
22.06 |
|
88.24 |
100 |
11.76 |
|
98.79 |
98.89 |
0.10 |
|
92.4 |
99.95 |
7.55 |
|
98.61 |
100 |
1.39 |
|
100 |
100 |
0 |
|
100 |
100 |
0 |
|
94.09 |
97.92 |
3.83 |
|
99.23 |
100 |
0.77 |
|
97.66 |
98.74 |
1.08 |
|
98.91 |
99.98 |
1.07 |
|
100 |
100 |
0 |
|
Fatal |
92.66 |
92.66 |
|
94.58 |
99.5 |
4.92 |
|
96.15 |
94.16 |
-1.99 |
|
96.29 |
97.03 |
0.74 |
|
100 |
100 |
0 |
|
86.53 |
96.67 |
10.14 |
|
99.23 |
100 |
0.77 |
|
78.08 |
99.11 |
21.03 |
|
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链接 |
描述 |
Support different style error messages |
|
Support the HHVM requirement of implementing methods of interfaces |
|
Support the definition usort() on equal values |
|
Support our parallel testing framework |
|
Support a string check in hash_hmac |
|
Better use of strings instead of large integers in certain parsing scenarios |
|
Support HHVM in PHP_BINARY checks |
|
Support HHVM as one of the possible PHP executables |
与Travis集成
HHVM 2.3版本公告中提到了与Travis CI集成。现在,我们开始持续的通过开源项目的单元测试,一些开源项目已把HHVM加入它们的Travis CI构建(棒极了)。以下是把HHVM加入CI构建的开源框架:
感谢以上项目能如此之快的支持我们。同样,我们对其他项目也提交了很多类似的优秀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/ |
[翻译] Facebook HHVM 团队封闭开发三周成果展的更多相关文章
- bug终结者 团队作业第三周
bug终结者 团队作业第三周 团队展示 队名 bug终结者 队员风采: 杨京典 20162302 风格:先构建框架,在一 一实现,在实现的过程中不断测试和修改. 擅长的技术:拆分问题,使用相对简单的思 ...
- 2017-2018-1 Java演绎法 第三周 作业
团队任务:团队展示与选题 团队展示 队员学号及姓名 学号 姓名 主要负责工作 20162315 马军 日常统计,项目部分代码 20162316 刘诚昊 项目部分代码,代码质量测试 20162317 袁 ...
- android组团开发站立会议第三周第一次会议
会议时间:组队开发第三周 星期一 开始时间晚上9:30-10:00 会议地点:学一食堂 二楼 到会人员:李志岩 王亚蕊 安帅 薛禄坤 张新宇 孙存良 会议概要: 1. ...
- “Hello World!”团队第三周召开的第二次会议
今天是我们团队“Hello World!”团队第三周召开的第二次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时间 ...
- “Hello World!”团队第三周召开的第三次会议
今天是我们团队“Hello World!”团队第三周召开的第三次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.代码地址 ...
- "Hello World"团队召开的第三周第七次会议
今天是我们团队“Hello World!”团队召开的第三周的第七次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.Todo List 六.会议照片 七.燃尽图 一.会议时 ...
- "Hello World"团队召开的第三周第六次会议
今天是我们团队“Hello World!”团队召开的第三周的第六次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时 ...
- “Hello World!”团队第三周召开的第一次会议
今天是我们团队“Hello World!”团队第三周召开的第一次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.Todo List 六.会议照片 七.燃尽图 一.会议时间 ...
- JavaEDU614 团队第三周项目总结
JavaEDU614 团队第三周项目总结 本周,根据项目计划完成模块的设计代码 本项目主要是完成俄罗斯方块的基本操作.用户可以自己练习和娱乐.需要满足以下几点要求. (1)界面控制游戏开始.暂停和结束 ...
随机推荐
- js中Math.round、parseInt、Math.floor和Math.ceil小数取整总结(转)
js中Math.round.parseInt.Math.floor和Math.ceil小数取整总结 Math.round.parseInt.Math.floor和Math.ceil 都可以返回一个整数 ...
- Struts2工作原理和执行流程图
在struts2的应用中,从用户请求到服务器返回相应响应给用户端的过程中,包含了许多组件如:Controller.ActionProxy.ActionMapping.Configuration Man ...
- Learning Python 008 正则表达式-003 search()方法
Python 正则表达式 - search()方法 findall()方法在找到第一个匹配之后,还会继续找下去,findall吗,就是找到所有的匹配的意思.如果你只是想找到第一个匹配的信息后,就不在继 ...
- R: which(查询位置)、%in% (是否存在)、ifelse(判断是否):
################################################### 问题:ifelse.which.%in% 18.4.27 解决方案: > x < ...
- 文件格式——fastq格式
fastQ格式 FASTQ是一种存储了生物序列(通常是核酸序列)以及相应的质量评价的文本格式. 他们都是以ASCII编码的.现在几乎是高通量测序的标准格式.NCBI Short Read Archiv ...
- java单链表反转
今天做leetcode,遇到了单链表反转.研究了半天还搞的不是太懂,先做个笔记吧 参考:http://blog.csdn.net/guyuealian/article/details/51119499 ...
- python远程登录Paramiko模块的安装
最近做云平台的项目,需要使用python来管理所有的主机,我选择了paramiko.它跨平台的,linux和window都可以使用,pssh只支持linux. 1:安装gcc和python-devel ...
- PLSQL Developer 直接用ip访问指定数据库
- HN669打包工具--游戏对接
一. 将游戏工程拖入到工具的HN669Ploy目录下,如下图: 二. xCode打开游戏工程,将Core目录下的HN669SDKCore工程添加入游戏工程,并引用库,如图: 三.调用API 1.A ...
- 为什么源码中很多方法就一行throw new RuntimeException("Stub!")
在使用某些类的方法时,发现其内部就一行throw new RuntimeException("Stub!"),但是实际运行中并没有抛出该错误,该方法也并没有语法报错. 因此可能是系 ...