PHP 8的Just In Time是Opcache扩展的一部分,旨在在运行时将某些操作码编译为CPU指令。这意味着使用JIT时,Zend VM不需要解释某些操作码,而这些指令将直接作为CPU级指令执行。

PHP 8 JIT

PHP 8将带来的最受好评的功能之一是Just In Time(JIT)编译器。许多博客和社区都在谈论它,并且肯定会引起很大的轰动,但是到目前为止,我发现关于JIT内部的细节很少。

经过多次研究和放弃后,我决定亲自检查PHP源代码。结合我对C语言的一点了解以及到目前为止所收集的所有分散信息,我提出了这篇文章,希望它也能帮助您更好地了解PHP的JIT。

简单来说: 当JIT按预期工作时,您的代码将不会通过Zend VM执行,而是直接作为一组CPU级指令执行。

这就是JIT核心思想。

但是为了更好地理解它,我们需要考虑php在内部如何工作。不是很复杂,但是需要一些介绍。

PHP代码如何执行?

我们都知道php是一种解释语言。但这到底是什么意思?

每当您要执行PHP代码(例如代码段或整个Web应用程序)时,都必须经过php解释器。

最常用的是PHP FPM和CLI解释器。

他们的工作非常简单:接收php代码,对其进行解释并向后吐出结果。

这通常发生在每种解释语言上。有些语言可能会删除一些步骤,但总体思路是相同的。

在PHP中,它是这样的:

PHP代码被读取并转换为一组关键字,即标记(Tokens)。这个过程允许解释器理解在程序的哪一部分中写了哪段代码。这第一步叫做词法分析或符号化。

有了Tokens后,PHP解释器将分析这个Tokens集合,并尝试理解它们。结果通过一个称为解析的过程生成了一个抽象语法树(AST)。这个AST是一组指示应该执行哪些操作的节点。例如,“echo 1 + 1”实际上应该表示“打印1 + 1的结果”,或者更实际一些“打印一个操作,操作是1 + 1”。

3 . 有了AST,理解操作和优先级就容易得多了。将这个树转换成可以执行的东西需要一个中间表示(IR),在PHP中我们称之为操作码。将AST转换为操作码的过程称为编译。

现在,有了操作码,剩下就是执行代码。PHP有一个名为Zend VM的引擎,它能够接收操作码列表并执行它们。在执行了所有操作码之后,Zend VM就存在了,程序就终止了。

执行的过程使用下图标识就更加清楚了。

非常直接,正如你们所能理解的。但这里有一个瓶颈:如果php代码变化不是那么频繁,那么每次执行代码时对其进行词法分析又有什么意义呢?

最后我们只关心操作码,对吧? 没错! 这就是为什么存在Opcache扩展。

Opcache扩展

Opcache扩展是随PHP附带的,通常没有什么理由禁用它。如果使用PHP,应该打开Opcache。

它的作用是为操作码在内存中添加一个共享缓存层。它的工作是从AST中新生成的操作码并缓存它们,以便进一步执行可以轻松跳过词法分析和解析阶段。

Opcache扩展的流程示意图:

PHP使用Opcache的解释流程。如果文件已经被解析,则php会为其获取缓存的操作码,而不是再次解析。

opcache完美地跳过了词法分析,语法解析和编译步骤。

注意:这就是PHP 7.4的预加载功能的亮点!它使您可以告诉PHP FPM解析代码库,将其转换为操作码并甚至在执行任何操作之前就对其进行缓存。

JIT即时编译器有效地做什么?

如果Opcache可以更快地获取操作码,这样它们就可以直接转到Zend VM,那么JIT应该让它们在跳过Zend VM的情况下运行。

Zend VM是一个用C编写的程序,充当操作码和CPU本身之间的一个层。JIT所做的是在运行时生成编译后的代码,这样php就可以跳过Zend VM直接转到CPU。理论上讲,我们应该从中获得性能提升。

起初,这对我来说很奇怪,因为为了编译机器代码,您需要为每种类型的体系结构编写一个非常具体的实现。但事实上,它是相当合理的。

PHP的JIT实现使用名为DynASM (Dynamic Assembler)的库,该库将一组特定格式的CPU指令映射为许多不同CPU类型的汇编代码。因此,Just In Time编译器使用DynASM将操作码转换为特定于架构的机器码。

不过,有一个想法困扰了我很长一段时间……

如果预加载能够在执行前将php代码解析为操作码,而DynASM可以将操作码编译为机器码(正好是及时编译),那么为什么我们不使用提前编译的方法直接编译php呢?!

我从收听Zeev的那集中得到的一个线索是PHP是弱类型的,这意味着PHP通常不知道变量的类型,直到Zend VM尝试执行某个操作码。

这可以通过查看zend_value联合类型看出,它有许多指针指向一个变量的不同类型表示。无论何时Zend VM尝试从zend_value中获取值,它都会使用像ZSTR_VAL这样的宏来尝试从值联合中访问字符串指针。

例如,这个Zend VM处理程序应该处理一个“小于或等于”(<=)表达式。看看它是如何分支到许多不同的代码路径的,只是为了猜测操作数类型。

用机器码复制这种类型推断逻辑是不可行的,可能会使事情变得更慢。

在计算类型之后编译所有内容也不是一个好选择,因为编译成机器码是一项CPU密集型任务。所以在运行时编译所有东西也是不好的。

JIT即时编译器是如何工作的?

现在我们知道我们不能在编译前推断出足够好的类型。我们还知道,在运行时进行编译是昂贵的。JIT对PHP有什么好处?

为了平衡这个等式,PHP的JIT只尝试编译一些它认为可以得到回报的操作码。为此,它对Zend VM正在执行的操作码进行概要分析,并检查哪些操作码可以编译。(根据您的配置)

当编译某个操作码时,它将把执行委托给编译后的代码,而不是委托给Zend VM。看起来如下:

PHP的JIT解释流程。如果已编译,则操作码不会通过Zend VM执行。

所以在Opcache扩展中有一些指令检测某个操作码是否应该编译。如果是,编译器然后使用DynASM将该操作码转换为机器码,并执行新生成的机器码。

有趣的是,由于当前实现中编译的代码有兆字节限制(也是可配置的),因此代码执行必须能够在JIT和解释代码之间无缝切换。

我仍然不确定编译部分什么时候有效地发生,但我想我现在真的不想知道。

因此性能的提高可能不会很大

为什么每个人都说大多数php应用程序不会从使用Just In Time编译器中获得很大的性能好处,我希望现在能够清楚地知道这一点。以及为什么Zeev建议对应用程序进行分析并试验不同的JIT配置是最好的方法。

如果您使用的是PHP FPM,编译后的操作码通常会在多个请求之间共享,但这仍然不能改变游戏规则。

这是因为JIT优化了cpu绑定操作,而现在大多数php应用程序都是I/O绑定的。如果你必须访问磁盘或网络,不管处理操作是否被编译。计时也非常类似。

文章翻译自https://thephp.website/en/issue/php-8-jit/

5.0

02

Post Views:

942

php 8 jit,深入理解PHP8 JIT相关推荐

  1. php8的jit如何使用,PHP JIT 是什么?PHP8 新特性之 JIT 图文详解

    PHP8 alpha1已经在昨天发布,相信关于JIT是大家最关心的,PHP8 JIT是什么,又怎么用,又有什么要注意的,以及性能提升到底咋样? 首先,我们来看一张图: (右图有点错误就是,当JIT以后 ...

  2. 深入了解PHP8 JIT(即时编译)功能

    (Just-In-Time)即时编译器是PHP 8.0中最重要的新功能之一.JIT可以通过将PHP应用程序的全部或经常调用的部分作为CPU机器代码编译并存储并直接执行,从而绕过Zend VM及其过程开 ...

  3. 支持PHP8 JIT的PHP源码加密库发布!

    FRICC2是PHP源码加密工具.当你使用PHP开发商业软件时可以使用FRICC2对发布的代码进行加密,加密后只有具备解密权限的PHP解析器才能执行程序.感谢PHP-Screw项目的贡献. 更少的文件 ...

  4. java jit技术_JVM之JIT

    JIT(just in time):即时编译编译器,能够加速 Java 程序的执行速度.通常通过 javac 将java代码编译,转换成 java 字节码,JVM将字节码将其翻译成机器指令,逐条读入, ...

  5. torch.jit.trace与torch.jit.script的区别

    文章目录 术语 什么时候用torch.jit.trace(结论:首选) 优点 什么时候用torch.jit.script(结论:必要时) 错误举例 动态控制 输入和输出有丰富类型的模型需要格外注意 Q ...

  6. java jit 编译器,[Java Performance] JIT编译器简介

    长时间运行应用的优化 对于长时间运行的应用,比如Servlet程序等,一般会使用吞吐量来测试它们的性能. 以下的一组数据表示了一个典型的数据获取程序在使用不同"热身时间"以及不同编 ...

  7. 理解 PHP 8 的 JIT

    TL;DR PHP 8 的 JIT(Just In Time)编译器将作为扩展集成到 php 中 Opcache 扩展 用于运行时将某些操作码直接转换为从 cpu 指令. 这意味着使用 JIT 后,Z ...

  8. php 8 jit,理解 PHP 8 的 JIT

    TL;DR PHP 8 的 JIT(Just In Time)编译器将做为扩展集成到 php 中 Opcache 扩展 用于运行时将某些操做码直接转换为从 cpu 指令.php 这意味着使用 JIT ...

  9. php 8 jit,PHP8正式版发布,带来了注解和JIT

    PHP8 正式版已经发布,它引入了一些重大变更,以及许多新特性和性能优化,包括命名参数.联合类型.注解.Constructor Property Promotion.match 表达式.nullsaf ...

最新文章

  1. SFB 项目经验-37-分配公网证书 For SFB 2015-持久聊天服务器(图解)
  2. 使用Oracle数据库开发中的一个技巧
  3. Java IO模型--BIO、NIO Single Thread、NIO Reactor、AIO单线程及多线程AIO
  4. JAVA-基础(查找文件夹内文件)
  5. 【数据库系统】O/R映射
  6. Mysql: LBS实现查找附近的人 (两经纬度之间的距离)
  7. SQL Server 2008安装和配置过程
  8. 5G(7)---5G NR协议栈及功能2 - MAC RLC PDCP SDAP
  9. [原] CentOS 7 安装 nginx, php mysql 套件
  10. 如何卸载mysql2008让_怎么才能把sql2008卸载干净
  11. Aspose word pdf 相互转换
  12. php 拼音搜索,通过拼音模糊搜索汉字的功能实现
  13. AWS Device Shadow使用
  14. 达尔豪西大学 计算机科学,西安大略大学和达尔豪西大学哪个好
  15. 如何把大写金额变为小写数字_excel怎么把小写数字转换成人民币大写?
  16. electron+vue3+vite2 如何使用打印
  17. git常用命令梳理及常见开发场景总结
  18. 炒股的最简单方法 炒股的管理和纪律要求
  19. Faster R-CNN文章详细解读
  20. IMP811REUS/T小秘密

热门文章

  1. A flight (to Boston) to Denver - 基于转移的顺滑技术研究 | 论文访谈间 #22
  2. 选择排序-冒泡排序-归并排序-快速排序-插入排序
  3. python中单双三引号区别_python基础题
  4. 服务器文件协议,文件服务器协议
  5. Vue-CLI@4——html-webpack-plugin默认配置的获取与修改
  6. Python——蟒蛇绘制
  7. FatMouse and Cheese
  8. springcloud、consul和Springboot的版本
  9. 软件工程概论 课堂练习 第2次作业1【思考:POS系统的对象关联】
  10. AppCompat DayNight theme