apache集成php7.3.5的详细步骤-自学php网
windows 2008r2+php5.6.28环境搭建详细过程-自学php网
PHP 代码简洁之道(小结)-自学php网
php设计模式之单例模式用法经典示例分析-自学php网
redis+php实现微博(三)微博列表功能详解-自学php网
redis+php实现微博(一)注册与登录功能详解-自学php网
redis+php实现微博(二)发布与关注功能详解-自学php网
php设计模式之工厂模式用法经典实例分析-自学php网
php文件包含的几种方式总结-自学php网
smarty模板的使用方法实例分析-自学php网
PHP MVC框架中类的自动加载机制实例分析-自学php网
php+redis实现消息队列功能示例详解-自学php网
php写入txt乱码的解决方法-自学php网
php写入mysql中文乱码的实例解决方法-自学php网
php校验公钥是否可用的实例方法-自学php网
PHP实现的文件浏览器功能简单示例-自学php网
php创建多级目录与级联删除文件的方法示例-自学php网
PHP中将一个字符串部分字符用星号*替代隐藏的实现代码详解-自学php网
分析PHP7 的垃圾回机制详解-自学php网
PHP实现跨服务器session共享的方法教程-自学php网
ADS

分析PHP7 的垃圾回机制详解-自学php网

来源:      时间: 2019-09-06 13:23:00     阅读数:3248 次     作者:

摘要: php家园网提供大量免费、原创、高清的php视频教程,并定期举行公益php培训!可边学习边在线修改示例代码,查看执行效果!php从入门到精通,一站式php自学平台! ...


300-250
垃圾回收机制垃圾回收机制是一种动态存储分配方案。它会自动释放程序不再需要的已分配的内存块。 自动回收内存的过程叫垃圾收集。垃圾回收机制可以让程序员不必过分关心程序内存分配,从而将更多的精力投入到业务逻辑。 在现在的流行各种语言当中,垃圾回收机制是新一代语言所共有的特征。垃圾的产生PHP7 中复杂类型,像字符串、数组、对象等的数据结构中,头部都有一个 gc, 这个 gc 的作用就是用来对垃圾回收的支持。当变量赋值、传递时,会增加 value 的引用数, unset、return 等释放变量时再减掉引用数,减掉后如果发现 refcount 变为 0 则直接释放 value,这是变量的基本回收过程。不过有一种问题是这个机制无法解决的,就是循环引用的问题。什么是循环引用呢? 简单说就是变量的内部里存的 value 又引用了变量自身。 这种比较经常发生在数组和对象类型的变量上。这里先讲一下引用,即 zend_reference 这个类型,这个是 PHP7 新增的变量类型,当对变量使用 “&” 操作时,会创建新的中间结构体 zend_reference,这个结构体会真正的指向对应的 value 结构。举个例子://当进行如下赋值操作时$a='hello';//$a->zend_string$b=$a;//$b,$a->zend_string$c=&$b;//$c,$b->zval(type=IS_REFERENCE,refcount=2)->zend_string最终会变成如下这样:image.png即 $b 和 $c 的 zval 是通过中间结构体 zend_reference 再指向最终的 zend_string。回到循环引用的问题,举个数组循环引用例子:$arr=[1];$a[]=&$a;unset($a);使用 & 操作之后,变量 a 就变成了引用类型且引用计数 refcount 为 2,而又赋值给自己里面的元素,即变量 a 变成了自己引用自己。具体如下如所示:image.png当 unset 之后就变成下图这样:image.png即 $a 所在的 zval 类型已经变成了 IS_UNDEF 了,zend_reference 结构体的引用计数减 1,但是仍然大于 0,这时候,这部分结构体就变成了垃圾,对此不处理的话,就可能会造成内存泄露。这里就需要垃圾收集器将这部分收集到缓冲区,之后进行回收处理。回收过程如果当变量的 refcount 减小后大于 0,PHP 并不会立即对这个变量进行垃圾鉴定和回收,而是放入一个缓冲区中,等这个缓冲区满了以后(10000 个值)再统一进行处理,加入缓冲区的是变量 zend_value 里的 gc,目前垃圾只会出现在数组和对象两种类型中,数组的情况上面已经介绍了,对象的情况则是成员属性引用对象本身导致的,其它类型不会出现这种变量中的成员引用变量自身的情况,所以垃圾回收只会处理这两种类型的变量。gc 的结构 zend_refcounted_h 具体如下:typedefstruct_zend_refcounted_h{uint32_trefcount;//记录zend_value的引用数union{struct{zend_uchartype,//zend_value的类型,与zval.u1.type一致zend_ucharflags,uint16_tgc_info//GC信息,记录在gc池中的位置和颜色,垃圾回收的过程会用到}v;uint32_ttype_info;}u;}zend_refcounted_h;一个变量只能加入一次缓冲区,为了防止重复加入,变量加入后会把 zend_refcounted_h.gc_info 置为 GC_PURPLE,即标为紫色,后续不会重复插入。垃圾缓冲区是一个双向链表,等到缓存区满了以后则启动垃圾检查过程:遍历缓冲区,对当前变量的所有成员进行遍历,然后把成员的 refcount 减 1 (如果成员还包含子成员则也进行递归遍历,即深度优先遍历),最后再检查当前变量的引用,如果减为了 0 则为垃圾。这个算法的原理核心是:垃圾是由于成员引用自身导致的,那么就对所有的成员减一遍引用,如果发现最后变量本身的 refcount 变为了 0 则就表明其引用全部来自自身成员,即其他任何地方都不再使用它,那么它就是垃圾,需要被回收掉。反之说明不是垃圾,需要将其从缓冲区移出去。具体的过程如下:(1) 从缓冲区链表的 roots 开始遍历,把当前 value 标为灰色 (zend_refcounted_h.gc_info 置为 GC_GREY),然后对当前 value 的成员进行深度优先遍历,把成员 value 的 refcount 减 1,并且也标为灰色;(2) 重复遍历缓冲区链表,检查当前 value 引用是否为 0,为 0 则表示确实是垃圾,把它标为白色(GC_WHITE),如果不为 0 则排除了引用全部来自自身成员的可能,表示还有外部的引用,并不是垃圾,这时候因为步骤(1)对成员进行了 refcount 减 1 操作,需要再还原回去,对所有成员进行深度遍历,把成员 refcount 加 1,同时标为黑色;(3) 再次遍历缓冲区链表,将非 GC_WHITE 的节点从 roots 链表中移出(移到待释放的列表),最终 roots 链表中全部为真正的垃圾,最后将这些垃圾清除。总结以上所述是小编给大家介绍的PHP7 的垃圾回收机制,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对自学php网网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

700-90


顶一下
(1)
100%
踩一下
(0)
0%

特别声明:本文为 PHP家园 自媒体平台 作者上传并发布,仅代表该作者观点。PHP家园 仅提供信息发布 平台。
本站全部内容均为 PHP家园 军迷娱乐与生活分享与个人的看法,不涉及任何军事与政治内容,图片与文章均来自网络,如有任何内容您觉得不妥,请立刻联系网站管理员给予删除!

查看原文      
最新评论   点击评论  
您好!没有相关评论,请 点击评论


表情删除后不可恢复,是否删除
取消
确定
图片正在上传,请稍后...
评论内容为空!
还没有评论,快来抢沙发吧!
点击查看更多精彩内容

最新资讯

最新文章

返回顶部