PHP7中Reference内核的使用

本文以PHP7中Reference内核为例,为大家分析PHP7中Reference内核的使用方法,阅读完整文相信大家对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该如何表示呢?
为此, 我们创造了这个新的类型:
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采用引用计数来做简单的垃圾回收, 考虑如下的代码:

<?php1. $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.phpUsed 0.00021380008539Used 0.00020173048281

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

关于PHP7中Reference内核的使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

原创文章,作者:BMUMA,如若转载,请注明出处:https://www.wangzhanshi.com/n/6892.html

(0)
BMUMA的头像BMUMA
上一篇 2025年1月1日 16:37:56
下一篇 2025年1月1日 16:37:58

相关推荐

  • PHP7代码加密扩展有什么特点

    介绍 一个简洁、高性能、跨平台的 PHP7 代码加密扩展 特点 简单快速,经实测,几乎不影响性能 兼容 OPcache、Xdebug 等其他扩展 支持 Linux、macOS、Wi…

    php 2025年1月1日
  • 如何在macbook pro中安装php7

    macbook pro怎么安装php7? Mac安装PHP7: 经历了一个漫长的等待,在我们的PHP5.6发布后,我们最新的PHP7终于发布了(等等,我们的6到哪去了?),根据官方…

    php 2025年1月1日
  • php7中有哪些新特性

    1.null合并运算符(??) ??语法: 如果变量存在且值不为NULL,它就会返回自身的值,否则返回它的第二个操作数. //php7以前 if判断 if(empty($_GET[…

    2025年1月1日
  • PHP关键字Self、Static和parent的区别详解

    简介 在使用PHP代码时,您可能经常会遇到parent::、static::和self::。但是当你第一次作为一个开发人员开始的时候,有时候你会很困惑,不知道它们是做什么的,以及它…

    php 2025年2月24日
  • PHP内存溢出的原因和解决方案

    前言 PHP作为一种广泛使用的服务器端脚本语言,常常用于处理动态内容和构建Web应用程序。然而,在开发和执行PHP代码时,开发者常常会面临一些常见的问题之一—&mdas…

    php 2024年12月17日
  • 如何实现可兼容php5与php7的cURL文件上传功能

    具体如下: 为啥要写这个示例 最近修改一个项目,需要通过cURL上传文件。 记得之前做过类似实现的,于是翻出来之前的代码,使用的是“@”前缀方式。 但同样的方法现在不行了!后来发现…

    php 2025年1月1日
  • 基于PHP封装图片裁剪工具类

    PHP工具类图片裁剪类封装 <?php namespace App\Utils; /** * 图片裁剪工具类 * @author 田小涛 * @date 2020年7月23日…

    php 2024年12月17日
  • yum安装php7版本的步骤

    Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。基于RPM包管理,能够从…

    2025年1月1日
  • ThinkPHP中使用ajax接收json数据的方法

    引言 在ThinkPHP框架中,使用AJAX接收JSON数据通常涉及前端和后端的交互。前端通过AJAX发送JSON数据到后端,后端控制器接收并处理这些数据,然后可能返回一些响应数据…

    php 2024年12月17日
  • 如何对php7进行性能优化

    PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想…

    php 2025年1月1日

发表回复

登录后才能评论