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 相关文章推荐
用sql命令修改数据表中的一个字段为非空(not null)的语句
Jun 04 PHP
php递归实现无限分类生成下拉列表的函数
Aug 08 PHP
php中判断字符串是否全是中文或含有中文的实现代码
Sep 16 PHP
php fsockopen解决办法 php实现多线程
Jan 20 PHP
php校验表单检测字段是否为空的方法
Mar 20 PHP
学习php设计模式 php实现合成模式(composite)
Dec 08 PHP
CI框架整合widget(页面格局)的方法
May 17 PHP
PHP设计模式之工厂模式与单例模式
Sep 28 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
Nov 14 PHP
ThinkPHP 3使用OSS的方法
Jul 19 PHP
php使用curl_init()和curl_multi_init()多线程的速度比较详解
Aug 15 PHP
laravel 获取某个查询的查询SQL语句方法
Oct 12 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判断变量类型常用方法
2012/04/24 PHP
php 不使用js实现页面跳转
2014/02/11 PHP
Smarty模板常见的简单应用分析
2016/11/15 PHP
php-msf源码详解
2017/12/25 PHP
PHP标准库(PHP SPL)详解
2019/03/16 PHP
在一个js文件里远程调用jquery.js会在ie8下的一个奇怪问题
2010/11/28 Javascript
js substr支持中文截取函数代码(中文是双字节)
2013/04/17 Javascript
js function定义函数的几种不错方法
2014/02/27 Javascript
jQuery学习笔记之 Ajax操作篇(二) - 数据传递
2014/06/23 Javascript
js实现DOM走马灯特效的方法
2015/01/21 Javascript
基于javascript实现右下角浮动广告效果
2016/01/08 Javascript
vue-cli创建的项目,配置多页面的实现方法
2018/03/15 Javascript
vue项目首屏加载时间优化实战
2019/04/23 Javascript
Vue 动态添加路由及生成菜单的方法示例
2019/06/20 Javascript
让 babel webpack vue 配置文件支持智能提示的方法
2019/06/22 Javascript
jquery实现下载图片功能
2019/07/18 jQuery
vue Treeselect 树形下拉框:获取选中节点的ids和lables操作
2020/08/15 Javascript
JavaScript Dom实现轮播图原理和实例
2021/02/19 Javascript
Pycharm之快速定位到某行快捷键的方法
2019/01/20 Python
python给微信好友定时推送消息的示例
2019/02/20 Python
python监控nginx端口和进程状态
2019/09/06 Python
python数值基础知识浅析
2019/11/19 Python
python 解决mysql where in 对列表(list,,array)问题
2020/06/06 Python
Python中return函数返回值实例用法
2020/11/19 Python
canvas实现圆绘制的示例代码
2019/09/11 HTML / CSS
贝玲妃美国官方网站:Benefit美国
2016/08/28 全球购物
大学生入党思想汇报
2014/01/14 职场文书
承认错误的检讨书
2014/01/30 职场文书
培训主管的职业生涯规划
2014/03/06 职场文书
2014年作风建设工作总结
2014/10/29 职场文书
2014小学教师个人工作总结
2014/11/10 职场文书
校长一岗双责责任书
2015/05/09 职场文书
孟佩杰观后感
2015/06/17 职场文书
人民调解协议书
2016/03/21 职场文书
字节飞书面试promise.all实现示例
2022/06/16 Javascript
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
2022/08/05 Vue.js