当前位置: 首页 > 后端技术 > PHP

PHP内核阅读(二)--浅谈gc回收机制(

时间:2023-03-29 22:59:54 PHP

自嘲)。....2333,我觉得这是因为它帮助我们解决了php语言层面的内存回收问题,但是这让我在跟java大牛吹牛的时候听到了一些内存泄漏的问题。...(纳尼,我以前没见过tmd)一脸疑惑。我的小菜,如果下面有什么不对的地方请指出,下面很多都是我自己看完+阅读源码后的总结。前言上一篇讲了PHP中的基本数据容器,zend_value,zval并不是所有实际存储数据的都是zend_value,还有zend_value通过指针指向的具体数据存储结构,比如_zend_array,_zend_stringstruct_zend_string{zend_refcounted_hGC;zend_ulongh;/*哈希值*/size_tlen;charval[1];};struct_zend_array{zend_refcounted_hgc;union{struct{ZEND_ENDIAN_LOHI_4(zend_ucharflags,zend_ucharnApplyCount,zend_ucharnIteratorsCount,zend_ucharconsistency)}v;uint32_t标志;}你;uint32_tnTableMask;桶*arData;uint32_tnNumUsed;uint32_tnNumOfElements;uint32_tnTableSize;uint32_tnInternalPointer;zend_longnNextFreeElement;这个变量其实就是zend_refcounted_h引用计数内存回收的两种情况。普通变量在生命周期结束后被回收。这种情况意味着当zend_value中refCount==0时,此时是正常的内存回收。垃圾回收所谓垃圾:是指通过循环引用(自引用,目前只出现在数组和对象类型中)的形式,使refcount永远不会为0。这种情况下,如果不处理,但是内存无法释放,那么内存泄漏代码如下:$a=array(1,2);xdebug_debug_zval("a");$a[]=&$a;xdebug_debug_zval("a");$b=$a;unset($a);xdebug_debug_zval("a");xdebug_debug_zval("b");结果如下a:(refcount=1,is_ref=0)array(size=2)0=>(refcount=0,is_ref=0)i??nt11=>(refcount=0,is_ref=0)i??nt2a:(refcount=2,is_ref=1)array(size=3)0=>(refcount=0,is_ref=0)i??nt11=>(refcount=0,is_ref=0)i??nt22=>(refcount=2、is_ref=1)&array(refcount=0,is_ref=0)int11=>(refcount=0,is_ref=0)i??nt22=>(refcount=1,is_ref=1)&array<按照正常逻辑,当unset($a)后,对应的zeng_valuerefCount=1,is_ref=0,但实际上等于refCount=2,is_ref=0,这导致,即使是unset($b),之后,refCount=1,is_ref=0,这种结果如上,当refCount=0时,内存正常回收。![图片上传中...]这是垃圾。当垃圾出现时,PHP的zend引擎有相应的垃圾回收机制。其实这个机制的原理是:(1).将这些垃圾放入缓冲区。(2).当buffer达到一定数量时,对所有垃圾的值本身启动refCount-1,将zend_refcounted中的gc_info变量设置为GC_GRAYtypedefstruct_zend_refcounted_h{uint32_trefcount;/*referencecounter32-bit*/union{struct{ZEND_ENDIAN_LOHI_3(zend_uchartype,zend_ucharflags,/*usedforstrings&objects*/uint16_tgc_info)/*这个变量是否保存GC根数(或0)和颜色*/}vuint32_t类型信息;}u;ed_hend_refcount;(3).遍历当前缓冲区,当refCount=0时表示当前值确实是垃圾,然后将zend_refcounted中的gc_info变量设置为GC_WHITE。然后因为所有的值都减1,所以又遍历一遍,那些refcount的value+1!value的zend_refcounted中的gc_info被GC_WHITE删除。说完GC垃圾回收算法的原理,好像没提到什么时候触发把这个**可能**的垃圾放入缓冲区。.....***触发该机制的时机是每次refCount减少时。***

猜你喜欢