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 相关文章推荐
二十行语句实现从Excel到mysql的转化
Oct 09 PHP
php Smarty 字符比较代码
Feb 27 PHP
用php的ob_start来生成静态页面的方法分析
Mar 09 PHP
PHP数据流应用的一个简单实例
Sep 14 PHP
php批量上传的实现代码
Jun 09 PHP
解决php接收shell返回的结果中文乱码问题
Jan 23 PHP
php构造函数的继承方法
Feb 09 PHP
PHP学习笔记(二):变量详解
Apr 17 PHP
10款PHP开源商城系统汇总介绍
Jul 23 PHP
php使用Header函数,PHP_AUTH_PW和PHP_AUTH_USER做用户验证
May 04 PHP
PHP操作mysql数据库分表的方法
Jun 09 PHP
Yii框架使用魔术方法实现跨文件调用功能示例
May 20 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面向对象的方法重载两种版本比较
2008/09/08 PHP
PHPUnit PHP测试框架安装方法
2011/03/23 PHP
详解PHP执行定时任务的实现思路
2015/12/21 PHP
YII Framework框架教程之国际化实现方法
2016/03/14 PHP
thinkPHP5.0框架命名空间详解
2017/03/18 PHP
PHP编程文件处理类SplFileObject和SplFileInfo用法实例分析
2017/07/22 PHP
CI框架(CodeIgniter)操作redis的方法详解
2018/01/25 PHP
javascript向flash swf文件传递参数值注意细节
2012/12/11 Javascript
AngularJS ng-template寄宿方式用法分析
2016/11/07 Javascript
jquery 获取索引值在一定范围的列表方法
2018/01/25 jQuery
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
JavaScript RegExp 对象用法详解
2019/09/24 Javascript
Javascript异步流程控制之串行执行详解
2020/09/27 Javascript
Python操作Mysql实例代码教程在线版(查询手册)
2013/02/18 Python
python中的实例方法、静态方法、类方法、类变量和实例变量浅析
2014/04/26 Python
Python编程之变量赋值操作实例分析
2017/07/24 Python
Python基于辗转相除法求解最大公约数的方法示例
2018/04/04 Python
对python 合并 累加两个dict的实例详解
2019/01/21 Python
pytorch 实现删除tensor中的指定行列
2020/01/13 Python
tensorflow实现二维平面模拟三维数据教程
2020/02/11 Python
TensorFlow获取加载模型中的全部张量名称代码
2020/02/11 Python
python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧(自定义信号与槽)详解与实例
2020/03/06 Python
Python 读取xml数据,cv2裁剪图片实例
2020/03/10 Python
Django 用户登陆访问限制实例 @login_required
2020/05/13 Python
Vans英国官方网站:美国南加州的原创极限运动潮牌
2017/01/20 全球购物
Shopty西班牙:缝纫机在线销售
2018/01/26 全球购物
Kusmi茶美国官网:优质散叶茶和茶包
2019/10/13 全球购物
意大利比基尼品牌:MISS BIKINI
2019/11/02 全球购物
介绍下Java的输入输出流
2014/01/22 面试题
商场开业庆典策划方案
2014/06/02 职场文书
安全标兵事迹材料
2014/08/17 职场文书
西双版纳导游词
2015/02/03 职场文书
2015新生加入学生会自荐书
2015/03/24 职场文书
springboot layui hutool Excel导入的实现
2022/03/31 Java/Android
MySQL实现字段分割一行转多行的示例代码
2022/07/07 MySQL
搭建zabbix监控以及邮件报警的超级详细教学
2022/07/15 Servers