PHP运行机制和原理

50 篇文章 0 订阅

1.什么是opcode缓存? 

      当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode)。Opcode cache的目地是避免重复编译,减少CPU和内存开销。如果动态内容的性能瓶颈不在于CPU和内存,而在于I/O操作,比如数据库查询带来的磁盘I/O开销,那么opcode cache的性能提升是非常有限的。但是既然opcode cache能带来CPU和内存开销的降低,这总归是好事。
  现代操作码缓存器(Optimizer+,APC2.0+,其他)使用共享内存进行存储,并且可以直接从中执行文件,而不用在执行前“反序列化”代码。这将带来显着的性能加速,通常降低了整体服务器的内存消耗,而且很少有缺点。

2.为什么要使用Opcode缓存?

      这得从PHP代码的生命周期说起,请求PHP脚本时,会经过五个步骤,如下图所示:  

  Zend引擎必须从文件系统读取文件、扫描其词典和表达式、解析文件、创建要执行的计算机代码(称为Opcode),最后执行Opcode。每一次请求PHP脚本都会执行一遍以上步骤,如果PHP源代码没有变化,那么Opcode也不会变化,显然没有必要每次都重行生成Opcode,结合在Web中无所不在的缓存机制,我们可以把Opcode缓存下来,以后直接访问缓存的Opcode岂不是更快,启用Opcode缓存之后的流程图如下所示:

3.有那些PHP Opcode缓存插件?

Optimizer+(Optimizer+于2013年3月中旬改名为Opcache,PHP 5.5集成Opcache,其他的会不会消失?)、eAccelerator、xcache、APC …

4.PHP Opcode原理

Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL。PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)

1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)
2.Parsing, 将Tokens转换成简单而有意义的表达式
3.Compilation, 将表达式编译成Opcodes
4.Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。

扫描 -> 解析 -> 编译 -> 执行 -> 输出

执行步骤

  • 扫描  对代码进行词法和语法分析,将内容切割成一个个片段 (token)
  • 解析  将代码片段筛掉空格注释等,将剩下的token 转成有意义的表达式
  • 编译  将表达式编译成中间码 (opcode)
  • 执行  将中间码一条条执行
  • 输出  将执行结果输出到缓冲区

PHP4.2开始提供了一个函数叫token_get_all,这个函数就可以讲一段PHP代码 Scanning成Tokens;

<?php
$code = <<<EOF
<?php
echo 'hello world'l;
$data = 1+1;
echo $data;
EOF;
  
print_r(token_get_all($code));

执行结果

Array
(
    [0] => Array
        (
            [0] => 376
            [1] => <?php
 
            [2] => 1
        )
 
    [1] => Array
        (
            [0] => 319
            [1] => echo
            [2] => 2
        )
 
    [2] => Array
        (
            [0] => 379
            [1] =>
            [2] => 2
        )
 
    [3] => Array
        (
            [0] => 318
            [1] => 'hello world'
            [2] => 2
        )
 
    [4] => Array
        (
            [0] => 310
            [1] => l
            [2] => 2
        )
 
    [5] => ;
    [6] => Array
        (
            [0] => 379
            [1] =>
 
            [2] => 2
        )
 
    [7] => =
    [8] => Array
        (
            [0] => 379
            [1] =>
            [2] => 3
        )
 
    [9] => Array
        (
            [0] => 308
            [1] => 1
            [2] => 3
        )
 
    [10] => +
    [11] => Array
        (
            [0] => 308
            [1] => 1
            [2] => 3
        )
 
    [12] => ;
    [13] => Array
        (
            [0] => 379
            [1] =>
 
            [2] => 3
        )
 
    [14] => Array
        (
            [0] => 319
            [1] => echo
            [2] => 4
        )
 
    [15] => Array
        (
            [0] => 379
            [1] =>
            [2] => 4
        )
 
    [16] => ;
)

观察上面可以得到三个信息

  1. Token id 例如空格回车都是 379
  2. token 字符串
  3. 行号

Token id 是Zend内部token对应码, 定义于zend_language_parser.h

提高PHP执行效率

  1. 压缩代码,去除无用注释和空白字符 (jquery.min.js)
  2. 尽量使用PHP内置函数或扩展函数
  3. 用 apc/xcache/opcache 等缓存PHP的opcode
  4. 缓存复杂和耗时的运算结果
  5. 能异步处理的不要同步处理,如发送邮件

 没有安装OPcache

同样的接口从以前的几百毫秒提升到现在的50ms左右 

HHVM 为何速度快

HHVM 是由 Facebook 打造的 PHP 虚拟机,它通过将 PHP 代码动态翻译成原生机器码而大幅提高速度。执行时不用每次都去解析。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值