PHP7内核之Reference详解

 更新时间:2019年03月14日 08:45:31   作者:风雪之隅  
这篇文章主要介绍了PHP7内核之Reference,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

问题

上一章说过引用(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该如何表示呢?

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

 如图所示, 引用是一种新的类型: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脚本来实现WordPress中评论分页的功能

    编写PHP脚本来实现WordPress中评论分页的功能

    这篇文章主要介绍了编写PHP脚本来实现WordPress中评论分页的功能的方法,包括上一页下一页和导航式分页功能的添加,需要的朋友可以参考下
    2015-12-12
  • php导出中文内容excel文件类实例

    php导出中文内容excel文件类实例

    这篇文章主要介绍了php导出中文内容excel文件类,实例分析了php操作带有中文内容的Excel文件及文件导出的实现方法,需要的朋友可以参考下
    2015-07-07
  • PHP实现通过CURL上传文件功能示例

    PHP实现通过CURL上传文件功能示例

    这篇文章主要介绍了PHP实现通过CURL上传文件功能,结合实例形式分析了php使用curl文件上传操作相关属性设置与使用技巧,需要的朋友可以参考下
    2018-05-05
  • PHP之将POST数据转化为字符串的实现代码

    PHP之将POST数据转化为字符串的实现代码

    今天来分享一个方便我们做LOG日志记录的自定义函数,需要将POST数据转化为字符串,需要的朋友可以参考下
    2016-11-11
  • PHP对象、模式与实践之高级特性分析

    PHP对象、模式与实践之高级特性分析

    这篇文章主要介绍了PHP对象、模式与实践之高级特性,结合实例形式分析了php面向对象程序设计中的静态属性和方法、抽象类、接口、拦截器、克隆对象等概念与简单实现方法,需要的朋友可以参考下
    2016-12-12
  • PHP使用OCR技术识别图片中的文字(无需接口)

    PHP使用OCR技术识别图片中的文字(无需接口)

    tesseract-ocr是一个流行的开源OCR引擎库,它使用C++编写, PHP作为一种流行的服务器端语言,也提供了一些ocr识别的库和工具,可以通过tesseract-ocr识别PDF、JPEG、GIF、PNG等格式的图像, tesseract-ocr的最大特点是它是针对多语言设计的,可以识别世界上大部分语言的文本
    2024-04-04
  • php中目录操作opendir()、readdir()及scandir()用法示例

    php中目录操作opendir()、readdir()及scandir()用法示例

    这篇文章主要介绍了php中目录操作opendir()、readdir()及scandir()用法,结合具体实例形式分析了PHP使用opendir()、readdir()及scandir()读取目录的相关操作技巧,需要的朋友可以参考下
    2019-06-06
  • PHP树形结构tree类用法示例

    PHP树形结构tree类用法示例

    这篇文章主要介绍了PHP树形结构tree类用法,结合实例形式分析了php无限分类树tree.class.php的定义及使用相关操作技巧,需要的朋友可以参考下
    2019-02-02
  • php一行代码获取文件后缀名实例分析

    php一行代码获取文件后缀名实例分析

    这篇文章主要介绍了php一行代码获取文件后缀名的方法,以实例形式较为详细的分析了其中涉及的函数和原理,并补充了三种常用的获取文件后缀名的方法,需要的朋友可以参考下
    2014-11-11
  • jquery获取多个checkbox的值异步提交给php的方法

    jquery获取多个checkbox的值异步提交给php的方法

    这篇文章主要介绍了jquery获取多个checkbox的值异步提交给php的方法,涉及jQuery操作页面元素进行异步传输的相关技巧,需要的朋友可以参考下
    2015-06-06

最新评论