加入收藏 | 设为首页 | 会员中心 | 我要投稿 西双版纳站长网 (https://www.0691zz.com.cn/)- 数据计算、IT业界、服务器、教程、云日志!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

深入讲解PHP垃圾回收及内存管理相关内容

发布时间:2022-08-11 12:05:38 所属栏目:PHP教程 来源:互联网
导读:PHP 垃圾回收与内存管理指引 本文将要讲述 PHP 发展历程中的垃圾回收及内存管理相关内容。 引用计数 在 PHP 5.2 及以前的版本中,PHP 的垃圾回收采用的是 引用计数 算法。 引用计数基础知识 引用计数基础知识 php 的变量存储在「zval」变量容器(数据结构)
  PHP 垃圾回收与内存管理指引
  本文将要讲述 PHP 发展历程中的垃圾回收及内存管理相关内容。
 
  引用计数
  在 PHP 5.2 及以前的版本中,PHP 的垃圾回收采用的是 引用计数 算法。
 
  引用计数基础知识
  引用计数基础知识
 
  php 的变量存储在「zval」变量容器(数据结构)中,「zval」属性包含如下信息:
 
  当前变量的数据类型;
  当前变量的值;
  用于标识变量是否为引用传递的 is_ref 布尔类型标识;
  指向该「zval」变量容器的变量个数的 refcount 标识符(即这个 zval 被引用的次数,注意这里的引用不是指引用传值,注意区分)。
  当一个变量被赋值时,就会生成一个对应的「zavl」变量容器。【推荐学习:PHP视频教程】
 
  查看变量 zval 容器信息
  要查看变量的「zval」容器信息(即查看变量的 is_ref 和 refcount),可以使用 XDebug 调试工具的 xdebug_debug_zval() 函数。
 
  安装 XDebug 扩展插件的方法可以查看 这个教程(https://github.com/huliuqing/phpnotes/issues/58),有关XDebug 使用方法请阅读 官方文档(https://xdebug.org/docs/)。
 
  假设,我们已经成功安装好 XDebug 工具,现在就可以来对变量进行调试了。
 
  查看普通变量的 zval 信息
  如果我们的 PHP 语句只是对变量进行简单赋值时,is_ref 标识值为 0,refcount 值为 1;若将这个变量作为值赋值给另一个变量时,则增加 zval 变量容器的 refcount 计数;同理,销毁(unset)变量时,「refcount」相应的减去 1。
 
  请看下面的示例:
 
 
 
  <?php
 
  // 变量赋值时,refcount 值等于 1
 
  $name = 'liugongzi';
 
  xdebug_debug_zval('name'); // (refcount=1, is_ref=0)string 'liugongzi' (length=9)
 
   
 
  // $name 作为值赋值给另一个变量, refcount 值增加 1
 
  $copy = $name;
 
  xdebug_debug_zval('name'); // (refcount=2, is_ref=0)string 'liugongzi' (length=9)
 
   
 
  // 销毁变量,refcount 值减掉 1
 
  unset($copy);
 
  xdebug_debug_zval('name'); // (refcount=1, is_ref=0)string 'liugongzi' (length=9)
 
  写时复制
  写时复制(Copy On Write:COW),简单描述为:如果通过赋值的方式赋值给变量时不会申请新内存来存放新变量所保存的值,而是简单的通过一个计数器来共用内存,只有在其中的一个引用指向变量的值发生变化时,才申请新空间来保存值内容以减少对内存的占用。 - TPIP 写时复制
  通过前面的简单变量的 zval 信息我们知道 $copy 和 $name 共用 zval 变量容器(内存),然后通过 refcount 来表示当前这个 zval 被多少个变量使用。
 
  看个实例:
 
 
 
 
  <?php
 
  $name = 'liugongzi';
 
  xdebug_debug_zval('name'); // name: (refcount=1, is_ref=0)string 'liugongzi' (length=9)
 
   
 
  $copy = $name;
 
  xdebug_debug_zval('name'); // name: (refcount=2, is_ref=0)string 'liugongzi' (length=9)
 
   
 
  // 将新的值赋值给变量 $copy
 
  $copy = 'liugongzi handsome';
 
  xdebug_debug_zval('name'); // name: (refcount=1, is_ref=0)string 'liugongzi' (length=9)
 
  xdebug_debug_zval('copy'); // copy: (refcount=1, is_ref=0)='liugongzi handsome'
 
  注意到没有,当将值 liugongzi handsome 赋值给变量 $copy 时,name 和 copy 的 refcount 值都变成了 1,在这个过程中发生以下几个操作:
 
  将 $copy 从 $name 的 zval(内从)中分离出来(即复制);
  将 $name 的 refcount 减去 1;
  对 $copy 的 zval 进行修改(重新赋值和修改 refcount);
  这里只是简单对「写时复制」进行介绍,感兴趣的朋友可以阅读文末给出的参考资料进行更加深入的研究。
 
  查看引用传递变量的 zval 信息
  引用传值(&)的「引用计数」规则同普通赋值语句一样,只是 is_ref 标识的值为 1 表示该变量是引用传值类型。

(编辑:西双版纳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读