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 相关文章推荐
PHP 和 MySQL 基础教程(二)
Oct 09 PHP
PHP自动选择 连接本地还是远程数据库
Dec 02 PHP
php中一个完整表单处理实现代码
Nov 10 PHP
如何使用Linux的Crontab定时执行PHP脚本的方法
Dec 19 PHP
使用php判断服务器是否支持Gzip压缩功能
Sep 24 PHP
老版本PHP转义Json里的特殊字符的函数
Jun 08 PHP
详解HTTP Cookie状态管理机制
Jan 14 PHP
PHP的压缩函数实现:gzencode、gzdeflate和gzcompress的区别
Jan 27 PHP
php文件操作小结(删除指定文件/获取文件夹下的文件名/读取文件夹下图片名)
May 09 PHP
php遍历、读取文件夹中图片并分页显示图片的方法
Nov 15 PHP
PHP如何防止XSS攻击与XSS攻击原理的讲解
Mar 22 PHP
ThinkPHP5与单元测试PHPUnit使用详解
Feb 23 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将fileterms函数返回的结果变成可读的形式
2011/04/21 PHP
初学PHP的朋友 经常问的一些问题。不断更新
2011/08/11 PHP
PHP取整数函数常用的四种方法小结
2012/07/05 PHP
php中如何防止表单的重复提交
2013/08/02 PHP
php数组使用规则分析
2015/02/27 PHP
php批量删除超链接的实现方法
2015/10/19 PHP
Zend Framework框架路由机制代码分析
2016/03/22 PHP
PHP设计模式(八)装饰器模式Decorator实例详解【结构型】
2020/05/02 PHP
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
分享一个自己写的table表格排序js插件(高效简洁)
2011/10/29 Javascript
JS 实现Table相同行的单元格自动合并示例代码
2013/08/27 Javascript
js+html5实现canvas绘制镂空字体文本的方法
2015/06/05 Javascript
向JavaScript的数组中添加元素的方法小结
2015/10/24 Javascript
jQuery实现判断控件是否显示的方法
2017/01/11 Javascript
JavaScript实现自动跳转文本功能
2017/05/25 Javascript
Vue+webpack项目基础配置教程
2018/02/12 Javascript
JS实现的DOM插入节点操作示例
2018/04/04 Javascript
vue实现一个炫酷的日历组件
2018/10/08 Javascript
原生JS实现无缝轮播图片
2020/06/24 Javascript
react项目从新建到部署的实现示例
2021/02/19 Javascript
[06:11]2014DOTA2国际邀请赛 专访团结一心的VG战队
2014/07/21 DOTA
[54:15]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第二场2月1日
2021/03/11 DOTA
详解Python中的各种函数的使用
2015/05/24 Python
Python中tell()方法的使用详解
2015/05/24 Python
分享python数据统计的一些小技巧
2016/07/21 Python
Python模拟鼠标点击实现方法(将通过实例自动化模拟在360浏览器中自动搜索python)
2017/08/23 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
2017/11/09 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
日本热销NO.1胶原蛋白冻:Aishitoto爱希特多
2019/06/20 全球购物
一套带网友答案的.NET笔试题
2016/12/06 面试题
飘柔洗发水广告词
2014/03/14 职场文书
《四季》教学反思
2014/04/08 职场文书
岗位竞聘演讲稿范文
2014/04/24 职场文书
英文慰问信范文
2015/03/24 职场文书
2016中秋晚会开幕词
2016/03/03 职场文书
Linux磁盘管理方法介绍
2022/06/01 Servers