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 相关文章推荐
BBS(php &amp; mysql)完整版(一)
Oct 09 PHP
PHP静态类
Nov 25 PHP
PHP MYSQL乱码问题,使用SET NAMES utf8校正
Nov 30 PHP
PHP生成自定义长度随机字符串的函数分享
May 04 PHP
ThinkPHP3.2.2的插件控制器功能简述
Jul 09 PHP
PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码
Mar 25 PHP
PHP实现多关键字加亮功能
Oct 21 PHP
php 实现一个字符串加密解密的函数实例代码
Nov 01 PHP
php 函数使用可变数量的参数方法
May 02 PHP
PHP+MySQL实现消息队列的方法分析
May 09 PHP
Yaf框架封装的MySQL数据库操作示例
Mar 06 PHP
laravel框架模型、视图与控制器简单操作示例
Oct 10 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
mac下使用brew配置环境的步骤分享
2011/05/23 PHP
PHP 下载文件时自动添加bom头的方法实例
2014/01/10 PHP
PHP使用递归方式列出当前目录下所有文件的方法
2015/06/02 PHP
php商品对比功能代码分享
2015/09/24 PHP
php传值方式和ajax的验证功能
2017/03/27 PHP
PHP实现断点续传乱序合并文件的方法
2018/09/06 PHP
jQuery与ExtJS之选择实例分析
2010/08/19 Javascript
window.location.hash 使用说明
2010/11/08 Javascript
jQuery 追加元素的方法如append、prepend、before
2014/01/16 Javascript
jquery获取html元素的绝对位置和相对位置的方法
2014/06/20 Javascript
JavaScript参数个数可变的函数举例说明
2014/10/10 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
2015/11/22 Javascript
js验证框架实现代码分享
2016/05/18 Javascript
浅谈jQuery中Ajax事件beforesend及各参数含义
2016/12/03 Javascript
js实现自动图片轮播代码
2017/03/22 Javascript
JavaScript中数组常见操作技巧
2017/09/01 Javascript
如何获取TypeScript的声明文件.d.ts
2018/05/01 Javascript
简述vue-cli中chainWebpack的使用方法
2019/07/30 Javascript
原生JavaScript实现滑动拖动验证的示例代码
2019/12/06 Javascript
如何利用 JS 脚本实现网页全自动秒杀抢购功能
2020/10/12 Javascript
Python实现获取本地及远程图片大小的方法示例
2018/07/21 Python
用pycharm开发django项目示例代码
2018/10/24 Python
python卸载后再次安装遇到的问题解决
2019/07/10 Python
详解Django定时任务模块设计与实践
2019/07/24 Python
python使用梯度下降算法实现一个多线性回归
2020/03/24 Python
Python如何用wx模块创建文本编辑器
2020/06/07 Python
java字符串格式化输出实例讲解
2021/01/06 Python
CSS3控制HTML元素动画效果
2014/02/08 HTML / CSS
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
英国天然宝石首饰购买网站:Gemondo Jewellery
2018/10/23 全球购物
屈臣氏泰国官网:Watsons TH
2021/02/23 全球购物
专科应届生求职信
2013/11/24 职场文书
违纪检讨书2000字
2014/02/08 职场文书
乡村卫生服务一体化管理实施方案
2014/03/30 职场文书
装修施工安全责任书
2014/07/24 职场文书
紧急迫降观后感
2015/06/15 职场文书