垃圾回收
各结构体头部的gc提供对垃圾回收的支持。
垃圾回收是一种自动的内存管理机制,当一个变量在内存中不再被需要时,应该予以释放,这种内存资源管理称为垃圾回收。
其中一种垃圾回收的方法是引用计数,通过对数据存储的物理空间多附加一个计数器空间,当其他数据与其相关时,计数器加一,反之,相关解除时计数器减一,定期检查各存储对象的计数器,计数器为零的话,则认为该对象已经被抛弃而应将其所占物理空间回收。
PHP 7 中垃圾回收的实现方法是定期遍历和标记若干存储对象的数组,再通过算法将是垃圾的物理空间回收。
3.4.1 gc的基本结构
zend_refcounted是由uint32_t的refcount和uint32_t的type_info组成,总大小为8字节。
type_info(4字节)
type:记录当前元素的类型
flags:标记数据类型
gc_info:当前元素的颜色和垃圾回收池中的位置,高地址的两位用来标记颜色
3.4.2 引用计数
3.4.3 循环引用问题
在PHP中使用&会改变等号两边zval的类型(改变为IS_REFERENCE),引用计数记录在新的结构体(zend_reference)中,并且引用计数为2.
3.4.4 垃圾回收
PHP垃圾回收包含两部分,垃圾收集器和垃圾回收算法。垃圾收集器是将可能是垃圾的元素收集在回收池中,然后由垃圾回收算法回收。
PHP7垃圾回收维护了一个全局变量gc_globals的HashTable。
向操作系统申请10001个gc_root_buffer结构体大小的内存,然后将GC_G(buf指向首地址),GC_G(last_unused)指向尾地址。
垃圾收集过程:
要求数据类型是数组或对象
没有在缓冲区中存在过
没有被标记过
将其gc_info标记为紫色,且记录在缓冲区的位置
当缓冲区满了,再收集新的元素就会触发垃圾回收算法,引用计数大于 0 说明它还在其他地方使用,那么先将元素的引用计数减 1,如果发现引用计数为 0,则说明任何地方都不再使用它,那么它就是垃圾,需要被回收掉反之说明不是垃圾,需要将其从回收池移出去。而垃圾回收算法也是围绕这个核心条件进行的。
垃圾回收过程: