PHP垃圾回收机制

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了PHP垃圾回收机制脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

什么是垃圾
垃圾主要是针对内存的,如果一个对象struct,并没有任何变量引用它,那这个对象就是垃圾

PHP垃圾回收机制

 

为啥要清理垃圾
不是说PHP线程结束的时候回销毁所有的变量,关闭所有打开的句柄资,不都是自动的吗?为什么还需要清理?
·如果PHP开启了很多内存空间,但是却没有销毁它,内存会一点点的被掉,最终导致内存溢出。
·如果写的PHP代码是个需要长时间执行的呢,例如弄成守护进程。

如何回收垃圾
第一步:从所有变量中找到垃圾(所有的变量怎么来的?怎样才能知道其中的某个变量是垃圾?)
第二步:找到垃圾后,清除垃圾(怎么清除?怎样才算真的清除垃圾?)

1、如何找垃圾
从所有变量中找到垃圾,所有的变量get_defined_VARs函数能够看到所有已经定义的变量,那意味着PHP本身能存储所有变量或已开辟的内存空间,具体在zend_globals.h中struct _zend_executor_globals中看到

补充:PHP变量值存储在struct _zval_struct中,而变量名存储在struct _zend_executor_globals中
struct _zend_executor_globals {

/*略*/

HashTable *active_symbol_table; /* 局部变量的符号表 */
HashTable symbol_table; /* main symbol table 全局变量的符号表*/

/*略*/

这样就能找到所有的变量了,怎样找到垃圾?按照我们的想法,一定会在这个变量上面打个标签,这个是垃圾,可以清理了。那么这个标签在哪里呢?
在struct _zval_struct中
zend_uint refcount__gc //用来标记有多少个变量指向它
zend_uchar is_ref__gc //用来标记是否用引用的方式指向它

2、如何清理掉
看看是不是垃圾,就看refcount__gc是不是0,找到0就清除,并回收内存(5.2以及以前版本)
PHP5.3以后,采用了新的算法,即引用计数系统中的同步周期回收算法来清除

先看一个简单的例子:
<?PHP
//把一个数组作为一个元素添加到自己内部
$a = array("one");

$a[] = &amp;$a;

xdebug_debug_zval(‘a‘);

输出
a:(refcount=2,is_ref=1)=array(
0=>(refcount=1,is_ref=0)=‘one‘,
1=>(refcount=2,is_ref=1)=...
)

PHP垃圾回收机制

 


能看到数组变量(a)同时也是这个数组的第二个元素(1)指向的变量容器中"refcount"为2。上面的输出结果中的"..."说明发生了递归操作,显然在这种情况下意味着"..."指向原始数组。
跟刚刚一样,对一个变量调用unset,将删除这个符号,且它指向的变量容器中的引用次数也减1.所以,如果我们执行完上面的代码后,对变量$a调用unset,那么变量$a和数组元素“1”所指向的变量容器的引用次数减1,从“2”变成“1”,如下:
(refcount=1,
1=>(refcount=1,is_ref=1)=...
)

PHP垃圾回收机制

 

3、引发思考
尽管不在有某个作用域中的任何符号指向这个结构(就是变量容器),由于数组元素“1”仍然指向数组本身,所以这个容器不能被清除。因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏。庆幸的是,PHP将在脚本执行结束时清除这个数据结构,但是在PHP清除之前,将想好不少内存。
如果上面的情况发生仅仅一两次倒没什么,但是如果出现几千次,甚至几十万次的内存泄漏,这显然是个大问题。这样的问题往往发生在长时间运行的脚本中,比如请求基本上不会结束的守护进程或者单元测试中的大的套件中。

4、PHP5.3的删除算法介绍
PHP5.3中,采用模拟删除每个疑似变量。模拟删除时将变量引用数减1,然后再进行模拟恢复,但恢复是有条件的,当有其他变量指向该值时才对其做模拟恢复。这样剩下的一对没能恢复的就是该删除

5、什么时候回收? ·当我们存储的疑似垃圾的区域满了的时候,就会被执行清除垃圾的操作,前提是开启了垃圾回收机制,当然认是打开的,PHP.ini设置允许你修改它:zend.enable_gc ·修改配置zend.enable_gc,也能通过分别调用gc_enable()和gc_disable()函数来打开和关闭垃圾回收机制。调用这些函数,与修改配置项来打开挥着关闭垃圾回收机制的效果是一样的。你还能调用gc_collect_cycles()函数达到这个目的。他能强制执行周期回收。

脚本宝典总结

以上是脚本宝典为你收集整理的PHP垃圾回收机制全部内容,希望文章能够帮你解决PHP垃圾回收机制所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。