日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

php7模拟,认识PHP7虚拟机()三

發(fā)布時間:2024/3/12 php 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php7模拟,认识PHP7虚拟机()三 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原標(biāo)題:認(rèn)識PHP7虛擬機()三

動態(tài)函數(shù)調(diào)用

盡量不要使用動態(tài)的函數(shù)名去調(diào)用函數(shù):

function foo() { }

foo();

number of ops: 4

compiled vars: none

line #* E I O op fetch ext return operands

-------------------------------------------------------------------------------------

2 0 E > NOP

3 1 INIT_FCALL 'foo'

2 DO_UCALL

3 > RETURN 1

NOP表示不做任何操作,只是將當(dāng)前opline指向下一條OPCode,編譯器產(chǎn)生這條指令是由于歷史原因。為何到PHP7還不移除它呢= =

看看使用動態(tài)的函數(shù)名去調(diào)用函數(shù):

function foo() { }

$a = 'foo';

$a();

number of ops: 5

compiled vars: !0 = $a

line #* E I O op fetch ext return operands

-------------------------------------------------------------------------------------

2 0 E > NOP

3 1 ASSIGN !0, 'foo'

4 2 INIT_DYNAMIC_CALL !0

3 DO_FCALL 0

4 > RETURN 1

不同點在于INIT_FCALL和INIT_DYNAMIC_CALL,看下兩個函數(shù)的源碼:

static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

{

USE_OPLINE

zval *fname = EX_CONSTANT(opline->op2);

zval *func;

zend_function *fbc;

zend_execute_data *call;

fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname)); /* 看下是否已經(jīng)在緩存中了 */

if (UNEXPECTED(fbc == NULL)) {

func = zend_hash_find(EG(function_table), Z_STR_P(fname)); /* 根據(jù)函數(shù)名查找函數(shù) */

if (UNEXPECTED(func == NULL)) {

SAVE_OPLINE();

zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(fname));

HANDLE_EXCEPTION();

}

fbc = Z_FUNC_P(func);

CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); /* 緩存查找結(jié)果 */

}

call = zend_vm_stack_push_call_frame_ex(

opline->op1.num, ZEND_CALL_NESTED_FUNCTION,

fbc, opline->extended_value, NULL, NULL);

call->prev_execute_data = EX(call);

EX(call) = call;

ZEND_VM_NEXT_OPCODE();

}

static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

{

/* 200多行代碼,就不貼出來了,會根據(jù)CV的類型(字符串、對象、數(shù)組)做不同的函數(shù)查找 */

}

很顯然INIT_FCALL相比INIT_DYNAMIC_CALL要輕量許多。

類的延遲綁定

簡單地說,類A繼承類B,類B最好先于類A被定義。

class Bar { }

class Foo extends Bar { }

number of ops: 4

compiled vars: none

line #* E I O op fetch ext return operands

-------------------------------------------------------------------------------------

2 0 E > NOP

3 1 NOP

2 NOP

3 > RETURN

從生成的OPCode可以看出,上述PHP代碼在運行時,執(zhí)行引擎不需要做任何操作。類的定義是比較耗性能的工作,例如解析類的繼承關(guān)系,將父類的方法/屬性添加進(jìn)來,但編譯器已經(jīng)做完了這些繁重的工作。

如果類A先于類B被定義:

class Foo extends Bar { }

class Bar { }

number of ops: 4

compiled vars: none

line #* E I O op fetch ext return operands

-------------------------------------------------------------------------------------

2 0 E > FETCH_CLASS 0 :0 'Bar'

1 DECLARE_INHERITED_CLASS '%00foo%2Fhome%2Froketyyang%2Ftest.php0x7fb192b7101f', 'foo'

3 2 NOP

3 > RETURN 1

這里定義了Foo繼承自Bar,但當(dāng)編譯器讀取到Foo的定義時,編譯器并不知道任何關(guān)于Bar的情況,所以編譯器就生成相應(yīng)的OPCode,使其定義延遲到執(zhí)行時。在一些其他的動態(tài)類型的語言中,可能會產(chǎn)生錯誤:Parse error : class not found。

除了類的延遲綁定,像接口、traits都存在延遲綁定耗性能的問題。

對于定位PHP性能問題,通常都是先用xhprof或xdebug profile進(jìn)行定位,需要通過查看OPCode定位性能問題的場景還是比較少的。

總結(jié)

希望通過這篇文章,能讓你了解到PHP虛擬機大致是如何工作的。具體opcode的執(zhí)行,以及函數(shù)調(diào)用涉及到的上下文切換,有許多細(xì)節(jié)性的東西,限于本文篇幅,在另一篇文章:PHP 7 中函數(shù)調(diào)用的實現(xiàn)進(jìn)行講解。返回搜狐,查看更多

責(zé)任編輯:

總結(jié)

以上是生活随笔為你收集整理的php7模拟,认识PHP7虚拟机()三的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。