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 CURL模拟GET及POST函数代码
Apr 25 PHP
PHP 强制下载文件代码
Oct 24 PHP
php学习笔记 面向对象的构造与析构方法
Jun 13 PHP
php中获取指定IP的物理地址的代码(正则表达式)
Jun 23 PHP
分享一个php 的异常处理程序
Jun 22 PHP
ThinkPHP自动填充实现无限级分类的方法
Aug 22 PHP
php中字符集转换iconv函数使用总结
Oct 11 PHP
Linux系统下php获得系统分区信息的方法
Mar 30 PHP
PHP中的traits简单使用实例
May 13 PHP
注意!PHP 7中不要做的10件事
Sep 18 PHP
PHP lcfirst()函数定义与用法
Mar 08 PHP
解决laravel session失效的问题
Oct 14 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
WAR3重制版DOTA 5V5初体验
2020/04/09 DOTA
php数组对百万数据进行排除重复数据的实现代码
2010/06/08 PHP
PHP编程最快明白(第一讲 软件环境和准备工作)
2010/10/25 PHP
优化php效率,提高php性能的一些方法
2011/03/24 PHP
Codeigniter里的无刷新上传的实现代码
2019/04/14 PHP
JavaScript事件委托的技术原理探讨示例
2014/04/17 Javascript
jquery实现类似EasyUI的页面布局可改变左右的宽度
2020/09/12 Javascript
javascript的document.referrer浏览器支持、失效情况总结
2014/07/18 Javascript
jQuery+css实现百度百科的页面导航效果
2014/12/16 Javascript
jQuery中filter()方法用法实例
2015/01/06 Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
javascript读取文本节点方法小结
2016/12/15 Javascript
nodejs和C语言插入mysql数据库乱码问题的解决方法
2017/04/14 NodeJs
JavaScript无操作后屏保功能的实现方法
2017/07/04 Javascript
web3.js增加eth.getRawTransactionByHash(txhash)方法步骤
2018/03/15 Javascript
使用Vue.observable()进行状态管理的实例代码详解
2019/05/26 Javascript
node.js 使用 net 模块模拟 websocket 握手进行数据传递操作示例
2020/02/11 Javascript
[02:36]DOTA2亚洲邀请赛小组赛精彩集锦:EE凭借法力虚空拿下4杀
2017/03/30 DOTA
python自动安装pip
2014/04/24 Python
python在windows下实现ping操作并接收返回信息的方法
2015/03/20 Python
Python遍历目录的4种方法实例介绍
2015/04/13 Python
利用Python实现Windows下的鼠标键盘模拟的实例代码
2017/07/13 Python
从CentOS安装完成到生成词云python的实例
2017/12/01 Python
解决Django数据库makemigrations有变化但是migrate时未变动问题
2018/05/30 Python
python导入模块交叉引用的方法
2019/01/19 Python
Python实现字符串匹配的KMP算法
2019/04/04 Python
Python虚拟环境的原理及使用详解
2019/07/02 Python
学python需要去培训机构吗
2020/07/01 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
matplotlib运行时配置(Runtime Configuration,rc)参数rcParams解析
2021/01/05 Python
澳大利亚冒险体验:Adrenaline(跳伞、V8赛车、热气球等)
2017/09/18 全球购物
总裁办公室主任职责
2014/01/02 职场文书
顶岗实习计划书
2015/01/16 职场文书
党支部创先争优公开承诺书
2015/04/30 职场文书
2016年春季开学典礼新闻稿
2015/11/25 职场文书
创业计划之特色精品店
2019/08/12 职场文书