JIT编译原理
一.查看JIT编译原理图
二.Zend Opcache作用
1.检查opcodes是否缓存
2.zend compiler编译器进行编译生成opcodes
3.optimizer优化器生成优化后的opcodes
4.把优化后的opcodes放入opcodes cache缓存
5.经过zend vm虚拟机生成opcodes handlers处理程序
6.送入x86 cpu架构进行执行
三.JIT编译原理
1.检查opcodes是否缓存
2.zend compiler编译器进行编译生成opcodes
3.optimizer优化器生成优化后的opcodes
4.把优化后的opcodes放入opcodes cache缓存
5.jit编译器把optimized opcodes再次编译成汇编机器码machine codes
6.进入zend vm虚拟前先检查是否开启jit引擎
7.如果已经开启了jit引擎则直接读取机器码中的jit buffer代码片段
8.送入x86 cpu架构进行执行
四.Opcache示意图的关键点
1.Opcache会做opcode层面的优化,比如图中的两条opcode合并为一条
2.PHP8的JIT目前是在Opcache之中提供的
3.JIT在Opcache优化之后的基础上,结合Runtime的信息再次优化,直接生成机器码
4.JIT不是原来Opcache优化的替代,是增强
5.目前PHP8只支持x86架构的CPU
Tracing JIT和Function JIT编译引擎
一.JIT功能开启
#php.iniopcache.jit=1205opcache.jit_buffer_size=64M
二.opcache.jit说明
1.是否在生成机器码的时候使用AVX指令, 需要CPU支持
0: 不使用
1: 使用
2.寄存器分配策略
0: 不使用寄存器分配
1: 局部(block)域分配
2: 全局(function)域分配
3.JIT触发策略
0: PHP脚本载入的时候就JIT
1: 当函数第一次被执行时JIT
2: 在一次运行后,JIT调用次数最多的百分之(opcache.prof_threshold * 100)的函数
3: 当函数/方法执行超过N(N和opcache.jit_hot_func相关)次以后JIT
4: 当函数方法的注释中含有@jit的时候对它进行JIT
5: 当一个Trace执行超过N次(和opcache.jit_hot_loop, jit_hot_return等有关)以后JIT
4.JIT优化策略,数值越大优化力度越大
0: 不JIT
1: 做opline之间的跳转部分的JIT
2: 内敛opcode handler调用
3: 基于类型推断做函数级别的JIT
4: 基于类型推断,过程调用图做函数级别JIT
5: 基于类型推断,过程调用图做脚本级别的JIT
三.JIT配置
1.disable
在启动时完全禁用JIT功能,并且在运行时无法启用
2.off
禁用,但是可以在运行时启用JIT
3.on
启用tracing模式
4.tracing
数值配置的别名1254
5.function
数值配置的别名1205
四.JIT实用配置
opcache.jit=tracingopcache.jit_buffer_size=64M
Opcodes编译原理
一.opcodes作用
opcodes是一种php脚本编译后的中间语言,就像java的bytecode,或者.net的msl
二.原生php代码
三.PHP执行这段代码会经过如下4个步骤
#PHP的语言引擎Zend1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)2.Parsing, 将Tokens转换成简单而有意义的表达式3.Compilation, 将表达式编译成Opocdes4.Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能
四.Scanning
#用token_get_all处理以上PHP原生代码#index.php';$arr=$tokens=token_get_all($str);echo "";print_r($arr);echo ""; ?>Array( [0] => Array ( [0] => 367 [1] => Array ( [0] => 316 [1] => echo ) [2] => Array ( [0] => 370 [1] => ) [3] => Array ( [0] => 315 [1] => "Hello World" ) [4] => ; [5] => Array ( [0] => 370 [1] => ) [6] => = [7] => Array ( [0] => 370 [1] => ) [8] => Array ( [0] => 305 [1] => 1 ) [9] => Array ( [0] => 370 [1] => ) [10] => + [11] => Array ( [0] => 370 [1] => ) [12] => Array ( [0] => 305 [1] => 1 ) [13] => ; [14] => Array ( [0] => 370 [1] => ) [15] => Array ( [0] => 316 [1] => echo ) [16] => Array ( [0] => 370 [1] => ) [17] => ;)
2.Parsing
#接下来,就是Parsing阶段了,Parsing首先会丢弃Tokens Array中的多余的空格,将剩下的转成一个一个的简单的表达式
1.echo a constant string2.add two numbers together3.store the result of the prior expression to a variable4.echo a variable
3.Compilation
#它会把Tokens编译成一个个op_array* ZEND_ECHO 'Hello World'* ZEND_ADD ~0 1 1* ZEND_ASSIGN !0 ~0* ZEND_ECHO !0> ```4.由Zend引擎一行一行读取并执行.Opcache和JIT功能开启
一.opcache配置
#php.inizend_extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20200930/opcache.soopcache.enable=1opcache.enable_cli=1
二.jit配置
#php.ini1.使用数值opcache.jit=1235opcache.jit_buffer_size=64M2.使用简单标记opcache.jit=tracingopcache.jit_buffer_size=64M
三.检测
#php文件phpinfo();
JIT高性能测试
一.PHP原生代码
#index.php
二.获得JIT汇编后的机器码
#/usr/local/php/bin/php/usr/local/php/bin/php -d opcache.jit=1205 -d opcache.jit_debug=0x01 index.php/usr/local/php/bin/php -d opcache.jit=function -d opcache.jit_debug=0x01 index.phpJIT$simple: ; (/tmp/1.php) sub $0x10, %rsp xor %rdx, %rdx jmp .L2.L1: add $0x1, %rdx
三.JIT基准测试
#Zend/bench.php#cp /mnt/php-8.0.0/Zend/bench.php /usr/local/nginx/html/bbs/
1.jit禁用
/usr/local/php/bin/php -d opcache.jit_buffer_size=0 bench.php/usr/local/php/bin/php -d opcache.jit=disable bench.php
2.jit开启
/usr/local/php/bin/php -d opcache.jit_buffer_size=64M -d opcache.jit=1205 bench.php/usr/local/php/bin/php -d opcache.jit=tracing bench.php
四.JIT计算压力测试
#index.php#win abab -n10 -c10 http://bbs.linux.com/index.phpab -n1000 -c1000 http://bbs.linux.com/index.phpab -n10000 -c10000 http://bbs.linux.com/index.php
五.JIT WEB压力测试
#index.phpphpinfo();#win abab -n10 -c10 http://bbs.linux.com/index.phpab -n1000 -c1000 http://bbs.linux.com/index.phpab -n10000 -c10000 http://bbs.linux.com/index.php