之前的文章中, 我也提過這方面的內容, 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
ary2(50000) 0.075
ary3(2000) 0.561
fibo(30) 1.156
hash1(50000) 0.114
hash2(500) 0.091
heapsort(20000) 0.270
matrix(20) 0.276
nestedloop(12) 0.599
sieve(30) 0.350
strcat(200000) 0.039
------------------------
Total 7.844
SWITCH方式:
laruence@dev01.tc$ sapi/cli/php bench.php
simple 0.393
simplecall 0.414
simpleucall 0.424
simpleudcall 0.445
mandel 1.007
mandel2 1.254
ackermann(7) 0.392
ary(50000) 0.084
ary2(50000) 0.073
ary3(2000) 0.593
fibo(30) 1.185
hash1(50000) 0.120
hash2(500) 0.092
heapsort(20000) 0.285
matrix(20) 0.295
nestedloop(12) 0.678
sieve(30) 0.359
strcat(200000) 0.042
------------------------
Total 8.138
GOTO方式 :
laruence@dev01.tc$ sapi/cli/php bench.php
simple 0.306
simplecall 0.373
simpleucall 0.369
simpleudcall 0.385
mandel 0.879
mandel2 1.132
ackermann(7) 0.356
ary(50000) 0.081
ary2(50000) 0.073
ary3(2000) 0.525
fibo(30) 1.043
hash1(50000) 0.111
hash2(500) 0.088
heapsort(20000) 0.247
matrix(20) 0.247
nestedloop(12) 0.519
sieve(30) 0.331
strcat(200000) 0.037
------------------------
Total 7.103
可見, GOTO方式最快, SWITCH方式最慢.和官方的描述稍有不符.
GOTO方式比其默認的CALL方式, 性能提升還是比較明顯的.
所以, 如果你希望讓PHP發揮到機制, 改變Zend VM的分發方式, 也可以做為一個考慮因素.
附:
使用GOTO方式的configure選項:
--with-zend-vm=GOTO
也可以在Zend目錄下使用:
php zend_vm_gen.php --with-vm-kind=[CALLGOTOSWITH]
測試腳本bench.php
/**
* PHP Perf Bench Test Script
*/
function simple() {
$a = 0;
for ($i = 0; $i < 1000000; $i++)
$a++;
$thisisanotherlongname = 0;
for ($thisisalongname = 0; $thisisalongname < 1000000; $thisisalongname++)
$thisisanotherlongname++;
}
/****/
function simplecall() {
for ($i = 0; $i < 1000000; $i++)
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答