美文网首页
PHP知识梳理_GC

PHP知识梳理_GC

作者: 空语 | 来源:发表于2019-03-25 17:12 被阅读0次

    参考PHP版本7.1

    1.PHP 变量结构

    php变量在zend中的定义分为zval zend_value, 
        zval存储变量名 和指向value的指针,
        zend_value存储具体的变量值
    
    //zend_types.h
    typedef struct _zval_struct     zval;
    
    typedef union _zend_value {
        zend_long         lval;    //int整形
        double            dval;    //浮点型
        zend_refcounted  *counted;
        zend_string      *str;     //string字符串
        zend_array       *arr;     //array数组
        zend_object      *obj;     //object对象
        zend_resource    *res;     //resource资源类型
        zend_reference   *ref;     //引用类型,通过&$var_name定义的
        zend_ast_ref     *ast;     //下面几个都是内核使用的value
        zval             *zv;
        void             *ptr;
        zend_class_entry *ce;
        zend_function    *func;
        struct {
            uint32_t w1;
            uint32_t w2;
        } ww;
    } zend_value;
    
    struct _zval_struct {
        zend_value        value; //变量实际的value
        union {
            struct {
                ZEND_ENDIAN_LOHI_4( //这个是为了兼容大小字节序,小字节序就是下面的顺序,大字节序则下面4个顺序翻转
                    zend_uchar    type,         //变量类型
                    zend_uchar    type_flags,  //类型掩码,不同的类型会有不同的几种属性,内存管理会用到
                    zend_uchar    const_flags,
                    zend_uchar    reserved)     //call info,zend执行流程会用到
            } v;
            uint32_t type_info; //上面4个值的组合值,可以直接根据type_info取到4个对应位置的值
        } u1;
        union {
            uint32_t     var_flags;
            uint32_t     next;                 //哈希表中解决哈希冲突时用到
            uint32_t     cache_slot;           /* literal cache slot */
            uint32_t     lineno;               /* line number (for ast nodes) */
            uint32_t     num_args;             /* arguments number for EX(This) */
            uint32_t     fe_pos;               /* foreach position */
            uint32_t     fe_iter_idx;          /* foreach iterator index */
        } u2; //一些辅助值
    };
    
        zend_value 中定义了 zend_refcount 即当前数据的引用次数,引用的变量每销毁一个 zend_refcount -1,正常情况下。函数执行完毕后会减为0,内存自动销毁回收zend_value.
        $a = array[];
        $a[] = &$a;
        unset($a);
        如上当出现类似自身引用自身时,unset后 zend_refcount 为1,这时候zend_value就有内存垃圾,zend的GC 机制就会将该 zend_value 放入GC的处理队列中。等待GC处理
    

    2. Zend GC

     zendGC 管理了一个buffer 作为作为垃圾缓存区的存储地址, buffer使用双向链表实现 长度10000,当有垃圾产生时 加入到链表中,当链表满时触发GC进行清理。
    GC清理过程: 
        1.使用深度优先算法,对垃圾成员进行遍历,将垃圾成员的refcount 减1。并标记状态为 grey(灰)。 
            为什么使用深度优先?为了检测成员的子成员引用
        2.重新遍历buffer,将refcount的值为0的 状态改为 WHITE(白),此类即为真正的垃圾数据,需要清理。如果非0 则表明除自身引用外,还有其他外部引用.非垃圾数据将refcount +1.将状态标记为黑色。
        3.遍历buffer, 将非WHITE状态的数据全部还原,剩余WHITE状态的均为垃圾数据 清空链表。

    相关文章

      网友评论

          本文标题:PHP知识梳理_GC

          本文链接:https://www.haomeiwen.com/subject/zyybvqtx.html