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 抓取网页图片并且另存为的实现代码
Mar 24 PHP
Smarty的配置与高级缓存技术分享
Jun 05 PHP
gd库图片下载类实现下载网页所有图片的php代码
Aug 20 PHP
基于ubuntu下nginx+php+mysql安装配置的具体操作步骤
Apr 28 PHP
phpinfo() 中 Local Value(局部变量)Master Value(主变量) 的区别
Feb 03 PHP
Yii2.0预定义的别名功能小结
Jul 04 PHP
php生成无限栏目树
Mar 16 PHP
PHP基于自增数据如何生成不重复的随机数示例
May 19 PHP
PHP开发中解决并发问题的几种实现方法分析
Nov 13 PHP
PHP开发之用微信远程遥控服务器
Jan 25 PHP
PHP重置数组为连续数字索引的几种方式总结
Mar 12 PHP
PHP实现对数字分隔加千分号的方法
Mar 18 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自动获取目录下的模板的代码
2010/08/08 PHP
PHP Session_Regenerate_ID函数双释放内存破坏漏洞
2011/01/27 PHP
php define的第二个参数使用方法
2013/11/04 PHP
浅谈discuz密码加密的方式
2014/05/22 PHP
PHP magento后台无法登录问题解决方法
2016/11/24 PHP
js兼容标准的表格变色效果
2008/06/28 Javascript
jquery 实现窗口的最大化不论什么情况
2013/09/03 Javascript
JavaScript移除数组元素减少长度的方法
2013/09/05 Javascript
利用JQuery和Servlet实现跨域提交请求示例分享
2014/02/12 Javascript
js中把JSON字符串转换成JSON对象最好的方法
2014/03/21 Javascript
浅谈setTimeout 与 setInterval
2015/06/23 Javascript
实例详解jQuery Mockjax 插件模拟 Ajax 请求
2016/01/12 Javascript
郁闷!ionic中获取ng-model绑定的值为undefined如何解决
2016/08/27 Javascript
深入理解vue Render函数
2017/07/19 Javascript
JavaScript基础之静态方法和实例方法分析
2018/12/26 Javascript
基于Vue el-autocomplete 实现类似百度搜索框功能
2019/10/25 Javascript
VUE Elemen-ui之穿梭框使用方法详解
2021/01/19 Javascript
[00:48]完美“圣”典2016风云人物:xiao8宣传片
2016/11/30 DOTA
python字符串,数值计算
2016/10/05 Python
python使用pyqt写带界面工具的示例代码
2017/10/23 Python
Go/Python/Erlang编程语言对比分析及示例代码
2018/04/23 Python
pycharm运行和调试不显示结果的解决方法
2018/11/30 Python
Python转换字典成为对象,可以用&quot;.&quot;方式访问对象属性实例
2020/05/11 Python
Selenium元素定位的30种方式(史上最全)
2020/05/11 Python
keras:model.compile损失函数的用法
2020/07/01 Python
Python迭代器协议及for循环工作机制详解
2020/07/14 Python
python爬虫构建代理ip池抓取数据库的示例代码
2020/09/22 Python
canvas离屏技术与放大镜实现代码示例
2018/08/31 HTML / CSS
珍珠鸟教学反思
2014/02/01 职场文书
工商管理专业大学生职业生涯规划范文
2014/03/09 职场文书
幼儿园毕业典礼主持词
2014/03/21 职场文书
实习评语大全
2014/04/26 职场文书
伦敦奥运会口号
2014/06/13 职场文书
教师党员先进性教育自我剖析材料思想汇报
2014/09/24 职场文书
党员评议表自我评价范文
2014/10/20 职场文书
结婚保证书(卖身契)
2015/02/26 职场文书