带你了解PHP7 性能翻倍的关键


Posted in PHP onNovember 19, 2015

20岁老牌网页程序语言PHP,最快将在10月底释出PHP 7新版,这是十年来的首次大改版,最大特色是在性能上的大突破,能比前一版PHP 5快上一倍,PHP之父Rasmus Lerdorf表示,甚至能比HHVM虚拟机下的PHP程序性能更快。

HHVM 是脸书为自家网站特性而量身客制的PHP优化机制,不见得适用任何网站。但Rasmus Lerdorf表示,新版目标之一就是要让任何网站开发者,就连使用开发框架Drupal、开源电子商务系统Opencart时,都能有不输使用HHVM 技术的性能。在新版发表前夕,他也趁来台参加PHPConf Taiwan年会时,分享PHP 7性能大突破的关键。

一个20年来历经了多 次改版和无数次优化的成熟语言,还能有性能提高一倍的突破绝非易事,Rasmus Lerdorf坦言,不像一般新项目多半容易找出许多改进空间,新版PHP并非修改部分程序就达到了如此的成果。反而是,透过大量细节优化和性能累加 后,PHP 7才具备了不输HHVM的执行性能。

Rasmus Lerdorf与PHP核心贡献团队花了许多心力减少程序运作时搬动的内存位数,由此加速执行的性能。例如,PHP中储存变量的数据架构zval从24位 缩减至16位、Hashtable从72位减少至56位,并检视PHP中的函式,思考有无任何改进性能的空间。

除了从减少内存的使用着手 外,Rasmus Lerdorf更检视CPU的Cache line的运作原理,了解程序代码如何与CPU互动、编译程序如何在新CPU架构下编译程序代码等细节,确保PHP 7的程序代码符合现代CPU的架构。虽然每个项目的优化对性能贡献都低于0.5%,但由于优化的项目很多,或是某项改善的功能会被应用程序反复呼叫,整体 修正的综效结果就能有如此大的进展。

受HHVM刺激,决定打造兼具性能与功能的PHP

Facebook为了优化PHP运作,搭配JIT编 译而打造出虚拟机HHVM。而HHVM虽然拥有快速的执行性能,其为特定用途优化的设计,只能满足小部分的开发者。反之,Rasmus Lerdorf除了想提升PHP的性能表现外,也想要同时满足高端使用者以及业余使用者的需求,让PHP 7成为兼备性能表现及通用功能的程序语言。

然而,开发符合市场上少部分人使用的程序语言并不是难事,但是PHP项目瞄准许多对象,必须同时符合业余使用者及专业开发者需求的原则下,开发难以面面俱 到,因为总是会有部分族群的需求无法被满足,「这就像拿水管大范围的喷洒,而每个人衣服都会被水沾湿一点,但是不会有人的衣服完全湿透。」Rasmus Lerdorf比喻。

不使用外挂框架的PHP的运算性能表现都很优异,但是受到外加框架的影响,原本可以在数秒内处理上千个网页要求的 PHP,性能大幅下降,变为只能处理数十个要求。Rasmus Lerdorf表示,在HHVM出现之前,相较于对PHP性能表现的要求,使用者比较在意PHP能否降低网页开发的难度,而这些框架能让开发者的工作变得 比较简单。但是在Facebook推出HHVM后,引出许多重视PHP性能表现的使用者,让Rasmus Lerdorf意识到许多使用者有性能表现的需求。他开始思考如何将HHVM的JIT架构与PHP融合。

但Rasmus Lerdorf表示,PHP与HHVM两者在架构设计上相当不同,例如,HHVM的多线程架构并不是很稳固。此外,HHVM的可移植性并不佳,离可以在 Windows平台上运作还有很大一段路,而PHP有很多开发者在Windows环境开发,而HHVM无法照顾到那些使用者。

Rasmus Lerdorf表示,他不能放弃PHP的主要架构,虽然他们曾经考虑过融合两者,但是,HHVM在使用上有很多的限制。虽然HHVM对Facebook及 许多开发者是非常好的工具,但对于PHP项目来说,HHVM的使用范畴还不够宽广,只能符合Facebook或是Wikipedia等特定项目的需求。

非强型别语言的PHP,导入JIT是难上加难

然而,在PHP中加入JIT编译是件非常困难的事情。Rasmus Lerdorf表示,JIT必须学会辨认程序的运作模(Patterns),例如了解哪些部份为重要的程序代码,并且在程序运作前,预测程序被呼叫的时 机,或是哪些部分的程序会呼叫。

Rasmus Lerdorf比喻,在许多汽车中,JIT必须能预测哪部分的车子会右转、哪部分的车子会左转或是某些颜色汽车会直行,「而JIT必须要全部预测正确,否则性能会大大的降低。」但是,如果预测正确,程序执行性能则会大大提升。

在一般的程序语言的编译中加入JIT已属不易,Rasmus Lerdorf表示,由于PHP的动态属性(dynamic)让加入JIT是难上加难。他举例,开发者宣告参数$a值为1,但不代表程序所有的$ a的值都为1,由于PHP中参数值可以很轻易地重新定义。在C语言中,当开发者宣告参数a为整数,则a永远为整数。如果程序中有任何地方宣告a是整数以外 的类型,连编译都无法执行。而因为C语言此种强型别的程序语言,「JIT可以预测变量a为整数,但是在PHP中,我们没有这种奢侈。」他解释,HHVM的 做法为当JIT得知a是整数型别后,则假设a永远为整数。

而HHVM为了在使用JIT编译,某种程度上受限了PHP的发展。HHVM的用户 必须清楚宣告变量的性质,但是使用PHP的开发者,可以先宣告没有性质的类别(Class),后续再指定类别的变量属性。「在没有任何限制下,将JIT加 入PHP是我们要做的事。」他表示,PHP必须顾及Wordpress、Drupal等框架的开发者,不能任意停止对此些框架的支持。故与HHVM相 比,PHP在打造JIT的条件限制更多。

但是,「这不代表我们不能做JIT。此外,我们也要控制PHP的发展走向。」Rasmus Lerdorf表示。

目前,PHP核心贡献者之一的Dmitry Stogov开发一个原型JIT,并且使用某些实验性的应用程序去测试运作。Rasmus Lerdorf表示,如果将此JIT用于执行某些重复性的运算或是循环程序,得以让PHP 7性能又再快上10倍。

不过他也坦承,当此实验性的JIT用于Wordpress时,并未得到任何加速效果,「我们想要打造的JIT不是要在大学课本上学到的东西,而是能在真实世 界中运作的JIT。」他表示。因为PHP一直都抱持如此的理想,试图解决人们生活中的问题,并且能真实世界中在线环境中运作,而不只是存在课本中的理论。

Rasmus Lerdorf表示,在PHP刚问世时,他每天至少花16个小时开发PHP。但目前他已经逐渐减少投入开发,转而投注心力在世界各地宣传及演讲。他打趣地 表示:「与其自己开发,不如激励远比我聪明,又愿意一天花十八小时写程序的人去开发PHP。」他表示,他的最终目标是PHP中没有任何一行由他所撰写的程 序代码,「任何在成长中的项目都不应该由一个开发者主导,老旧的程序代码应该被新的程序代码替换。」而他认为,其他开发者应该以此为目标。

PHP 相关文章推荐
MySQL相关说明
Jan 15 PHP
dede3.1分页文字采集过滤规则详说(图文教程)续二
Apr 03 PHP
PHP开发环境配置(MySQL数据库安装图文教程)
Apr 28 PHP
Google Voice 短信发送接口PHP开源版(2010.5更新)
Jul 22 PHP
php 计划任务 检测用户连接状态
Mar 29 PHP
解决ajax+php中文乱码的方法详解
Jun 09 PHP
php中将数组转成字符串并保存到数据库中的函数代码
Sep 29 PHP
PHP代码优化之成员变量获取速度对比
Feb 28 PHP
对PHP新手的一些建议(PHP学习经验总结)
Aug 20 PHP
部署PHP时的4个配置修改说明
Oct 19 PHP
php实现网站留言板功能
Nov 04 PHP
PHP用正则匹配form表单中所有元素的类型和属性值实例代码
Feb 28 PHP
php curl模拟post请求和提交多维数组的示例代码
Nov 19 #PHP
phpStudy访问速度慢和启动失败的解决办法
Nov 19 #PHP
标准版Eclipse搭建PHP环境的详细步骤
Nov 18 #PHP
WordPress网站性能优化指南
Nov 18 #PHP
php+ajax实现无刷新分页
Nov 18 #PHP
如何使用php脚本给html中引用的js和css路径打上版本号
Nov 18 #PHP
php生成唯一数字id的方法汇总
Nov 18 #PHP
You might like
全国FM电台频率大全 - 12 安徽省
2020/03/11 无线电
解析PHP中ob_start()函数的用法
2013/06/24 PHP
PHP is_subclass_of函数的一个BUG和解决方法
2014/06/01 PHP
php分页函数完整实例代码
2014/09/22 PHP
php判断两个浮点数是否相等的方法
2015/03/14 PHP
php+MySql实现登录系统与输出浏览者信息功能
2016/07/01 PHP
Yii2框架自定义验证规则操作示例
2019/02/08 PHP
Laravel事件监听器用法实例分析
2019/03/12 PHP
PHP中md5()函数的用法讲解
2019/03/30 PHP
IE iframe的onload方法分析小结
2010/01/07 Javascript
jquery validation插件表单验证的一个例子
2010/03/03 Javascript
基于jQuery选择器的整理集合
2013/04/26 Javascript
jquery解析xml字符串示例分享
2014/03/25 Javascript
IE中图片的onload事件无效问题和解决方法
2014/06/06 Javascript
javascript时间函数大全
2014/06/30 Javascript
JavaScript实现动态添加,删除行的方法实例详解
2015/07/02 Javascript
jQuery左右滚动支持图片放大缩略图图片轮播代码分享
2015/08/26 Javascript
js阻止浏览器默认行为的简单实例
2016/05/15 Javascript
轮播的简单实现方法
2016/07/28 Javascript
微信小程序 视图容器组件的详解及实例代码
2017/01/19 Javascript
React入门教程之Hello World以及环境搭建详解
2017/07/11 Javascript
JavaScript 中的 this 简单规则
2017/09/19 Javascript
JavaScript forEach中return失效问题解决方案
2020/06/01 Javascript
三剑客:offset、client和scroll还傻傻分不清?
2020/12/04 Javascript
Python使用xlrd读取Excel格式文件的方法
2015/03/10 Python
修改python plot折线图的坐标轴刻度方法
2018/12/13 Python
python在新的图片窗口显示图片(图像)的方法
2019/07/11 Python
python3中eval函数用法使用简介
2019/08/02 Python
Python通过递归获取目录下指定文件代码实例
2019/11/07 Python
老师对学生的评语
2014/04/18 职场文书
建筑工地大门标语
2014/06/18 职场文书
高中生毕业评语
2014/12/30 职场文书
雷峰塔导游词
2015/02/09 职场文书
遗失说明具结保证书
2015/02/26 职场文书
公司车辆管理制度
2015/08/04 职场文书
Vue中Object.assign清空数据报错的解决方案
2022/03/03 Vue.js