PHP的垃圾回收机制代码实例讲解


Posted in PHP onFebruary 27, 2021

PHP可以自动进行内存管理,清除不需要的对象,主要使用了引用计数

zval结构体中定义了ref_countis_ref , ref_count是引用计数 ,标识此zval被多少个变量引用 , 为0时会被销毁
is_ref标识是否使用的 &取地址符强制引用

为了解决循环引用内存泄露问题 , 使用同步周期回收算法
比如当数组或对象循环的引用自身 , unset掉数组的时候 , 当refcount-1后还大于0的 , 就会被当成疑似垃圾 , 会进行遍历 ,并且模拟的删除一次refcount-1如果是0就删除 ,如果不是0就恢复

顽固垃圾的产生过程

<?php
  $a = "new string";
?>

代码中,$a变量内部存储信息为

a: (refcount_gc=1, is_ref_gc=0)='new string'

当把 a 赋 值 给 另 外 一 个 变 量 的 时 候 , a赋值给另外一个变量的时候, a赋值给另外一个变量的时候,a对应的zval的refcount_gc会加1

<?php
  $a = "new string";
  $b = $a;
?>

此时 a 和 a和 a和b变量对应的内部存储信息为, a 和 a和 a和b同时指向一个字符串"new string" ,它的refcount变成2

a,b: (refcount_gc=2, is_ref=0)='new string'

当用unset删除$b变量时,“new string” 的refcount_gc会减1变成1。

<?php
  $a = "new string"; //a: (refcount_gc=1, is_ref_gc=0)='new string'
  $b = $a;      //a,b: (refcount_gc=2, is_ref=0)='new string'
  unset($b);     //a: (refcount_gc=1, is_ref=0)='new string'
?>

对于普通的变量来说,这一切很正常,但是在复合类型变量(数组和对象)中,会发生比较有意思的事情:

<?php
  $a = array('meaning' => 'life', 'number' => 42);
?>

$a内部存储信息为:

a: (refcount=1, is_ref=0)=array (
'meaning' => (refcount=1, is_ref=0)='life',
'number' => (refcount=1, is_ref=0)=42
)

数组变量本身($a)在引擎内部实际上是一个哈希表,这张表中有两个zval项 meaning和number,所以实际上那一行代码中一共生成了3个zval,这3个zval都遵循变量的引用和计数原则,用图来表示:
PHP的垃圾回收机制代码实例讲解

下面在$a中添加一个元素,并将现有的一个元素的值赋给新的元素:

<?php
  $a = array('meaning' => 'life', 'number' => 42);
  $a['name'] = $a['meaning'];
?>

那么$a的内部存储为 , “life” 的ref_count变成2 , 42的ref_count是1:

a: (refcount=1, is_ref=0)=array (
'meaning' => (refcount=2, is_ref=0)='life',
'number' => (refcount=1, is_ref=0)=42,
'name' => (refcount=2, is_ref=0)='life'
)

如果将数组的引用赋值给数组中的一个元素,有意思的事情就会发生:

<?php
  $a = array('one');
  $a[] = &$a;
?>

这样 a 数 组 就 有 两 个 元 素 , 一 个 索 引 为 0 , 值 为 字 符 o n e , 另 外 一 个 索 引 为 1 , 为 a数组就有两个元素,一个索引为0,值为字符one,另外一个索引为1,为 a数组就有两个元素,一个索引为0,值为字符one,另外一个索引为1,为a自身的引用,内部存储如下:
PHP的垃圾回收机制代码实例讲解

a: (refcount=2, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=2, is_ref=1)=…
)

array这个zvalref_count是2 , 是一个环形引用
这时对$a进行unset,那么 a 会 从 符 号 表 中 删 除 , 同 时 ‘ a会从符号表中删除,同时` a会从符号表中删除,同时‘a指向的zvalrefcount_gc`减少1.

<?php
$a = array('one');
$a[] = &$a;
unset($a);
?>

那么问题就产生了, a 已 经 不 在 符 号 表 中 , 用 户 无 法 再 访 问 此 变 量 , 但 是 a已经不在符号表中,用户无法再访问此变量,但是 a已经不在符号表中,用户无法再访问此变量,但是a之前指向的zval的refcount_gc变为1而不是0,因此不能被回收,从而产生内存泄露,新的GC要做的工作就是清理此类垃圾。

为了解决循环引用内存泄露问题 , 使用同步周期回收算法 , 这种ref_count减1后还大于0的会被作为疑似垃圾

比如当数组或对象循环的引用自身 , unset掉数组的时候 , 当refcount-1后还大于0的 , 会进行遍历 ,并且模拟的删除一次refcount-1如果是0就删除 ,如果不是0就恢复。

到此这篇关于PHP的垃圾回收机制代码实例讲解的文章就介绍到这了,更多相关PHP的垃圾回收机制内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
模仿OSO的论坛(五)
Oct 09 PHP
PHP 多进程 解决难题
Jun 22 PHP
php中怎么搜索相关联数组键值及获取之
Oct 17 PHP
kohana框架上传文件验证规则写法示例
Jul 14 PHP
php中的mongodb select常用操作代码示例
Sep 06 PHP
PHP中大于2038年时间戳的问题处理方案
Mar 03 PHP
php简单socket服务器客户端代码实例
May 18 PHP
PHP 在数组中搜索给定的简单实例 array_search 函数
Jun 13 PHP
php 输出json及显示json中的中文汉字详解及实例
Nov 09 PHP
Yii2――使用数据库操作汇总(增删查改、事务)
Dec 19 PHP
关于PHP5.6+版本“No input file specified”问题的解决
Dec 11 PHP
基于php伪静态的实现方法解析
Jul 31 PHP
php命令行模式代码实例详解
Feb 26 #PHP
PHP时间类完整代码实例
Feb 26 #PHP
PHP队列场景以及实现代码实例详解
Feb 26 #PHP
PHP实现长轮询消息实时推送功能代码实例讲解
Feb 26 #PHP
php的对象传值与引用传值代码实例讲解
Feb 26 #PHP
php并发加锁问题分析与设计代码实例讲解
Feb 26 #PHP
PHP内存溢出优化代码详解
Feb 26 #PHP
You might like
PHP获取当前文件所在目录 getcwd()函数
2009/05/13 PHP
php 生成唯一id的几种解决方法
2013/03/08 PHP
PHP随机字符串生成代码(包括大小写字母)
2013/06/24 PHP
PHP间隔一段时间执行代码的方法
2014/12/02 PHP
js停止输出代码
2008/07/20 Javascript
javascript 特殊字符串
2009/02/25 Javascript
JS获取地址栏参数的小例子
2013/08/23 Javascript
getJSON调用后台json数据时函数被调用两次的原因猜想
2013/09/29 Javascript
javascript数字时钟示例分享
2014/04/23 Javascript
c#+jquery实现获取radio和checkbox的值
2020/09/12 Javascript
原生Ajax 和jQuery Ajax的区别示例分析
2014/12/17 Javascript
Javascript实现商品秒杀倒计时(时间与服务器时间同步)
2015/09/16 Javascript
JS加载iFrame出现空白问题的解决办法
2016/05/13 Javascript
JS正则替换掉小括号及内容的方法
2016/11/29 Javascript
js原生之焦点图转换加定时器实例
2016/12/12 Javascript
nodejs创建简易web服务器与文件读写的实例
2017/09/07 NodeJs
vue实现自定义多选与单选的答题功能
2018/07/05 Javascript
JavaScript实现创建自定义对象的常用方式总结
2018/07/09 Javascript
vue设置默认首页的操作
2020/08/12 Javascript
JavaScript 绘制饼图的示例
2021/02/19 Javascript
python对html代码进行escape编码的方法
2015/05/04 Python
python同时遍历数组的索引和值的实例
2018/11/15 Python
基于matplotlib xticks用法详解
2020/04/16 Python
使用scrapy ImagesPipeline爬取图片资源的示例代码
2020/09/28 Python
快速创建python 虚拟环境
2020/11/28 Python
使用CSS3 制作一个material-design 风格登录界面实例
2016/12/12 HTML / CSS
HTML5中使用postMessage实现Ajax跨域请求的方法
2016/04/19 HTML / CSS
伯利陶器:Burleigh Pottery
2018/01/03 全球购物
市场营销专科应届生求职信
2013/11/24 职场文书
农场厂长岗位职责
2013/12/28 职场文书
初三政治教学反思
2014/01/30 职场文书
公务员更新知识培训实施方案
2014/03/31 职场文书
项目工作说明书
2014/07/29 职场文书
教师节随笔
2015/08/15 职场文书
大学三好学生主要事迹范文
2015/11/03 职场文书
《灰雀》教学反思
2016/02/19 职场文书