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实现多级树型菜单
Oct 09 PHP
php下MYSQL limit的优化
Jan 10 PHP
PHP中通过HTTP_USER_AGENT判断是否为手机移动终端的函数代码
Feb 14 PHP
PHP编程风格规范分享
Jan 15 PHP
php中http与https跨域共享session的解决方法
Dec 20 PHP
php获取文件后缀的9种方法
Mar 22 PHP
php的api数据接口书写实例(推荐)
Sep 22 PHP
浅谈PHP中静态方法和非静态方法的相互调用
Oct 04 PHP
thinkPHP引入类的方法详解
Dec 08 PHP
PHP 传输会话curl函数的实例详解
Sep 12 PHP
YII分模块加载路由的实现方法
Oct 01 PHP
laravel5.6中的外键约束示例
Oct 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
很温暖很温暖的Lester Young
2021/03/03 冲泡冲煮
利用php获取服务器时间的实现代码
2013/06/07 PHP
解析mysql 表中的碎片产生原因以及清理
2013/06/22 PHP
set_exception_handler函数在ThinkPHP中的用法
2014/10/31 PHP
ThinkPHP框架设计及扩展详解
2014/11/25 PHP
ThinkPHP表单令牌错误的相关解决方法分析
2016/05/20 PHP
基于PHPexecl类生成复杂的报表表头示例
2016/10/14 PHP
jQuery toggle()设置CSS样式
2009/11/05 Javascript
让checkbox不选中即将选中的checkbox不选中
2014/07/11 Javascript
jQuery动态修改超链接地址的方法
2015/02/13 Javascript
纯js实现重发验证码按钮倒数功能
2015/04/21 Javascript
基于jquery实现的树形菜单效果代码
2015/09/06 Javascript
jQuery选择器用法实例详解
2015/12/17 Javascript
js实现图片无缝滚动
2015/12/23 Javascript
阻止表单提交按钮多次提交的完美解决方法
2016/05/16 Javascript
基于Bootstrap里面的Button dropdown打造自定义select
2016/05/30 Javascript
关于javascript原型的修改与重写(覆盖)差别详解
2016/08/31 Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
2017/06/22 Javascript
jQuery动态添加元素无法触发绑定事件的解决方法分析
2018/01/02 jQuery
解决Vue打包后访问图片/图标不显示的问题
2019/07/25 Javascript
微信浏览器左上角返回按钮监听的实现
2020/03/04 Javascript
Python中实现对list做减法操作介绍
2015/01/09 Python
python批量创建指定名称的文件夹
2019/03/21 Python
解决python 读取excel时 日期变成数字并加.0的问题
2019/10/08 Python
如何使用python socket模块实现简单的文件下载
2020/09/04 Python
Canvas实现保存图片到本地的示例代码
2018/06/28 HTML / CSS
Corelle官方网站:购买康宁餐具
2016/11/02 全球购物
Omio荷兰:预订火车、巴士和机票
2018/11/04 全球购物
RealTek面试题
2016/06/28 面试题
物业管理员岗位职责范文
2013/11/25 职场文书
党员自我评价分享
2013/12/13 职场文书
乡镇干部先进性教育活动个人整改措施
2014/09/16 职场文书
广播稿:校园广播稿范文
2019/04/17 职场文书
html5表单的required属性使用
2021/07/07 HTML / CSS
德劲DE1107指针试高灵敏度全波段收音机机评
2022/04/05 无线电
Win11 vmware不兼容怎么办?Win11与VMware虚拟机不兼容的解决方法
2023/01/09 数码科技