垃圾回收
    各结构体头部的gc提供对垃圾回收的支持。
    垃圾回收是一种自动的内存管理机制,当一个变量在内存中不再被需要时,应该予以释放,这种内存资源管理称为垃圾回收。
    其中一种垃圾回收的方法是引用计数,通过对数据存储的物理空间多附加一个计数器空间,当其他数据与其相关时,计数器加一,反之,相关解除时计数器减一,定期检查各存储对象的计数器,计数器为零的话,则认为该对象已经被抛弃而应将其所占物理空间回收。
    PHP 7 中垃圾回收的实现方法是定期遍历和标记若干存储对象的数组,再通过算法将是垃圾的物理空间回收。

    3.4.1 gc的基本结构
    image.png
    image.png
    zend_refcounted是由uint32_t的refcount和uint32_t的type_info组成,总大小为8字节。
    type_info(4字节)
    type:记录当前元素的类型
    flags:标记数据类型
    gc_info:当前元素的颜色和垃圾回收池中的位置,高地址的两位用来标记颜色

    3.4.2 引用计数
    image.png
    3.4.3 循环引用问题
    在PHP中使用&会改变等号两边zval的类型(改变为IS_REFERENCE),引用计数记录在新的结构体(zend_reference)中,并且引用计数为2.
    image.png
    3.4.4 垃圾回收
    PHP垃圾回收包含两部分,垃圾收集器和垃圾回收算法。垃圾收集器是将可能是垃圾的元素收集在回收池中,然后由垃圾回收算法回收。
    PHP7垃圾回收维护了一个全局变量gc_globals的HashTable。
    向操作系统申请10001个gc_root_buffer结构体大小的内存,然后将GC_G(buf指向首地址),GC_G(last_unused)指向尾地址。
    image.png
    垃圾收集过程:
    要求数据类型是数组或对象
    没有在缓冲区中存在过
    没有被标记过
    将其gc_info标记为紫色,且记录在缓冲区的位置
    当缓冲区满了,再收集新的元素就会触发垃圾回收算法,引用计数大于 0 说明它还在其他地方使用,那么先将元素的引用计数减 1,如果发现引用计数为 0,则说明任何地方都不再使用它,那么它就是垃圾,需要被回收掉反之说明不是垃圾,需要将其从回收池移出去。而垃圾回收算法也是围绕这个核心条件进行的。
    垃圾回收过程:
    image.png