内容简介:重大事件: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等高拓展性功能
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming Collective Intelligence
Toby Segaran / O'Reilly Media / 2007-8-26 / USD 39.99
Want to tap the power behind search rankings, product recommendations, social bookmarking, and online matchmaking? This fascinating book demonstrates how you can build Web 2.0 applications to mine the......一起来看看 《Programming Collective Intelligence》 这本书的介绍吧!