时间:2022-8-8来源:本站原创作者:佚名
程序开发求职招聘微信群 http://www.gpitp.gd.cn/new/20211001/95866.html

很多时候,我们会发现代码顺序,和程序实际执行的顺序不同。比如说复杂的表达式、回调函数等情况。这种时候我们可能会对程序执行的结果感到困惑。程序的执行过程对于开发人员和用户都是一个黑盒过程。假如有一个类似于日志的东西,可以让开发人员在编码阶段了解程序的执行过程,就可以使开发人员更准确地了解代码的执行结果,减少程序执行的不确定性,降低bug发生的概率。

比如下面这段代码:

?phpi=1;i=i++;k=i+++i*i++;

口算的结果是:

i=1;//i原始的值+表达式值(第一次自增后的值)+表达式值(第一次自增后的值)k=1+2*2;i=3;//两次自增后的值k=5;

实际的执行结果:

问题出在了k变量的计算结果。

口算的执行过程是,先取i变量的值作为临时值,再进行++i自增,自增后的值作为表达式的值,再获取当前i变量的值作为表达式的值,再进行i++自增,表达式的值相乘以后拿到结果,再和之前获取的临时值相加。

根据结果推算,k的执行顺序是先进行++i自增,自增后的值作为表达式的值,再获取当前i变量的值作为表达式的值,再进行i++自增,表达式的值相乘以后拿到结果,再和当前的i变量值相加。

实际项目开发过程中,我们肯定会尽量避免这种混淆,通过不同的变量名和括号分割表达式,消除代码的歧义。

但是假如我们真的遇到了这种不能确定执行顺序的代码。除了通过实际执行来猜测执行过程外,我们也可以通过一些工具来输出程序的执行过程。php的源代码在真正被zendvm执行之前,大致会先编译成抽象语法树,再生成opcode,最后交给zend引擎执行。opcode大致相当于汇编代码或者cpu的指令。

通过vld扩展输出opcode:

如果安装了swoole,并且输出内容很长,可以暂时禁用swoole扩展。

php-dvld.active=1-dvld.verbosity=3-dvld.execute=0t.php

vld扩展通过hook,可以在程序执行过程中,输出opcode。

上图蓝色框出来的部分就是实际执行的指令,从上往下为指令的执行顺序。最左边一列是指令对应源代码的行号。

指令含义:

ASSIGN代码赋值,POST_INC代表i++类型的自增(后缀自增),PRE_INC代码++i类型的自增(前缀自增),MUL代码乘法运算,ADD代表加法运算。

明白了指令的含义以后,就很容易可以看出k赋值语句的执行顺序,和我们之前根据程序执行结果推算的一致。

这里并不是探讨那段自增赋值代码的执行逻辑,也不是要求记忆opcode指令的含义,而是希望通过了解vld这个工具,实现在开发阶段对php执行过程指令级的观测。其实通过xhprof也可以查看程序的执行过程,但是观测粒度比较粗,无法查看某一行语句的内部执行过程。除了用vld扩展查看opcode,还有很多类似的调试监控工具,比如用php-parser库解析输出抽象语法树,用GDB调试运行中的程序,用strace在程序过程中动态输出内存、CPU、系统调用等。了解和学习这些工具的使用,可以有效地提升php程序的可观测性,为性能优化和代码调试提供科学依据,也有助于学习php的内核原理。

预览时标签不可点收录于话题#个上一篇下一篇
转载请注明原文网址:http://www.coolofsoul.com/phpfz/phpfz/24338.html
------分隔线----------------------------