深入了解php opcode缓存原理
什么是opcode
opcode(operate code)是计算机指令中的一部分,用于指定要执行的操作,指令的格式和规范由处理器的指定规范指定
opcode是一种php脚本编译后的中间语言,就像java的ByteCode,或者.NET的MSL
为什么要使用opcode缓存
opcode cache的目的是避免重复编译,减少CPU和内存开销的。如果动态内容的性能瓶颈不在于CPU和内容,而在于IO操作,比如数据库查询带来的IO开销,这个时候opcode cache的性能提升是非常有局限的。无论如何既然opcode cache 可以降低cpu和内存的开销,这当然是好事了
目前PHP中常见的opcode cahce模块如下
APC
Optimizer+(目前已开源并与php5.5+集成了opcache)
xcache
eAccelerator
Opcode原理
例如有如下一段代码
<?php
echo 'Hello World';
$a = 1 + 1;
echo $a;
?>
php执行这段代码会经过如下4个步骤(准确的说,通过php的语言引擎Zend)
Scanning(Lexing)将php代码转化为语言片段(Tokens)
Parsing,将Tokens转化为简单而有意义的表达式
Complilation,将表达式编译成Opcode
Execution,顺序执行Opcode,每次一条,从而实现php脚本的功能
如下图

Lexing阶段
Lex 就是一个词法分析的依据表。Zend引擎会会对输入的php代码进行词法分析(切确的说是: Zend/zend_language_scanner.c会根据Zend/zend_language_scanner.l(Lex文件) ),从而得到一个一个的词,php中提供了一个函数:token_get_all可以将一段php代码解析成tokens
如果用这个函数分析上面的示例代码,结果如下:
Array
(
[0] => Array
(
[0] => 374
[1] => <?php
[2] => 1
) [1] => Array
(
[0] => 377
[1] =>
[2] => 1
) [2] => Array
(
[0] => 317
[1] => echo
[2] => 1
) [3] => Array
(
[0] => 377
[1] =>
[2] => 1
) [4] => Array
(
[0] => 316
[1] => "Hello World"
[2] => 1
) [5] => ;
[6] => Array
(
[0] => 310
[1] => $a
[2] => 1
) [7] => Array
(
[0] => 377
[1] =>
[2] => 1
) [8] => =
[9] => Array
(
[0] => 377
[1] =>
[2] => 1
) [10] => Array
(
[0] => 306
[1] => 1
[2] => 1
) [11] => Array
(
[0] => 377
[1] =>
[2] => 1
) [12] => +
[13] => Array
(
[0] => 377
[1] =>
[2] => 1
) [14] => Array
(
[0] => 306
[1] => 1
[2] => 1
) [15] => ;
[16] => Array
(
[0] => 377
[1] =>
[2] => 1
) [17] => Array
(
[0] => 317
[1] => echo
[2] => 1
) [18] => Array
(
[0] => 377
[1] =>
[2] => 1
) [19] => Array
(
[0] => 310
[1] => $a
[2] => 1
) [20] => ;
[21] => Array
(
[0] => 376
[1] => ?>
[2] => 1
) )
分析这个返回结果我们可以发现,源码中的字符串,字符,空格都会原样返回。每个源代码的字符都会出现在相应的顺序处。而其他的例如标签,操作符,语句 都被转化成一个包含;两部分的array:Token ID(也就是在Zend内部的该Token的对应码,比如T_ECHO,T_STRING)和 源码中原来的内容
Parsing阶段
Parsing阶段首先会丢弃Tokens array中的多余空格,然后将剩余的Tokens转换成一个一个简单的表达式
echo a contanst string
add two numbers together
store the result of the prior expression to a variable
echo a variable
Complilation阶段
Complilation阶段会把Tokens编译成一个个op_array,每个op_array包含如下5个部分
Opcode数字的标示,指明了每个op_array的操作类型,比如add,echo
结果 存放Opcode的结果
操作数1 给Opcode的操作数
操作数2
扩展值 1个整形用来区别被重载的操作符
比如我的php代码会被Parsing成:
ZEND_ECHO 'Hello World'
ZEND_ADD ~0 1 1
ZEND_ASSIGN !0 ~0
ZEND_ECHI ~0
在上面的代码我们并没有看到 $a,去哪里了?
这个就要介绍操作数了,每个操作数都是由以下两个部分组成:
op_type :为IS_CONST,IS_TMP_VAR,IS_VAR,IS_UNUESED or IS_CV
u 一个联合体,根据op_type不同 分别用不同的类型保存这个操作数的值(const)或者左值(var)
而对于var来说,每个var也不一样
IS_TMP_VAR 顾名思义就是这是一个临时变量,保存一些op_array 的结果,以便接下来的op_array 使用,这种的操作数u保存着一个指向变量表的一个句柄(整数),这个操作数一般用~ 开头 ,比如 ~0 表示 变量表中0号的未知的临时变量
IS_VAR 这是我们一般意义上的变量,他们以$开头表示
IS_CV 表示ZE2.1/PHP5.1以后的编译器使用的一种cache机制,这种变量保存着被应用的变量地址,当一个变量第一次被应用的时候 ,就会被CV起来,以后对这个变量的引用就不需要再去查找active符号表了,CV变量已!开头表示
这么开来 我的$a 被优化成了!0了
Opcode Cache原理
通过上面的介绍,我们了解了opcode,关于opcode cache的原理图大致如下

我们可以看到除了 Lexing,Parsing,Complilation,Execution阶段 还多了一个阶段:检测文件是否有更新
如果没有更新直接获取缓存的opcode,直接进入Execution阶段然后返回结果
如果更新了就按照原来流程(加入一个环节:图中红色部分 缓存opcode)
原文地址:深入了解php opcode缓存原理
标签:php opcache opcode apc token_get_all 缓存
智能推荐
- PAC 自动代理
- phpstorm9 无法输入中文逗号句号等符号了,怎么破?
- phpexcel 读取数据
- 【Composer】实战操作二:自己创建composer包并提交
- 完美解决failed to open stream: HTTP request failed!(file_get_contents引起的)
深入了解php opcode缓存原理的更多相关文章
- 【转载】深入理解PHP Opcode缓存原理
转载地址:深入理解PHP Opcode缓存原理 什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).O ...
- 黄聪:深入理解PHP Opcode缓存原理
什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译,减少 ...
- 深入理解PHP Opcode缓存原理
什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译,减少 ...
- php的opcode缓存原理
opcode是什么? 它是一种PHP脚本编译后的中间语言,类似java的字节码. PHP代码执行(Zend引擎)的步骤如下: 1.Scanning(Lexing) ,将PHP代码转换为语言片段(T ...
- php opcode缓存
本文移至:http://www.phpgay.com/Article/detail/classid/2/id/61.html 1.什么是opcode 解释器分析代码之后,生成可以直接运行的中间代码,就 ...
- PHP-深入理解Opcode缓存
1.什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译, ...
- 浏览器HTTP缓存原理分析
以前项目中遇到了很多浏览器缓存相关的问题,也在网上查过资料,搞过服务器的配置,来确保客户端加载服务器资源的速度和资源有效性.最近仔细看了下http协议中和缓存相关的一些属性,总结一下. 浏览器缓存原理 ...
- ahjesus 前端缓存原理 转载
LAMP缓存图 从图中我们可以看到网站缓存主要分为五部分 服务器缓存:主要是基于web反向代理的静态服务器nginx和squid,还有apache2的mod_proxy和mod_cache模 浏览器缓 ...
- Hibernate缓存原理与策略
Hibernate缓存原理: 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等 ...
随机推荐
- BZOJ 3156: 防御准备 斜率优化DP
3156: 防御准备 Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战 ...
- loadrunner关联边界乱码
问题现象: 如上图中的我想关联 <ins class="curmarker" id="cur2494"></ins><ins cl ...
- 2016.6.21 PHP与MqSQL交互之图片读取
<td width="265"> <?php mysql_select_db("member"); mysql_query("set ...
- 面向对象之对象,作用域及this
object eg: var o = { a : 2, b : 3 }; console.log(o); console.log(typeof o); console.log(o.a.toFixed( ...
- http://jingyan.baidu.com/article/bad08e1ee14ae409c85121cf.html
http://jingyan.baidu.com/article/bad08e1ee14ae409c85121cf.html
- AngularJS学习笔记一:简单入门
阿里云网站的前端是AngularJS实现的. 先下载AngularJS的开发工具包,我下载的angular-1.4.0. 在合适位置引入js文件: <script src="angul ...
- COGS731 [网络流24题] 最长递增子序列(最大流)
给定正整数序列x1,..., xn (n<=500).(1)计算其最长递增子序列的长度s.(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列.(3)如果允许在取出的序列中多次使用x1和 ...
- Hibernate批处理操作优化 (批量插入、更新与删除)
问题描述 我开发的网站加了个新功能:需要在线上处理表数据的批量合并和更新,昨天下午发布上线,执行该功能后,服务器的load突然增高,变化曲线异常,SA教育了我一番,让我尽快处理,将CPU负载降低. 工 ...
- winform学习-----理解小概念-20160517
1.MouseDown事件 当鼠标指针位于控件上并按下鼠标键时发生. 2.MouseUp事件 当鼠标指针在控件上并释放鼠标按键时发生. 与 mouseout 事件不同,只有在鼠标指针离开被选元素时,才 ...
- Java 反射机制学习资料
Java反射——引言 Java反射——Class对象 Java反射——构造函数 Java反射——字段 Java反射——方法 Java反射——Getter和Setter Java反射——私有字段和私有方 ...