什么是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模块如下

  1. APC

  2. Optimizer+(目前已开源并与php5.5+集成了opcache)

  3. xcache

  4. 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,去哪里了?

这个就要介绍操作数了,每个操作数都是由以下两个部分组成:

  1. op_type :为IS_CONST,IS_TMP_VAR,IS_VAR,IS_UNUESED or IS_CV

  2. 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   缓存

智能推荐

深入了解php opcode缓存原理的更多相关文章

  1. 【转载】深入理解PHP Opcode缓存原理

    转载地址:深入理解PHP Opcode缓存原理 什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).O ...

  2. 黄聪:深入理解PHP Opcode缓存原理

    什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译,减少 ...

  3. 深入理解PHP Opcode缓存原理

    什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译,减少 ...

  4. php的opcode缓存原理

    opcode是什么? 它是一种PHP脚本编译后的中间语言,类似java的字节码.   PHP代码执行(Zend引擎)的步骤如下: 1.Scanning(Lexing) ,将PHP代码转换为语言片段(T ...

  5. php opcode缓存

    本文移至:http://www.phpgay.com/Article/detail/classid/2/id/61.html 1.什么是opcode 解释器分析代码之后,生成可以直接运行的中间代码,就 ...

  6. PHP-深入理解Opcode缓存

    1.什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译, ...

  7. 浏览器HTTP缓存原理分析

    以前项目中遇到了很多浏览器缓存相关的问题,也在网上查过资料,搞过服务器的配置,来确保客户端加载服务器资源的速度和资源有效性.最近仔细看了下http协议中和缓存相关的一些属性,总结一下. 浏览器缓存原理 ...

  8. ahjesus 前端缓存原理 转载

    LAMP缓存图 从图中我们可以看到网站缓存主要分为五部分 服务器缓存:主要是基于web反向代理的静态服务器nginx和squid,还有apache2的mod_proxy和mod_cache模 浏览器缓 ...

  9. Hibernate缓存原理与策略

    Hibernate缓存原理: 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等 ...

随机推荐

  1. 安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情(三)码农网

    12. 安装 Apache Tomcat Tomcat 是由 Apache 设计的用来运行 Java HTTP web 服务器的 servlet 容器.按照下面的方法安装 tomcat,但需要指出的是 ...

  2. enter键实现自动登录

    将登录窗口的属性acceptbutton更改为登录按钮!

  3. git学习 本地常用操作01

    注意: Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动 不要使用Windows自带的记事本编辑任何文本文件 开始git项目: 初始化本地项目: 初始化:g ...

  4. HDU2167 Pebbles(状压DP)

    题目给一张n×n的格子,每个格子都有数字,要从格子中取若干个数字,八个方向相邻的数字不能一起取,问取的数字最大和是多少. 从第一行一行一行看下去,可以发现第1行取哪几列只会影响到第2行,第3行后面的一 ...

  5. List.Sort以及快速排序ZZ

    经常看到有人因为使用.net中的集合类处理海量数据时性能不够理想,就武断的得出.net不行,c#也不行这样的结论.对于.net framework这样的类库来说,除了性能以外,通用性和安全性同样重要, ...

  6. BZOJ3827 : [Poi2014]Around the world

    把环倍长,破环成链 设f[i]表示i一次性能飞达的最右边的点,因为f[]单调递增,所以可以$O(n)$求出 这样就形成了一个树结构,对于每个节点,在其到根节点路径上二分出深度最大的点,使得其飞过一圈 ...

  7. PNG无损压缩工具Optipng【备忘】

    Optipng 是专门的 PNG 图像优化工具. 支持WINODWS.LINUX 地址:http://optipng.sourceforge.net/ 另:jpegoptim 优化 jpeg 图片 地 ...

  8. codeforces round #201 Div2 A. Difference Row

    #include <iostream> #include <vector> #include <algorithm> using namespace std; in ...

  9. 转:深入理解JavaScript闭包概念

    闭包向来给包括JavaScript程序员在内的程序员以神秘,高深的感觉,事实上,闭包的概念在函数式编程语言中算不上是难以理解的知识.如果对作用域,函数为独立的对象这样的基本概念理解较好的话,理解闭包的 ...

  10. mysql中datetime比较大小问题 (转的)

    方法一: 你也可以:select * from t1 where unix_timestamp(time1) > unix_timestamp('2011-03-03 17:39:05') an ...