简介

在PHP的生命周期中

词法分析(zend_language_scanner),将PHP代码转换为语言片段(Tokens)
语法分析(zend_language_parser)将Tokens转换成简单而有意义的表达式
编译(compiler),将表达式编译成Opocdes,返回zend_op_array指针
Zend Engine(zend_vm_execute),顺次执行Opcodes,每次一条, 根据传入的zend_op_array指针,执行opcode并将结果返回输出

在上述执行过程中,经常被人提起的解释型语言性能问题也就是因为每次执行脚本,上述过程都会重复执行。因此,也就出现了APC, xcache, eAccelerator等缓存,不过现在官方主推的是opcache

什么是opcode缓存

当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode)。Opcode cache的目地是避免重复编译,减少CPU和内存开销。如果动态内容的性能瓶颈不在于CPU和内存,而在于I/O操作,比如数据库查询带来的磁盘I/O 开销,那么opcode cache的性能提升是非常有限的。也就是opcode cache能带来CPU和内存开销的降低

APC, xcache, eAccelerator,opcache 使用共享内存进行存储,并且可以直接从中执行文件,而不用在执行前“反序列化”代码

词法分析

Zend/zend_language_scanner.c 会根据Zend/zend_language_scanner.l(Lex文件),来对输入的 PHP代码进行词法分析,从而得到一个一个的“词”,PHP4.2+开始提供了一个函数叫token_get_all ,这个函数就可以将一段PHP代码 Scanning成Tokens

一、安装VLD扩展

1、下载

地址:http://pecl.php.net/package/vld

wget  http://pecl.php.net/get/vld-0.13.0.tgz

2、编译安装

cd /usr/local/src/
wget http://pecl.php.net/get/vld-0.13.0.tgz
tar -zxf vld-0.13.0.tgz
cd vld-0.13.0
phpize && ./configure --with-php-config=php-config --enable-vld
make && make install
echo extension=vld.so >> /etc/php.d/vld.ini
service php-fpm reload
php-config、phpize要加入环境变量

3、opcode的结构

vim Zend/zend_compile.h

typedef struct _zend_op_array zend_op_array;
typedef struct _zend_op zend_op;
struct _zend_op {
opcode_handler_t handler;
znode_op op1;
znode_op op2;
znode_op result;
ulong extended_value;
uint lineno;
zend_uchar opcode;
zend_uchar op1_type;
zend_uchar op2_type;
zend_uchar result_type;
};
struct _zend_op_array {
/* Common elements */
zend_uchar type;
const char *function_name;
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
zend_uint num_args;
zend_uint required_num_args;
zend_arg_info *arg_info;
/* END of common elements */ zend_uint *refcount; zend_op *opcodes;
zend_uint last; zend_compiled_variable *vars;
int last_var; zend_uint T; zend_brk_cont_element *brk_cont_array;
int last_brk_cont; zend_try_catch_element *try_catch_array;
int last_try_catch; /* static variables support */
HashTable *static_variables; zend_uint this_var; const char *filename;
zend_uint line_start;
zend_uint line_end;
const char *doc_comment;
zend_uint doc_comment_len;
zend_uint early_binding; /* the linked list of delayed declarations */ zend_literal *literals;
int last_literal; void **run_time_cache;
int last_cache_slot; void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};

4、opcode的使用

STD_PHP_INI_ENTRY("vld.active",       "0", PHP_INI_SYSTEM, OnUpdateBool, active,       zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.skip_prepend", "0", PHP_INI_SYSTEM, OnUpdateBool, skip_prepend, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.skip_append", "0", PHP_INI_SYSTEM, OnUpdateBool, skip_append, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.execute", "1", PHP_INI_SYSTEM, OnUpdateBool, execute, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.verbosity", "1", PHP_INI_SYSTEM, OnUpdateBool, verbosity, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.format", "0", PHP_INI_SYSTEM, OnUpdateBool, format, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.col_sep", "\t", PHP_INI_SYSTEM, OnUpdateString, col_sep, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.save_dir", "/tmp", PHP_INI_SYSTEM, OnUpdateString, save_dir, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.save_paths", "0", PHP_INI_SYSTEM, OnUpdateBool, save_paths, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.dump_paths", "1", PHP_INI_SYSTEM, OnUpdateBool, dump_paths, zend_vld_globals, vld_globals)

这些是vld的系统配置

默认值

static void vld_init_globals(zend_vld_globals *vld_globals)
{
vld_globals->active = 0;
vld_globals->skip_prepend = 0;
vld_globals->skip_append = 0;
vld_globals->execute = 1;
vld_globals->format = 0;
vld_globals->col_sep = "\t";
vld_globals->path_dump_file = NULL;
vld_globals->dump_paths = 1;
vld_globals->save_paths = 0;
vld_globals->verbosity = 1;
}

php -dvld.active=1 -dvld.execute= -f  test.php

[root@localhost code]# php -dvld.active test.php
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename: /data/code/test.php
function name: (null)
number of ops: 5
compiled vars: none
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > SEND_VAL 'dbname'
1 DO_FCALL 1 $0 'config'
2 SEND_VAR_NO_REF 6 $0
3 DO_FCALL 1 'var_dump'
3 4 > RETURN 1 branch: # 0; line: 2- 3; sop: 0; eop: 4; out1: -2
path #1: 0,

更多指令参见:http://php.net/manual/en/internals2.opcodes.list.php,同时列出了每条指令的案例

Opcode查看利器之vld的更多相关文章

  1. php调试利器之phpdbg

    信海龙的博客 php调试利器之phpdbg 简介 PHPDBG是一个PHP的SAPI模块,可以在不用修改代码和不影响性能的情况下控制PHP的运行环境. PHPDBG的目标是成为一个轻量级.强大.易用的 ...

  2. Win下必备利器之Cmder

    诚言,对于开发码字者,Mac和Linux果断要比Windows更贴心;但只要折腾下,Windows下也是有不少利器的.之前就有在Windows下效率必备软件一文中对此做了下记载:其虽没oh-my-zs ...

  3. C#编程利器之二:结构与枚举(Structure and enumeration)【转】

    C#编程利器之二:结构与枚举(Structure and enumeration) 在上一篇文章中,介绍了类如何封装程序中的对象.而实际中,出了类可以封装对象外,结构和枚举也可以封装一些对象,本文将着 ...

  4. 后台任务利器之Hangfire

    后台任务利器之Hangfire 一.简述 Hangfire作为一款高人气且容易上手的分布式后台执行服务,支持多种数据库.在.net core的环境中,由Core自带的DI管理着生命周期,免去了在NF4 ...

  5. .NET Core开源组件:后台任务利器之Hangfire 转载 https://www.cnblogs.com/chenug/p/6655636.html

    .NET Core开源组件:后台任务利器之Hangfire   一.简述 Hangfire作为一款高人气且容易上手的分布式后台执行服务,支持多种数据库.在.net core的环境中,由Core自带的D ...

  6. 大数据并行计算利器之MPI/OpenMP

    大数据集群计算利器之MPI/OpenMP ---以连通域标记算法并行化为例 1 背景 图像连通域标记算法是从一幅栅格图像(通常为二值图像)中,将互相邻接(4邻接或8邻接)的具有非背景值的像素集合提取出 ...

  7. Android开发利器之ActivityTracker

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/113 Android开发利器之ActivityTracke ...

  8. windows管理员利器之用Log Parser Studio分析IIS日志(附逐浪CMS官方命令集)

    原文:windows管理员利器之用Log Parser Studio分析IIS日志(附逐浪CMS官方命令集) Log Parser Studio是一个强大的IIS图形分析工具,值得推荐. 1. 安装L ...

  9. Java高并发编程基础三大利器之CountDownLatch

    引言 上一篇文章我们介绍了AQS的信号量Semaphore<Java高并发编程基础三大利器之Semaphore>,接下来应该轮到CountDownLatch了. 什么是CountDownL ...

随机推荐

  1. C++中二维数组的动态分配

    C++中二维数组的动态分配 作者:   来源:csdn博客   公布者:admin 时间:2009-04-23 13:55:03   点击:115 C++中一维数组的动态分配十分经常使用,但C++刚開 ...

  2. “==”和equals之间的区别

    通俗点讲,==是看看左右是不是一个东西.equals是看看左右是不是长得一样.如果单纯是想记住,==:等于.equals:相同.两个长得一样的人,只能说长的相同(equals),但是不等于他们俩是一个 ...

  3. 24.Semaphore

    Semaphore     在进程方面完成信号线的控制,可以控制某个资源下,可被同时访问的线程个数.对系统的访问量进行评估,信号量维护了一个许可集:在许可前会阻塞每一个 semaphore.acqui ...

  4. iOS:UITableView表格视图控件

    UITableView:表格视图控件,继承滚动视图控件UIScrollView,(类似于UIPickerView选择器,它主要通过设置数据源代理和行为代理实现协议来设置单元格)    对表格的操作主要 ...

  5. OpenCV学习(19) 细化算法(7)

    最后再来看一种通过形态学腐蚀和开操作得到骨架的方法.http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/ 代码非常简单: v ...

  6. libjson 编译和使用 - 2. 配置使用lib文件

    以下转自:http://blog.csdn.net/laogong5i0/article/details/8223448 1. 在之前的libjson所在的解决方案里新建一个控制台应用程序,叫Test ...

  7. go语言基础之数组做函数参数是值拷贝

    1.数组做函数参数是值拷贝 示例: package main //必须有个main包 import "fmt" //数组做函数参数,它是值传递 //实参数组的每个元素给形参数组拷贝 ...

  8. linux进程、调度、线程、进程上下文等几点理解

    1.信号来自进程或内核 2.线程共享进程的代码空间和数据空间(全局变量或静态变量),文件描述符,信号,以及malloc分配的内存,每个线程拥有独立的栈空间和程序计数器,在创建线程时,调用pthread ...

  9. 测试用的数据库Transaction Log太大, 用于缩减它的脚本

    记在这里, 备用. select name, recovery_model_desc from sys.databases where name = 'WSS_Content_1000' USE WS ...

  10. Balanced Binary Tree leetcode java

    题目: Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced bin ...