php windows vld,PHP之opcode及VLD使用
OpCode,即Operation Code,操作码。通常是指计算机指令中的一部分,用于指定要执行的操作, 指令的格式和规范由处理器的指令规范指定。
通常opcode还有另一种称谓:字节码(byte codes)。例如Java编译后生成的class文件。
PHP中的opcode则属于后者,PHP构建在Zend虚拟机(Zend VM)之上。PHP的opcode就是Zend虚拟机中的指令。当Zend 引擎完成对脚本代码的编译后,便将它们生成可以直接运行的中间代码,即OpCode。
比如写了如下PHP代码:
echo "Hello World!";
$a = 1 +1;
echo $a;
?>
PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend):
1. Scanning(Lexing) ,Zend Engine(Zend引擎),调用词法分析器(Lex生成的,源文件在Zend/zend_language_sanner.l),将我们要执行的PHP源文件,去掉空格 ,注释,分割成一个一个的语言片段(Tokens)。
2. Parsing, Zend引擎会将得到的token forward给语法分析器(yacc生成, 源文件在 Zend/zend_language_parser.y),将Tokens转换成简单而有意义的表达式。
3. Compilation, 将表达式编译成Opocdes,opcode一般会以op array的形式存在。
4. Execution, Zend引擎调用zend_executor来顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
每一次请求到来的时候,都是这样一个过程,但是很明显每次都需要编译,是非常低效的。因为PHP源码不变,OpCode就不会改变,所以前面的步骤就不需要每次都进行,这就是所谓的OpCode缓存,就是将第三步生成的OpCode缓存下来,这样下一次请求来的时候就不需要前三步,直接执行OpCode就可以了,从而可以大大的提升执行速度。
关于Opcode缓存
详细的opcode编译过程可以看鸟哥的博客《深入理解PHP原理之OpCode》。
那如何可以看到我们的PHP脚本,最终被编译成什么样的呢? 也就是说,OpCode长的什么样子呢? 在PECL中已经有这样的模块,可以让我们直接使用了,那就是由 Derick Rethans开发的VLD (Vulcan Logic Dissassembler)模块。只需要下载这个模块,并把他作为PHP扩展载入,就可以通过简单的设置,来得到脚本编译的结果了。
1. 安装VLD
下载地址:http://pecl.php.net/package/vld
windows直接下载dll拷贝到php的ext目录中,然后在php.ini中加上extension=php_vld.dll就可以了。
Linux下载编译安装,然后同样php.ini加上extension=vld.so即可。
2. 使用VLD
php -dvld.active=1 test.php
比如上面的代码,就可以得到:
PHP构建在Zend 引擎之上。PHP的opcode就是Zend虚拟机中的指令,在PHP源码({PHPSRC}/Zend/zend_vm_opcodes.c)中可以发现,一共有187条指令。顺便说一下,目前PHP源码托管到github上了,源码地址:https://github.com/php/php-src/
在PHP7之前的源码中,opcode({PHPSRC}/Zend/zend_compile.h)是这样的:
struct _zend_op {
opcode_handler_t handler; // 执行该opcode时调用的处理函数
znode result;
znode op1;
znode op2;
ulong extended_value;
uint lineno;
zend_uchar opcode; // opcode代码
};
最新的PHP7中的是这样,可以看到增加了三个字段,表示操作数的数据类型,这大概是为PHP7可以支持强类型修改的吧(猜的)。
struct _zend_op {
const void *handler;
znode_op op1;
znode_op op2;
znode_op result;
uint32_t extended_value;
uint32_t lineno;
zend_uchar opcode;
zend_uchar op1_type;
zend_uchar op2_type;
zend_uchar result_type;
};
各个字段的含义:
(1)handler:op的执行句柄。
(2)op1, op2, result:这三个字段是op的操作数和操作结果载体,当然并不是每个op都需要使用这三个字段,根据op的功能不同,会使用其中某些字段。比如类型为ZEND_ECHO的op只需要使用op1,功能就是将op1中的相应的值输出。
void zend_do_echo(const znode *arg TSRMLS_DC) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ECHO;
opline->op1 = *arg;
SET_UNUSED(opline->op2);
}
PHP7之前的代码是znode类型,而php7中是znode_op类型。
PHP7中znode_op和znode的定义:
typedef union _znode_op {
uint32_t constant;
uint32_t var;
uint32_t num;
uint32_t opline_num; /* Needs to be signed */
#if ZEND_USE_ABS_JMP_ADDR
zend_op *jmp_addr;
#else
uint32_t jmp_offset;
#endif
#if ZEND_USE_ABS_CONST_ADDR
zval *zv;
#endif
} znode_op;
typedef struct _znode { /* used only during compilation */
zend_uchar op_type;
zend_uchar flag;
union {
znode_op op;
zval constant; /* replaced by literal/zv */
} u;
} znode;
PHP7之前版本znode:
typedef struct _znode {
int op_type;
union {
zval constant;
zend_uint var;
zend_uint opline_num; /* Needs to be signed */
zend_op_array *op_array;
zend_op *jmp_addr;
struct {
zend_uint var; /* dummy */
zend_uint type;
} EA;
} u;
} znode;
具体变化的原因由于并没有仔细的看源码,所以还不太明白,有空研究一下源码。
其中op_type这个int类型的字段定义操作数的类型,这些类型一共有五种:
#define IS_CONST (1<<0)
#define IS_TMP_VAR (1<<1)
#define IS_VAR (1<<2)
#define IS_UNUSED (1<<3) /* Unused variable */
#define IS_CV (1<<4) /* Compiled variable */
IS_CONST:
表示常量,例如$a = 123; $b = “hello”;这些代码生成OP后,123和”hello”都是以常量类型操作数存在。
IS_TMP_VAR:表示临时变量,临时变量一般在前面加~来表示,这是一些OP执行过程中需要用到的中间变量,例如初始化一个数组的时候,就需要一个临时变量来暂时存储数组zval,然后将数组赋值给变量。
IS_VAR:一般意义上的变量,以$开发表示,此种变量本人目前研究的较少,暂不介绍
IS_UNUSED :暂时不介绍,从名字来看应该是标识为不使用
IS_CV:这种类型的操作数比较重要,此类型是在PHP后来的版本中(大概5.1)中才出现,CV的意思是compiled variable,即编译后的变量,变量都是保存在一个符号表中,这个符号表是一个哈希表,试想如果每次读写变量的时候都需要到哈希表中去检索,势必会对效率有一定的影响,因此在执行上下文环境中,会将一些编译期间生成的变量缓存起来,此过程以后再详细介绍。此类型操作数一般以!开头表示,比如变量$a=123;$b=”hello”这段代码,$a和$b对应的操作数可能就是!0和!1, 0和1相当于一个索引号,通过索引号从缓存中取得相应的值。
(3)opcode:与CPU的指令类似,有一个标示指令的opcode字段。此字段保存的整形值即为op的编号,用来区分不同的op类型,opcode的可取值都被定义成了宏,可以在{PHPSRC}/Zend/zend_vm_opcodes.h中看到这些宏的定义,类似如({PHPSRC}/Zend/zend_vm_opcodes.h):
#define ZEND_NOP 0
#define ZEND_ADD 1
#define ZEND_SUB 2
#define ZEND_MUL 3
#define ZEND_DIV 4
#define ZEND_MOD 5
#define ZEND_SL 6
#define ZEND_SR 7
#define ZEND_CONCAT 8
(4)lineno:对应PHP源码中的行号。
(5)extended_value:PHP不像汇编那么底层,在脚本实际执行的时候可能还需要其他更多的信息,保存在extended_value字段。
转载请注明出处fullstackdevel.com:SEAN是一只程序猿 » PHP之opcode及VLD使用
php windows vld,PHP之opcode及VLD使用相关推荐
- php opcodevld,利用PHP扩张vld查看PHP opcode
作者:zhanhailiang 日期:2013-03-04 首先下载最新版vld扩展:~/public_html/php-5.3.13/ext> wget http://pecl.php.net ...
- VLD的安装使用及其问题
目录 下载 VLD 安装 VLD 使用 VLD 打开项目 配置 VLD 环境(VS 版本在 2015 及其以下的无需配置) 使用 VLD 问题 应用程序无法正常启动 0xc150002 无法显示内存泄 ...
- Visual Leak Detector (VLD)使用
Visual C++内置内存泄露检测工具,但是功能十分有限.VLD就相当强大,可以定位文件.行号,可以非常准确地找到内存泄漏的位置,而且还免费.开源! 在使用的时候只要将VLD的头文件和lib文件放在 ...
- vs 2010 下使用VLD工具
名词解释: 1.stack trace:调用堆栈信息 2.debug heap:调试堆 3.Allocation Hook:向调试堆注册的回调函数,当申请内存时,调试堆即调用此回调函数 前言 VC++ ...
- QT使用VLD检测内存泄漏
QT使用VLD检测内存泄漏 下载VLD VLD版本:vld-2.5.1-setup 下载地址:https://kinddragon.github.io/vld/ 安装VLD 直接双击安装,选择安装位置 ...
- qt5使用内存检测工具vld查看内存泄漏
什么是vld? Visual Leak Detector是一款用于Visual C++的免费的内存泄露检测工具.相比较其它的内存泄露检测工具,它在检测到内存泄漏的同时,还具有如下特点: 1. 可以得到 ...
- Qt Creator 中使用VLD检测内存泄漏
简介 Visual Leak Detector是一款用于Visual C++的免费的内存泄露检测工具.相比较其它的内存泄露检测工具,它在检测到内存泄漏的同时,还具有如下特点:可以得到内存泄漏点的调用堆 ...
- 内存泄漏查找工具VLD的使用
1.什么是vld? Visual Leak Detector(VLD)同样是一款开源检测内存泄露软件的简称. 官方的介绍如下地址:在Visual Studio调试器下运行程序时,Visual Leak ...
- 在vs中使用 vld 进行内存泄漏检测
下载 vld https://github.com/KindDragon/vld 安装 vld 后记录安装目录 C:\Program Files (x86)\Visual Leak Detector ...
- 内存泄露检测工具VLD相关配置
参考链接: VLD(Visual LeakDetector)内存泄露库的使用 VS2019编译 内存泄漏检测工具VLD 一.源码下载 源码下载链接:https://github.com/KindDra ...
最新文章
- jvm 堆外内存_NIO效率高的原理之零拷贝与直接内存映射
- 邮件发送类,支持HTML格式,支持优先级设置
- CentOs 6.0 下安装cacti的syslog插件
- Duo js 一个非常酷的前端打包工具
- 再有人问 Java 中的注解就把这篇文章丢给他!
- ML之DT(树模型):DT(树模型算法)算法的简介、代码定义、案例应用之详细攻略
- 微服务框架 Go-Micro 集成 Nacos 实战之服务注册与发现
- uni-app内置地图轨迹_MIUI11 新增亲情守护,支持安全围栏、运动轨迹功能
- Linux kernel同步机制
- docker 安装部署 Jenkins 2.322
- qt如何安装python_安装Python QT,PythonQT,的
- 人工智能是一个工程问题,而不是魔术!
- 不加载任何包,手撕一个R语言版BP神经网络模型
- Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署 grafana 度量分析和可视化
- 数值分析思考题(钟尔杰版)参考解答——第一章
- python爬虫之JS混淆加密、字体反爬
- memory repair
- 新型单词记忆法汇总(沪江英语):
- 解决springboot无法访问此网站,springboot启动后无法访问网站
- RSA算法计算d的两种方法。
热门文章
- MFC通过CImage绘制透明图层的png图片
- 现代通信技术之分组交换技术
- Python之计算机算法基础总结(借鉴、整理)、排序算法、查找算法
- iso22000食品安全管理体系_ISO22000-食品安全管理体系认证
- Android速度仪表盘,速度评级小车动画(模仿电脑版360宽带测速器)
- 计算机设备管理器驱动,设备管理器安装驱动程序的详细教程
- Android-APP之桌面宠物
- 怎样改变计算机桌面的特效主题,教你如何更改电脑主题,桌面,图标,系统主题 - 飞机城社区论坛 - 阎良论坛 飞机城论坛,......
- ManualResetEvent使用说明
- 使用fdisk给新增加硬盘分区