background image

如何提高

PHP 中 Zend 引擎分发方式

 
    从 PHP5.1 开始,PHP 提供了用户对 Zend VM 执行分发方式的选择接口.
  之前的文章中

, 我也提过这方面的内容, Zend 虚拟机在执行的时候, 对于编译生成的

op_array 中的每一条 opline 的 opcode 都会分发到相应的处理器(zend_vm_def.h 定义)执行, 而
按照分发的方式不同

, 分发过程可以分为 CALL, SWITCH, 和 GOTO 三种类型.

  默认是

CALL 方式, 也就是所有的 opcode 处理器都定义为函数, 然后虚拟机调用. 这种

方式是传统的方式

, 也一般被认为是最稳定的方式.

  

SWITCH 方式和 GOTO 方式则和其命名的意义相同,  分别通过 switch 和 goto 来分发

opcode 到对应的处理逻辑(段).
  官方给出的描述是

:

  

CALL – Uses function handlers for opcodes

  

SWITCH – Uses switch() statement for opcode dispatch

  

GOTO – Uses goto for opcode dispatch (threaded opcodes architecture)

  

GOTO is usually (depends on CPU and compiler) faster than SWITCH, which

  

tends to be slightly faster than CALL.

  

CALL is default because it doesn’t take very long to compile as opposed

  

to the other two and in general the speed is quite close to the others.

  那么如果使用

GOTO 方式, 效率上到底能提高多少呢?

  今天我就分别使用各种方式来测试一番

, 测试脚本 bench.php.

  第一点被证明的就是

, 官方说的 GOTO 方式编译耗时显著高于其他俩种方式, 我一开始

在虚拟机上编译

, 每次都 Hangup(囧), 最后只好换了个强劲点的物理机, 大约 3 分钟后, 编译

成功

..

  测试环境

:

 
  

PHP 5.3.0 Linux

  

AMD Opteron(tm) Processor 270(2G) X 4 6G Memory

 
  编译参数

:

 
  

./configure --with-zend-vm=CALL/GOTO/SWITCH

 
  测试结果如下

(都是三次取中值):

  

CALL 方式:

 
  

laruence@dev01.tc$ sapi/cli/php bench.php

  

simple 0.358

  

simplecall 0.418

  

simpleucall 0.405

  

simpleudcall 0.424

  

mandel 1.011

  

mandel2 1.238

  

ackermann(7) 0.375

  

ary(50000) 0.083