带你了解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 相关文章推荐
用PHP调用Oracle存储过程
Oct 09 PHP
PHP文件上传实例详解!!!
Jan 02 PHP
PHP 加密解密内部算法
Apr 22 PHP
redis 队列操作的例子(php)
Apr 12 PHP
php 批量生成html,txt文件的实现代码
Jun 26 PHP
浅析php中抽象类和接口的概念以及区别
Jun 27 PHP
div li的多行多列 无刷新分页示例代码
Oct 16 PHP
从刷票了解获得客户端IP的方法
Sep 21 PHP
利用PHP实现开心消消乐的算法示例
Oct 12 PHP
PHP中类型转换 ,常量,系统常量,魔术常量的详解
Oct 26 PHP
PHP实现文件上传后台处理脚本
Mar 04 PHP
PHP 实现 WebSocket 协议原理与应用详解
Apr 22 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
无法载入 mcrypt 扩展,请检查 PHP 配置终极解决方案
2011/07/18 PHP
PHP仿微信多图片预览上传实例代码
2016/09/13 PHP
PHP配置ZendOpcache插件加速
2019/02/14 PHP
如何通过Apache在本地配置多个虚拟主机
2020/07/29 PHP
使用Post提交时须将空格转换成加号的解释
2013/01/14 Javascript
jQuery中:checked选择器用法实例
2015/01/04 Javascript
js实现完全自定义可带多级目录的网页鼠标右键菜单方法
2015/02/28 Javascript
理解JS绑定事件
2016/01/19 Javascript
Bootstrap基本插件学习笔记之折叠(22)
2016/12/08 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
NodeJS实现视频转码的示例代码
2017/11/18 NodeJs
基于Node.js实现压缩和解压缩的方法
2018/02/13 Javascript
Vue实现内部组件轮播切换效果的示例代码
2018/04/07 Javascript
在vue项目中使用md5加密的方法
2018/09/14 Javascript
跟混乱的页面弹窗说再见
2019/04/11 Javascript
vue - props 声明数组和对象操作
2020/07/30 Javascript
解决Antd 里面的select 选择框联动触发的问题
2020/10/24 Javascript
[31:33]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS DT 第一场
2014/05/23 DOTA
[38:31]完美世界DOTA2联赛PWL S3 Magma vs GXR 第一场 12.13
2020/12/17 DOTA
[07:01]DOTA2-DPC中国联赛正赛 Aster vs Magma 3月5日 赛后选手采访
2021/03/11 DOTA
提升Python程序运行效率的6个方法
2015/03/31 Python
全面了解python中的类,对象,方法,属性
2016/09/11 Python
python DataFrame 修改列的顺序实例
2018/04/10 Python
Python3.6使用tesseract-ocr的正确方法
2018/10/17 Python
Python Pillow Image Invert
2019/01/22 Python
深入解析Python小白学习【操作列表】
2019/03/23 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
Python爬虫实现使用beautifulSoup4爬取名言网功能案例
2019/09/15 Python
Python QTimer实现多线程及QSS应用过程解析
2020/07/11 Python
Yahoo-PHP面试题3
2012/01/14 面试题
北京RT科技有限公司.net工程师面试题
2013/02/15 面试题
公司总经理岗位职责
2014/03/15 职场文书
群众路线班子对照检查材料
2014/09/25 职场文书
python批量创建变量并赋值操作
2021/06/03 Python
opencv-python图像配准(匹配和叠加)的实现
2021/06/23 Python
JavaScript小技巧带你提升你的代码技能
2021/09/15 Javascript