PHP7内核之Reference详解


Posted in PHP onMarch 14, 2019

问题

上一章说过引用(REFERENCE)在PHP5的时候是一个标志位, 而在PHP7以后我们把它变成了一种新的类型:IS_REFERNCE. 然而引用是一种很常见的应用, 所以这个变化带来了很多的变化, 也给我们在做PHP7开发的时候, 因为有的时候疏忽忘了处理这个类型, 而带来不少的bug.

最简单的情况, 就是在处理各种类型的时候, 从此以后我们要多考虑这种新的类型, 比如在PHP7中, 这样的代码形式就变得很常见了:

try_again:
swtich (Z_TYPE_P(zv)) {
   case IS_TRING:
   break;
   case IS_ARRAY:
   break;
  ...
   case IS_REFERENCE:
   zv = Z_REFVAL_P(zv); //解引用
   goto try_again;
   break;
}

如果大家自己写的扩展, 如果忘了考虑这种新的类型, 那么就会导致问题.

为什么?
那么既然这种新类型会带来这么多问题, 那么当时为什么要用把引用变成一种类型呢? 为什么不还是使用一个标志位呢?

一句话来说, 就是我们不得不这么做. -_#

前面说到, Hashtable直接存储的是zval, 这样在符号表中, 俩个zval如何共用一个数值呢? 对于字符串等复杂类型来说还好, 我们貌似可以在zend_refcounted结构中加入一个标志位来表明是引用来解决, 然而这个也会遇到Change On Write带来的复制, 但是我们知道在PHP7中, 一些类型是直接存储在zval中的, 比如IS_LONG, 但是引用类型是需要引用计数的, 那么对于一个是IS_LONG并且又是IS_REFERNCE的zval该如何表示呢?

为此, 我们创造了这个新的类型:

PHP7内核之Reference详解

 如图所示, 引用是一种新的类型:zend_reference, 对于IS_REFERNCE类型的zval, zval.value.ref是一个指向zend_reference的指针, 它包含了引用计数和一个zval, 具体的zval的值是存在zval.value.ref->val中的.

所以对于IS_LONG的引用来说, 就用一个类型是IS_REFERNCE的zval, 它指向一个zend_reference, 而这个zend_reference->val中是一个类型为IS_LONG的zval.

Change On Write
PHP采用引用计数来做简单的垃圾回收, 考虑如下的代码:

<?php
1. $val = "laruence";
2. $ref = &$val;
3. $copy = $val;
?>

$ref和$val是指向同一个zval的引用, 在PHP5的时候, 我们是通过一个引用计数为2, 并且引用标志位为1来表示这种情况, 当把$val复制给$copy(line 3)的时候, 我们发现$val是一个计数大于1的引用, 所以要产生Change on write, 也就是分离. 所以我们需要复制这个zval.

而在PHP7中, 情况就变得简单了很多, 首先在引用赋值给$ref(line 2)的时候, 生成一个IS_REFERNCE类型, 然后因为此时有俩个变量引用它所以zend_reference这个结构的引用计数zval.value.ref->gc.refcount为2.

再随后的赋值给$copy(line 3)的时候, 发现$val是一个引用, 于是让$copy指向的是zval.value.ref->val, 也就是字符串值为laruence的zval, 然后把zval的引用计数+1, 也就是zval.value.ref->val.value.str.gc.refcount为2. 并没有产生复制.

从而这就很好的解决了上一章所说的PHP5的那个经典的问题, 比如我们在PHP7下运行上一章的那个问题, 我们得到的结果是:

$ php-7.0/sapi/cli/php /tmp/1.php
Used 0.00021380008539
Used 0.00020173048281

 可见确实没有发生复制, 从而不会产生任何的性能问题.

以上所述是小编给大家介绍的PHP7内核之Reference详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

PHP 相关文章推荐
ajax php 实现写入数据库
Sep 02 PHP
PHP 读取文件内容代码(txt,js等)
Dec 06 PHP
使用PHP求两个文件的相对路径
Jun 20 PHP
修改apache配置文件去除thinkphp url中的index.php
Jan 17 PHP
PHP输出缓存ob系列函数详解
Mar 11 PHP
destoon实现不同会员组公司名称显示不同的颜色的方法
Aug 22 PHP
php几个预定义变量$_SERVER用法小结
Nov 07 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
Nov 11 PHP
如何使用纯PHP实现定时器任务(Timer)
Jul 31 PHP
快速解决PHP调用Word组件DCOM权限的问题
Dec 27 PHP
关于laravel 子查询 &amp; join的使用
Oct 16 PHP
浅谈PHP之ThinkPHP框架使用详解
Jul 21 PHP
掌握PHP垃圾回收机制详解
Mar 13 #PHP
浅谈php的TS和NTS的区别
Mar 13 #PHP
浅谈PHP各环境下的伪静态配置
Mar 13 #PHP
Laravel框架实现的使用smtp发送邮件功能示例
Mar 12 #PHP
Laravel事件监听器用法实例分析
Mar 12 #PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
Mar 12 #PHP
PHP DB 数据库连接类定义与用法示例
Mar 11 #PHP
You might like
php 判断访客是否为搜索引擎蜘蛛的函数代码
2011/07/29 PHP
解析PHP高效率写法(详解原因)
2013/06/20 PHP
php实现的Captcha验证码类实例
2014/09/22 PHP
浅析php如何实现App常用的秒发功能
2016/08/03 PHP
PHP 用session与gd库实现简单验证码生成与验证的类方法
2016/11/15 PHP
ThinkPHP 整合Bootstrap Ajax分页样式
2016/12/23 PHP
自定义Laravel (monolog)日志位置,并增加请求ID的实现
2019/10/17 PHP
JSONP 跨域访问代理API-yahooapis实现代码
2012/12/02 Javascript
JS获取后台Cookies值的小例子
2013/03/04 Javascript
javascript 禁用IE工具栏,导航栏等等实现代码
2013/04/01 Javascript
JS获取html对象的几种方式介绍
2013/12/05 Javascript
jQuery操作CheckBox的方法介绍(选中,取消,取值)
2014/02/04 Javascript
jquery form表单序列化为对象的示例代码
2014/03/05 Javascript
Angularjs编写KindEditor,UEidtor,jQuery指令
2015/01/28 Javascript
js实现类似菜单风格的TAB选项卡效果代码
2015/08/28 Javascript
js获取页面及个元素高度、宽度的代码
2016/04/26 Javascript
Bootstrap modal 多弹窗之叠加关闭阴影遮罩问题的解决方法
2017/02/27 Javascript
AngularJS实现表单验证功能详解
2017/10/12 Javascript
js通过Date对象实现倒计时动画效果
2017/10/27 Javascript
详解JavaScript的BUG和错误
2018/05/07 Javascript
Vux+Axios拦截器增加loading的问题及实现方法
2018/11/08 Javascript
JavaScript 预解析的4种实现方法解析
2019/09/03 Javascript
Node.js中console.log()输出彩色字体的方法示例
2019/12/01 Javascript
python二叉树遍历的实现方法
2013/11/21 Python
python数据类型判断type与isinstance的区别实例解析
2017/10/31 Python
tensorflow TFRecords文件的生成和读取的方法
2018/02/06 Python
Python序列循环移位的3种方法推荐
2018/04/09 Python
Python判断两个list是否是父子集关系的实例
2018/05/04 Python
Python入门Anaconda和Pycharm的安装和配置详解
2019/07/16 Python
Python2和3字符编码的区别知识点整理
2019/08/08 Python
Square Off美国/加拿大:世界上最聪明的国际象棋棋盘
2018/12/06 全球购物
西班牙在线光学:Visual-Click
2020/06/22 全球购物
省文明单位申报材料
2014/05/08 职场文书
教学质量月活动总结
2015/05/11 职场文书
小学大队干部竞选稿
2015/11/20 职场文书
如何利用Matlab制作一款真正的拼图小游戏
2021/05/11 Python