PHP垃圾回收机制

简述 php垃圾回收机制

对于一个PHPer 来说,程序运行时出现内存益出可谓是见多不怪的,从而想到的解决方法无非是以下几点:

1, 设置脚本运行内存大小,
2, 脚本运行时间等,  

但, 最终这些都只能解决表面问题甚至更改过配可能还后导致内存益出。 那我们接下来就了解一下为何会导致溢出

1,循环嵌套(死循环, 套娃式循环)
2,恶性递归
3,多个Array或object 引用变量,导致内存泄漏

分析导致上述问题的原因

造成问题1,2略过,自行检查代码问题,至于问题3我们首先了解下php的垃圾回收机制。
php 5.3版本前是用应用计数的方式来进行垃圾回收,建议大家安装php的xdebug扩展,这样可以更清楚的了解。
	述语普及
	refcount	--	**引用计数**的次数
	is_ref(booler)	---	布尔类型, php用来区分是否为引用变量的标识
	interned	---	当 字符, 数字, booler不进行引用次数占用
	简单类型的探讨 (string|int|booler)
	e g,1  赋值变量
	$a = "how are you ?"
	xdebug_debug_zval('a');
	结果为
	a: (refcount=1, is_ref=0)='how are you ?'
	
	e g,2 引用赋值
	$b = &$a
	xdebug_debug_zval('a', 'b');
	a: (refcount=2, is_ref=1)='how are you ?'
	b: (refcount=2, is_ref=1)='how are you ?'
	此处: $b引用$a php内部标识为共享内存则引用次数+1, 更改引用变量状态

	e g,3 销毁引用变量中的任意一个变量
	unset($a)
	xdebug_debug_zval('b');
	b: (refcount=1, is_ref=1)='how are you ?'

	负责类型探讨 (array|object)
	e g,4 
	$a[] = 'aaa'
	$a[] = 'bbb'
	xdebug_debug_zval('a');
	a (refcount=1, is_ref=0)
		array (size=2)
		  0 => (interned, is_ref=0)string 'aaa' (length=3)
		  1 => (interned, is_ref=0)string 'bbb' (length=3)
	unset($a) 
	表示该数组已销毁
	a: no such symbol a:
	
	e g,5 引用自身
	$a[] = &$a
	xdebug_debug_zval('a');
	a (refcount=1, is_ref=0)
		array (size=3)
		  0 => (interned, is_ref=0)string 'aaa' (length=3)
		  1 => (interned, is_ref=0)string 'bbb' (length=3)
		  2 => (refcount=2, is_ref=1)null
注:此处不方面展示, 故用图代替
此处,引用自身导致形成闭环从而导致当unset()后, 只是单纯销毁一部分

在这里插入图片描述

	unset($a)
	xdebug_debug_zval('a')

结果为: 剩余这部分将无法回收, 从而导致内存泄漏,要想回收只能等待脚本结束后,php进程|线程结束后将泄漏的内存销毁处理 (php.version < 5.3 )
在这里插入图片描述
犹豫上述的图比较抽象, 不易理解可参考如下代码配合上图理解

	$initMemory = memory_get_usage();
	echo "execute init memory : {$initMermory} <br>";
	$a = array('one');
	$a = &$a;
	unset($a);
	$endMemory = memory_get_usage();
	echo "execute after memory : {$endMemory} <br>"
	//如果在使用unset() 后 $initMemory == $endMemory 表示没有内存泄漏, 如果不等则反之
	// 输出结果为
	execute init memory:4861800
	execute after memory:4862200

接下来了解一下新的垃圾回收机制:

php.version > 5.3 之后引入了梗缓存机制, php启动时默认设置指定zval数量的根缓冲区(default 10000), 
当php发现存在循环引用的zval时便其加入根缓存区, 当缓存区达到上限后,就会进行垃圾回收, 以此解决**循环引用**的内存泄漏问题 

总结
判定垃圾界限:

 1, 引用计数减少为0时 自动清除, 不属于垃圾
 2, 如果zval的引用次数减少后还大于0, 那么进入**垃圾回收周期**
	垃圾回收周期含义:  当存储zval根缓存满后, 算法执行
		模拟删除 : 引用计数减1,导致模拟删除
		模拟恢复	: 引用计数真的不为0时, 执行模拟删除的逆运算
		真的删除 : 引用计数为0
	详细介绍请看 : https://blog.csdn.net/weixin_40341587/article/details/78710081

垃圾回收机制:

1, php.version < 5.3 以引用计数机制进行判断
2, php version > 5.3 后给予引用计数判定法则,将引用计数不为0的垃圾添加到预分配的zval中,当zval到达峰值时, 会进行垃圾回收,从而解决"循环引用"的内存泄漏问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值