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 相关文章推荐
PHPMyadmin 配置文件详解(配置)
Dec 03 PHP
php数组的概述及分类与声明代码演示
Feb 26 PHP
php smarty模板引擎的6个小技巧
Apr 24 PHP
thinkphp获取栏目和文章当前位置的方法
Oct 29 PHP
php在apache环境下实现gzip配置方法
Apr 02 PHP
php使用MySQL保存session会话的方法
Jun 18 PHP
php图片添加文字水印实现代码
Mar 15 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
PHP simplexml_load_string()函数实例讲解
Feb 03 PHP
Laravel如何创建服务器提供者实例代码
Apr 15 PHP
php创建类并调用的实例方法
Sep 25 PHP
php redis setnx分布式锁简单原理解析
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
PHP 编程请选择正确的文本编辑软件
2006/12/21 PHP
PHP5.2下chunk_split()函数整数溢出漏洞 分析
2007/06/06 PHP
显示程序执行时间php函数代码
2013/08/29 PHP
生成随机字符串和验证码的类的PHP实例
2013/12/24 PHP
Zend Framework页面缓存实例
2014/06/25 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
2016/02/15 PHP
CSS3画一个阴阳八卦图
2021/03/09 HTML / CSS
javascript 树控件 比较好用
2009/06/11 Javascript
一些常用的JavaScript函数(json)附详细说明
2011/05/25 Javascript
jQuery1.6 使用方法一
2011/11/23 Javascript
JS的replace方法介绍
2012/10/20 Javascript
node.js入门教程迷你书、node.js入门web应用开发完全示例
2014/04/06 Javascript
node.js中的fs.mkdirSync方法使用说明
2014/12/17 Javascript
javascript设置文本框光标的方法实例小结
2016/11/04 Javascript
javascript中new Array()和var arr=[]用法区别
2017/12/01 Javascript
web前端vue之CSS过渡效果示例
2018/01/10 Javascript
jQuery动态移除与增加onclick属性的方法详解
2018/06/07 jQuery
详解Vue.directive 自定义指令
2019/03/27 Javascript
Vue项目服务器部署之子目录部署方法
2019/05/12 Javascript
JS中的算法与数据结构之字典(Dictionary)实例详解
2019/08/20 Javascript
jquery获取input输入框中的值
2019/11/13 jQuery
python在windows下实现备份程序实例
2014/07/04 Python
Python计算回文数的方法
2015/03/11 Python
浅析python实现scrapy定时执行爬虫
2018/03/04 Python
python实现搜索文本文件内容脚本
2018/06/22 Python
python os模块简单应用示例
2019/05/23 Python
opencv导入头文件时报错#include的解决方法
2019/07/31 Python
在Python中利用pickle保存变量的实例
2019/12/30 Python
python集合的新增元素方法整理
2020/12/07 Python
python安装mysql的依赖包mysql-python操作
2021/01/01 Python
会计学个人自荐信模板
2013/12/13 职场文书
营销总经理岗位职责
2014/02/02 职场文书
美容院营销方案
2014/03/05 职场文书
爸爸的三轮车观后感
2015/06/16 职场文书
Springboot配置suffix指定mvc视图的后缀方法
2021/07/03 Java/Android
漫画「狩龙人拉格纳」公开TV动画预告图
2022/03/22 日漫