首頁 >後端開發 >php教程 >PHP是如何做垃圾回收的(圖文)

PHP是如何做垃圾回收的(圖文)

angryTom
angryTom轉載
2020-01-31 17:33:412645瀏覽

PHP是如何做垃圾回收的(圖文)

PHP是如何做垃圾回收的?

包含php 5 與php7 的變數實作與垃圾回收的比較

變數的實作

PHP 的變數是弱型別的,可以表示整數、浮點數、字串等型別。 PHP 的變數是使用結構體zval 表示的

PHP 5.* zval 和zend_value 結構

struct _zval_struct { // 结构体
    zvalue_value value;
    zend_uint refcount__gc;
    zend_uchar type;
    zend_uchar is_ref__gc;
}

typedef union _zvalue_value { // 联合体
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str; // 字符串
    HashTable *ht; // 数组
    zend_object_value obj; // 对象
    zend_ast *ast;
} zvalue_value;

PHP 7.0 zval 和zend_value 結構

struct _zval_struct {
    union {
        zend_long         lval;             /* long value */
        double            dval;             /* double value */
        zend_refcounted  *counted;
        zend_string      *str;
        zend_array       *arr;
        zend_object      *obj;
        zend_resource    *res;
        zend_reference   *ref;
        zend_ast_ref     *ast;
        zval             *zv;
        void             *ptr;
        zend_class_entry *ce;
        zend_function    *func;
        struct {
            uint32_t w1;
            uint32_t w2;
        } ww;
    } value;
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                zend_uchar    type,         /* active type */
                zend_uchar    type_flags,
                zend_uchar    const_flags,
                zend_uchar    reserved)     /* call info for EX(This) */
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t     var_flags;
        uint32_t     next;                 /* hash collision chain */
        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;
};

##PHP5 與PHP7引用計數的對比

php 5.* 變數賦值等操作引用計數如圖所示,在倒數第二步,會形成一個循環引用,並且在unset 操作之後,會產生垃圾。

PHP是如何做垃圾回收的(圖文)

PHP 7 的計數放到了具體的 value 中,zval 不存在寫時複製(寫時分離)。

並且 PHP 7 的有一個專門的 zend_reference 用來表示引用。

PHP是如何做垃圾回收的(圖文)

有了以上關於 PHP 變數儲存的知識,我們可以理解一下 PHP 是如何做垃圾回收的了。

什麼是垃圾

首先,我們要定義什麼是垃圾。

1. refcount 增加的不是

2. refcount 等於0的不是,這個會被直接清除

3. refcount 減少,並且不等於0的才是垃圾

垃圾收集

1. php7 要求資料型別是數組和對象,並且type_flag 是IS_TYPE_COLLECTABLE

#2. 沒有在緩衝區中存在過

3. 沒有被標記過

4. 標記為紫色,並且放到緩衝區中

回收演算法

論文:https://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf

PHP 5.3 版本以及之後的版本

# 1. 將垃圾放到一個root 池中

2. 當滿10000 個節點的時候進行垃圾回收

3. 遍歷雙向鍊錶中的節點refcount-1

4. 遍歷雙向鍊錶將refcount=0 的節點刪除,到free佇列中

#5.對refcount!=0 的refcount 1

PHP是如何做垃圾回收的(圖文)

以上是PHP是如何做垃圾回收的(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除