除非您现在或者是过去生活在一块石头上(在这种情况下,欢迎您),否则您将意识到JIT将进入PHP8:今天的投票悄无声息地结束,绝大多数人赞成合并到PHP8中,所以它是正式的。
为了庆祝而抛出一些疯狂的形状,如图1所示,它甚至被称为“((Detroit)JIT”)。
现在坐下来阅读下面的神话破坏文章,我们将消除对这些东西的困惑。 JIT将会带来什么好处,并深入研究它的工作原理(但只有一点点,因为我不想让您感到无聊)。
由于我不知道我在跟谁说话,所以我将首先从简单的问题开始,然后再处理复杂的问题,如果您已经确定知道标题中的问题的答案,您可以跳过该部分...
什么是JIT?
PHP实现了一个虚拟机,一种虚拟处理器-我们称之为Zend VM。PHP将您可读的脚本编译为虚拟机可以理解的指令(我们将其称为操作码),此执行阶段称为“编译时间”。在执行的“运行时”阶段,虚拟机(Zend VM)将执行您的代码指令(操作码)。
这一切都很好,并且诸如APC(过去)和OPCache(今天)之类的工具会缓存代码的指令(操作码),以便“编译时间”仅在必须时发生。
首先,用一行来解释一般的JIT:即时是一种编译器策略,它采用中间代码表示并将其在运行时转换为与体系结构相关的机器代码-即时执行。
在PHP中,这意味着JIT将为Zend VM生成的指令视为中间表示,并发出与体系结构相关的机器代码,因此,代码的宿主不再是Zend VM,而直接是您的CPU。
为什么PHP需要JIT?
从Facebook HHVM项目的健康竞争开始,自PHP 7.0出现之前就一直是PHP内部社区的关注焦点。PHP 7.0的大多数核心更改都包含在PHPNG补丁中,该补丁大大改善了PHP在其核心中利用内存和CPU的方式,此后我们每个人都被迫密切关注性能。
从PHP 7.0开始,已经进行了一些性能改进,对HashTable(PHP的核心数据结构)进行了优化,在Zend VM中对某些操作码进行了专门化,对编译器进行了对某些序列的专门化,以及对Optimizer组件的持续改进OPCache ...以及其他很多东西,太无聊了。
荒谬的事实是,这些优化只能将我们带走,而我们正在迅速接近或可能已经遇到了进一步改进它的能力。
警告:当我们说诸如“我们无法进一步改进”之类的东西时,我们真正的意思是,“我们必须做出的进一步改进的权衡不再具有吸引力”……每当我们谈论时关于性能优化,我们正在谈论取舍。通常,要在性能方面进行权衡取舍。我们都想认为最简单的代码是最快的代码,但是在现代C编程世界中情况并非如此。最快的代码通常是准备利用依赖于体系结构的内在函数或依赖于平台(编译器)的内置函数的代码。简单性并不能保证最佳性能...
目前,将PHP转换为JIT的能力似乎是从PHP压缩性能的最佳方法。
JIT可以使我的网站更快吗?
可能性不大。
也许不是您所期望的答案:通常,用PHP编写的应用程序受I/O约束,而JIT在受CPU约束的代码上效果最佳。
“I/O和CPU约束”到底是什么意思?
当我们要描述一段代码或应用程序的一般性能特征时,我们使用术语I/O约束(I/O密集型)和CPU约束(计算密集型)。
用最简单的术语来说:
如果我们可以改进(减少,优化)它正在执行的I/O,则一段受I/O约束的代码会更快。
如果我们可以改善(减少,优化)CPU正在执行的指令,或者(神奇地)提高CPU的时钟速度,则CPU约束的代码段将更快。
一段代码或一个应用程序可以是I/O约束,CPU约束或CPU和I/O同时约束。
通常,PHP应用程序倾向于受I/O约束-放慢它们的速度是它们正在执行的I/O-连接,读取和写入数据库,缓存,文件,套接字等。
CPU约束(计算密集型)的PHP是什么样的?
由于大多数PHP应用程序的本质,CPU约束代码并不是很多PHP程序员都会熟悉的东西-他们的工作往往是连接到某个数据库,或者可能是缓存,进行一些轻松的工作并吐出html/json/xml响应。
您可能会四处查看代码库,发现许多与I/O无关的代码,甚至调用与I/O完全断开连接的函数的代码,并且会感到困惑,我似乎是在暗示这并没有使您的应用程序CPU受到限制,即使处理非I/O的代码行数可能比I/O多。
PHP实际上相当快,它是世界上最快的解释语言之一。Zend VM调用与I/O无关的函数与在机器代码中进行相同的调用之间没有显着差异。显然有区别,但是事实是机器代码具有调用约定,而Zend VM具有调用约定,机器代码具有序言,而Zend VM具有序言:您是在Zend操作码还是机器代码中调用some_c_level_function()不会对进行调用的应用程序的性能产生重大影响-尽管可能对该调用产生重大影响。
注意:调用约定(大致)是在before另一个函数之前执行的指令序列,而序言是at entry另一个函数中执行的指令序列:在两种情况下,调用约定都将参数压入堆栈,序言将它们从堆栈中弹出。
关于循环,尾部调用和XI的问题是什么呢:PHP实际上非常聪明,启用了OPCache的Optimizer组件后,您的代码就可以像魔术一样转换为您可能编写的最有效的形式。
现在必须注意,JIT不会从VM建立的约定中更改Zend函数的调用约定-Zend必须能够随时在JIT和VM模式之间切换,因此决定保留调用约定由VM建立。结果,在JIT中,您到处都可以看到的那些呼叫并没有明显地更快。
如果您想查看CPU绑定的PHP代码是什么样子,请查看Zend/bench.php...这显然是CPU绑定代码的一个极端示例,但它应该可以理解JIT真正发挥作用的地方是数学领域。
PHP是否做出了最终的权衡以提高数学速度?
否。我们这样做是为了扩展PHP的范围,并且相当大地如此。
不希望自己大声疾呼,我们已经覆盖了整个网络-如果您是2019年的Web程序员,并且尚未考虑将PHP用于下一个项目,那么您做错了网络-在这个非常偏颇的PHP开发人员看来。
乍一看,提高PHP中更快地执行数学的能力的范围似乎很狭窄。
但是,这实际上为诸如机器学习,3d渲染,2d(gui)渲染和数据分析之类的事情打开了大门。
为什么在PHP 7.4中不能使用它?
我只是将JIT称为“最终的权衡”,我认为是:它可以说是有史以来发明的最复杂的编译器策略之一,也许是最复杂的。引入JIT会带来相当大的复杂性。
如果您问Dmitry(JIT的作者)是否使PHP变得复杂,他会说“不,我讨厌复杂性”(这是直接引述)。
从根本上讲,复杂是我们所不了解的任何事情,目前,很少有真正了解我们所拥有的JIT实现的内部开发人员(少于少数)。
PHP 7.4很快出现,与PHP 7.4合并将为我们提供一个PHP版本,很少有人可以进行调试,修复或改进(从任何实际意义上来说)。对于那些拒绝加入PHP 7.4的人来说,这只是不可接受的情况。
在从现在到PHP 8的这段时间里,我们中的许多人将在业余时间工作以了解JIT:我们仍然具有要实现的功能以及需要为PHP 8重写的工具,首先我们必须了解JIT。我们需要这段时间,非常感谢大多数选民认为有资格将它赠送给我们。
复合体不是可怕的代名词:复合体可以像星云一样美丽,而JIT就是这种复合体。原则上,您可以完全理解复杂的事物,而只是稍微减少该事物的表面复杂性。换句话说,即使有20位内部开发人员像Dmitry一样熟悉JIT,也并不能真正改变JIT的复杂性。
PHP的开发会变慢吗?
没有理由认为会。我们有足够的时间可以自信地说,到PHP 8普遍可用时,我们中已经有足够的人熟悉JIT,至少在今天和我们在修复错误和推动PHP向前发展方面一样好。
当试图将JIT本质上是复杂的观点与之相提并论时,请考虑我们花在介绍新功能上的大部分时间实际上是在讨论该功能。对于大多数功能,甚至修复程序,编写代码可能需要几分钟或几小时的时间,而讨论则可能需要数周或数月的时间。在极少数情况下,某个功能的代码编写可能需要花费数小时或数天的时间,但是在那些极少数情况下,讨论总是会花费更长的时间。
那就是我要说的...
周末愉快。
原文地址
PHP GR8
https://blog.krakjoe.ninja/2019/03/php-gr8.html
扩展文章
PHP 8.0发布日期和PHP中JIT的状态
https://www.21cto.com/article/2029