原标题:认识PHP7虚拟机()三

动态函数调用

尽量不要使用动态的函数名去调用函数:

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表示不做任何操作,只是将当前opline指向下一条OPCode,编译器产生这条指令是由于历史原因。为何到PHP7还不移除它呢= =

看看使用动态的函数名去调用函数:

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,看下两个函数的源码:

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)); /* 看下是否已经在缓存中了 */

if (UNEXPECTED(fbc == NULL)) {

func = zend_hash_find(EG(function_table), Z_STR_P(fname)); /* 根据函数名查找函数 */

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); /* 缓存查找结果 */

}

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多行代码,就不贴出来了,会根据CV的类型(字符串、对象、数组)做不同的函数查找 */

}

很显然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代码在运行时,执行引擎不需要做任何操作。类的定义是比较耗性能的工作,例如解析类的继承关系,将父类的方法/属性添加进来,但编译器已经做完了这些繁重的工作。

如果类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,但当编译器读取到Foo的定义时,编译器并不知道任何关于Bar的情况,所以编译器就生成相应的OPCode,使其定义延迟到执行时。在一些其他的动态类型的语言中,可能会产生错误:Parse error : class not found。

除了类的延迟绑定,像接口、traits都存在延迟绑定耗性能的问题。

对于定位PHP性能问题,通常都是先用xhprof或xdebug profile进行定位,需要通过查看OPCode定位性能问题的场景还是比较少的。

总结

希望通过这篇文章,能让你了解到PHP虚拟机大致是如何工作的。具体opcode的执行,以及函数调用涉及到的上下文切换,有许多细节性的东西,限于本文篇幅,在另一篇文章:PHP 7 中函数调用的实现进行讲解。返回搜狐,查看更多

责任编辑:

php7模拟,认识PHP7虚拟机()三相关推荐

  1. VM虚拟机-三种网络连接方式(桥接、NAT、仅主机模式)

    目录 虚拟机网络连接 一.Bridged(桥接) 二.NAT(网络地址转换) 三.Host-Only(仅主机) 在vmware workstation中如何配置网络连接方式 一.桥接 二.NAT 三. ...

  2. [转}SkyEye硬件模拟平台,第三部分: 硬件仿真实现之二

    SkyEye硬件模拟平台,第三部分: 硬件仿真实现之二 CPU/开发板仿真 文档选项 <script language=JavaScript type=text/javascript> & ...

  3. VM虚拟机-三种网络连接方式(桥接、NAT、仅主机模式

    目录 虚拟机网络连接 一.Bridged(桥接) 二.NAT(网络地址转换) 三.Host-Only(仅主机) 在vmware workstation中如何配置网络连接方式 一.桥接 二.NAT 三. ...

  4. php7.1函数,PHP7.1常用新特性和函数

    在php7发布了之后,官方又紧接着发布了php7.1.php7.2,我们也接着使用了新版本.接下来就说说7.1有那些新的特性. Nullable types 在7的时候,如果使用了强类型就必须传递或者 ...

  5. 【Tools】VMware虚拟机三种网络模式详解和操作

    00. 目录 文章目录 00. 目录 01. VMware虚拟机三种网络模式 02. Bridged(桥接模式) 03. NAT(地址转换模式) 04. Host-Only(仅主机模式) 05. 参考 ...

  6. Vmware虚拟机三种网络模式配图详解

    目录 Vmware虚拟机三种网络模式详解 Vmware虚拟机三种网络模式详解 具体的文字描述参见博文:https://www.cnblogs.com/linjiaxin/p/6476480.html ...

  7. VMWare虚拟机三种网络形式

    网关的概念 网关: 网关实质上是一个网络通向其他网络的IP地址.比如有网络A和网络B,网络A的IP地址范围为"192.168.1.1~192. 168.1.254",子网掩码为25 ...

  8. VMWare虚拟系统上网设置及VMWare虚拟机三种工作模式详解

    =========================================================== 很多网友安装了VMWare虚拟机,但是在虚拟机上网问题上却卡住了.要想虚拟机上网 ...

  9. 2021年全国职业院校技能大赛 “大数据技术与应用”—模拟赛题(三)

    2021年全国职业院校技能大赛 "大数据技术与应用" --模拟赛题(三) 文章适合了解大数据技术与应用技能大赛 赛题.文章在编写过程中难免有疏漏和错误,欢迎大佬指出文章的不足之处: ...

最新文章

  1. 分解和合并:Java 也擅长轻松的并行编程!
  2. ES7和ES8的了解
  3. request mysql 接口_TP5接口开发
  4. Hibernate面试题收藏
  5. 在Windows 7中打开Telent客户端服务
  6. JS中SetTimeOut和SetInterval方法的区别?
  7. L3-004. 肿瘤诊断-PAT团体程序设计天梯赛GPLT(广度优先搜索)
  8. STL 算法接口及用法说明
  9. 对字符串进行折半查找c语言,C语言:编写折半查找函数
  10. grub引导程序适用范围
  11. 智能优化算法应用:基于GWO优化的对称交叉熵图像多阈值分割 - 附代码
  12. kindeditor 文件上传 java_富文本编辑器kindeditor上传图片的配置方法
  13. 实对称矩阵的特征向量矩阵为酉矩阵
  14. luogu3191 [HNOI2007]紧急疏散EVACUATE
  15. 7、核心芯片说明文档
  16. 在python里调用c++的DLL出现Windows Error -529697949
  17. 【嵌入式--伺服电机】(11)MIT无刷电机FOC硬件电路分析
  18. 高一末计算机考试试题,高一计算机第一学期期末试题
  19. 台式计算机找不到无线连接,我的win7台式机找不到无线网卡解决方法介绍
  20. 燕山大学计算机考研资料汇总

热门文章

  1. 【Node.js】node入门全攻略
  2. Mongodb和ElasticSearch(ES)---未完待续
  3. pico的学习之路(二)——YL-56声音传感器(树莓派pico实现)
  4. linux 旋转编码器,基于ARM_Linux的旋转编码器接口与驱动程序的设计
  5. 用户行为分析模型实践--漏斗分析模型
  6. 千里马常有,而伯乐不常有
  7. GroupM小结1(14年8月28日)
  8. 基于ssm的田园管理系统
  9. docker设置代理 速度终于起飞
  10. 心态很容易受别人影响_孩子在学校受了委屈,家长该如何做?