内容简介:重大事件:PHP JIT 已进入 PHP RFC,并将在PHP 8.0中实现,而PHP 7.4中也将包含JIT作为实验性功能.查看以下为翻译:
重大事件:PHP JIT 已进入 PHP RFC,并将在 PHP 8.0中实现,而PHP 7.4中也将包含JIT作为实验性功能.
查看 https://wiki.php.net/rfc/jit
以下为翻译:
PHP RFC:JIT
-
版本:0.9
-
日期:2019-01-28
-
作者:Dmitry Stogov dmitry @ php.net ,Zeev Suraski zeev@php.net
-
现状:正在讨论中
-
首次发布于: https : //wiki.php.net/rfc/jit
介绍
众所周知,PHP 7的性能跳跃最初是由尝试为PHP实现JIT而启动的。我们在2011年开始在Zend(主要是由Dmitry)开展这些工作,从那时起尝试了3种不同的实现。我们从未提出过发布其中任何一个的建议,主要有三个原因:它们导致典型的Web应用程序没有实质性的性能提升; 它们的开发和维护非常复杂; 我们仍然有其他方向可以探索以提高性能,而无需使用JIT。
今日JIT的案例
尽管支持JIT的PHP的大部分基础都没有改变 – 我们相信今天有一个很好的案例可用于支持JIT的PHP。
首先,我们相信我们已经达到了使用其他优化策略提高PHP性能的能力。换句话说 – 除非我们使用JIT,否则我们无法进一步提高PHP的性能。
其次 – 使用JIT可能会为在其他非Web,CPU密集型场景中更频繁使用PHP打开大门 – 其中性能优势实际上非常可观 – 而且今天可能还没有考虑PHP。
最后 – 使JIT可用可以为我们(额外的努力)提供在PHP中开发内置函数的能力,而不是(或除了)C – 而不会遭受与此类策略相关的巨大性能损失。今天的非JITted发动机。反过来,这可以为更快的创新打开大门 – 而且还可以实现更安全的实施,这将不太容易受到内存管理,溢出和与基于C的开发相关的类似问题的影响。
提案
我们建议将JIT包含在PHP 8中,并提供额外的工作来提高其性能和可用性。
此外,我们建议考虑在PHP 7.4中包含JIT作为实验性功能(默认情况下禁用)。
PHP JIT实现为OPcache的几乎独立部分。它可以在PHP编译时和运行时启用/禁用。启用后,PHP文件的本机代码存储在OPcache共享内存的另一个区域中,op_array→opcodes []。处理程序保留指向JIT编码的指针。这种方法根本不需要引擎修改。
我们使用DynAsm(为LuaJIT项目开发)来生成本机代码。它是一个非常轻量级和高级的工具,但它确实承担了目标汇编语言的良好和非常低级的开发知识。在过去,我们尝试过LLVM,但它的代码生成速度几乎慢了100倍,因此使用起来非常昂贵。目前,我们仅在POSIX平台上支持x86和x86_64。Windows支持应该相对简单,但对我们来说是(并且仍然是)低优先级。DynAsm还支持ARM。ARM64,MIPS,MIPS64和PPC,理论上我们应该能够支持PHP部署中常用的所有平台(给予足够的努力)。
JIT的质量可以在 https://gist.github.com/dstogov/12323ad13d3240aee8f1 上发布的Mandelbrot基准测试中得到证明,它可以将性能提高4倍以上(0.011秒对PHP 7.4的0.046秒)。
function iterate($x,$y) { $cr = $y-0.5; $ci = $x; $zr = 0.0; $zi = 0.0; $i = 0; while (true) { $i++; $temp = $zr * $zi; $zr2 = $zr * $zr; $zi2 = $zi * $zi; $zr = $zr2 - $zi2 + $cr; $zi = $temp + $temp + $ci; if ($zi2 + $zr2 > BAILOUT) return $i; if ($i > MAX_ITERATIONS) return 0; } }
以下是为上面的PHP函数生成的完整汇编代码,主循环代码在.L5和.L7之间可见:
JIT$Mandelbrot::iterate: ; (/home/dmitry/php/bench/b.php) sub $0x10, %esp cmp $0x1, 0x1c(%esi) jb .L14 jmp .L1 .ENTRY1: sub $0x10, %esp .L1: cmp $0x2, 0x1c(%esi) jb .L15 mov $0xec3800f0, %edi jmp .L2 .ENTRY2: sub $0x10, %esp .L2: cmp $0x5, 0x48(%esi) jnz .L16 vmovsd 0x40(%esi), %xmm1 vsubsd 0xec380068, %xmm1, %xmm1 .L3: mov 0x30(%esi), %eax mov 0x34(%esi), %edx mov %eax, 0x60(%esi) mov %edx, 0x64(%esi) mov 0x38(%esi), %edx mov %edx, 0x68(%esi) test $0x1, %dh jz .L4 add $0x1, (%eax) .L4: vxorps %xmm2, %xmm2, %xmm2 vxorps %xmm3, %xmm3, %xmm3 xor %edx, %edx .L5: cmp $0x0, EG(vm_interrupt) jnz .L18 add $0x1, %edx vmulsd %xmm3, %xmm2, %xmm4 vmulsd %xmm2, %xmm2, %xmm5 vmulsd %xmm3, %xmm3, %xmm6 vsubsd %xmm6, %xmm5, %xmm7 vaddsd %xmm7, %xmm1, %xmm2 vaddsd %xmm4, %xmm4, %xmm4 cmp $0x5, 0x68(%esi) jnz .L19 vaddsd 0x60(%esi), %xmm4, %xmm3 .L6: vaddsd %xmm5, %xmm6, %xmm6 vucomisd 0xec3800a8, %xmm6 jp .L13 jbe .L13 mov 0x8(%esi), %ecx test %ecx, %ecx jz .L7 mov %edx, (%ecx) mov $0x4, 0x8(%ecx) .L7: test $0x1, 0x39(%esi) jnz .L21 .L8: test $0x1, 0x49(%esi) jnz .L23 .L9: test $0x1, 0x69(%esi) jnz .L25 .L10: movzx 0x1a(%esi), %ecx test $0x496, %ecx jnz JIT$$leave_function mov 0x20(%esi), %eax mov %eax, EG(current_execute_data) test $0x40, %ecx jz .L12 mov 0x10(%esi), %eax sub $0x1, (%eax) jnz .L11 mov %eax, %ecx call zend_objects_store_del jmp .L12 .L11: mov 0x4(%eax), %ecx and $0xfffffc10, %ecx cmp $0x10, %ecx jnz .L12 mov %eax, %ecx call gc_possible_root .L12: mov %esi, EG(vm_stack_top) mov 0x20(%esi), %esi cmp $0x0, EG(exception) mov (%esi), %edi jnz JIT$$leave_throw add $0x1c, %edi add $0x10, %esp jmp (%edi) .L13: cmp $0x3e8, %edx jle .L5 mov 0x8(%esi), %ecx test %ecx, %ecx jz .L7 mov $0x0, (%ecx) mov $0x4, 0x8(%ecx) jmp .L7 .L14: mov %edi, (%esi) mov %esi, %ecx call zend_missing_arg_error jmp JIT$$exception_handler .L15: mov %edi, (%esi) mov %esi, %ecx call zend_missing_arg_error jmp JIT$$exception_handler .L16: cmp $0x4, 0x48(%esi) jnz .L17 vcvtsi2sd 0x40(%esi), %xmm1, %xmm1 vsubsd 0xec380068, %xmm1, %xmm1 jmp .L3 .L17: mov %edi, (%esi) lea 0x50(%esi), %ecx lea 0x40(%esi), %edx sub $0xc, %esp push $0xec380068 call sub_function add $0xc, %esp cmp $0x0, EG(exception) jnz JIT$$exception_handler vmovsd 0x50(%esi), %xmm1 jmp .L3 .L18: mov $0xec38017c, %edi jmp JIT$$interrupt_handler .L19: cmp $0x4, 0x68(%esi) jnz .L20 vcvtsi2sd 0x60(%esi), %xmm3, %xmm3 vaddsd %xmm4, %xmm3, %xmm3 jmp .L6 .L20: mov $0xec380240, (%esi) lea 0x80(%esi), %ecx vmovsd %xmm4, 0xe0(%esi) mov $0x5, 0xe8(%esi) lea 0xe0(%esi), %edx sub $0xc, %esp lea 0x60(%esi), %eax push %eax call add_function add $0xc, %esp cmp $0x0, EG(exception) jnz JIT$$exception_handler vmovsd 0x80(%esi), %xmm3 jmp .L6 .L21: mov 0x30(%esi), %ecx sub $0x1, (%ecx) jnz .L22 mov $0x1, 0x38(%esi) mov $0xec3802b0, (%esi) call rc_dtor_func jmp .L8 .L22: mov 0x4(%ecx), %eax and $0xfffffc10, %eax cmp $0x10, %eax jnz .L8 call gc_possible_root jmp .L8 .L23: mov 0x40(%esi), %ecx sub $0x1, (%ecx) jnz .L24 mov $0x1, 0x48(%esi) mov $0xec3802b0, (%esi) call rc_dtor_func jmp .L9 .L24: mov 0x4(%ecx), %eax and $0xfffffc10, %eax cmp $0x10, %eax jnz .L9 call gc_possible_root jmp .L9 .L25: mov 0x60(%esi), %ecx sub $0x1, (%ecx) jnz .L26 mov $0x1, 0x68(%esi) mov $0xec3802b0, (%esi) call rc_dtor_func jmp .L10 .L26: mov 0x4(%ecx), %eax and $0xfffffc10, %eax cmp $0x10, %eax jnz .L10 call gc_possible_root jmp .L10
向后不兼容的变化
没有
建议的PHP版本
PHP 8和PHP 7.4(单独投票)
RFC影响
致SAPI
没有
到现有扩展
没有
对Opcache
JIT将作为OPcache的一部分实现。
新常数
没有
php.ini默认值
如果有任何php.ini设置,则列出:
-
opcache.jit_buffer_size – 为本机代码生成保留的共享内存缓冲区的大小(以兆字节为单位)。默认值 – 0禁用JIT。
-
opcache.jit – JIT控件选项。由4位十进制数字组成 – CRTO(默认为1205.可能最好更改为1235)。
-
O – 优化级别
-
0 – 不要JIT
-
1 – 最小JIT(调用标准VM处理程序)
-
2 – 选择性VM处理程序内联
-
3 – 基于单个函数的静态类型推断的优化JIT
-
4 – 基于静态类型推断和调用树的优化JIT
-
5 – 基于静态类型推断和内部过程分析的优化JIT
-
-
T – JIT触发器
-
0 – JIT在第一个脚本加载时的所有函数
-
1 – 首次执行时的JIT功能
-
2 – 第一次请求时的配置文件,第二次请求时编译热门功能
-
3 – 动态配置文件并编译热门功能
-
4 – 在doc-comments中使用@jit标记编译函数
-
-
R – 寄存器分配
-
0 – 不执行寄存器分配
-
1 – 使用本地线性扫描寄存器分配器
-
2 – 使用全局线性扫描寄存器分配器
-
-
C – CPU特定的优化标志
-
0 – 没有
-
1 – 启用AVX指令生成
-
-
-
opcache.jit_debug – JIT调试控制选项,其中每个位启用一些调试选项。默认 – 0。
-
(1«0) – 打印生成的汇编程序
-
(1«1) – 用于代码生成的打印中间SSA表单
-
(1«2) – 注册分配信息
-
(1«4) – 允许使用GDB调试JIT编码
-
(1«5) – 生成perf.map文件以列出Linux perf报告中的JIt-ed函数
-
(1«6) – 提供有关Linux Oprofile的JIt-ed代码的信息
-
(1«7) – 提供有关英特尔VTune的JIt-ed代码的信息
-
(1«8) – 生成perf.dump文件以在Linux perf peport中显示JIT-ed函数的汇编代码
-
性能
JIT使bench.php的速度提高了两倍多:0.140秒vs 0.320秒。预计这将使大多数CPU密集型工作负载运行得更快。然而,就像以前的尝试一样 – 它目前似乎没有显着改善像WordPress这样的现实应用程序(opcache.jit = 1235 326 req / sec vs 315 req / sec)。
开放式问题
投票开始时确保没有未解决的问题!
未来范围
在PHP 8中,我们将在热函数的初始分析之后改进JIT并执行优化的代码生成。这将允许应用推测性优化并仅生成真正执行的代码。也可以将JIT与预加载和FFI进行更深层次的集成,也许是开发(和提供)用PHP编写的内置函数的标准化方法,而不仅仅是在 C语言 中。
提议的投票选择
该项目需要50%+ 1的多数。
由于PHP 7.4已经分支并且其引擎预计不会发生显着变化(因此需要对JIT实现进行相应更改),我们还可以考虑在PHP-7.4中包含JIT作为实验性功能(默认情况下禁用)。
将JIT包含在PHP 7.4中(实验性的)? | ||
---|---|---|
真正的名字 | 是 | 没有 |
最后结果: | 0 | 0 |
此民意调查已经结束。 |
补丁和测试
https://github.com/zendtech/php-src/ – PHP JIT分支是在两年多前宣布的,从那时起就与PHP master保持一致。
履行
项目实施后,此部分应包含
-
它被合并的版本
-
git commit(s)的链接
-
该功能的PHP手册条目的链接
-
指向语言规范部分的链接(如果有)
参考
被拒绝的功能
使用邮件列表中讨论的功能更新此更新。
RFC / jit.txt ·最后修改时间:2019/01/31 09:31 by 梅德
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- GitLab 11.11 发布,增强协作性功能以及 DevOps 功能
- GitLab 11.11 发布,增强协作性功能以及 DevOps 功能
- 基于AOP的一种RecyclerView复杂楼层开发框架,支持组件化,全局楼层打通,MVP等高拓展性功能
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。