PHPの廃棄物処理メカニズム

PHP5.3バージョンの前に、可変回復機構PHPは単に処理計数により(参照カウント= 0は、メモリを再利用する場合)、これは問題になります

$ A =配列( "STR");

[] =&$ $。

設定を解除($ A)。

PHPスクリプトが割り当てを完了した後に解除実行する前に、もちろん、すなわち廃棄物、それが0に等しくないので、解除、$ Aは、refcout 1で行った後、メモリを回収することができない、2の参照カウントを$メモリはすべてリサイクルし、今PHPスクリプトに加えて使用、デーモンのサービスを記述するためのより多くの場所(もちろん、私はお勧めしません)、この期間中にこのような上記の方法として、2ヶ月スクリプトの終了前に、月までかかることがありますこれは、メモリのオーバーフローが生成されます

 注意:設定を解除し、メモリを解放することはできません、あなたはzvalを参照カウントを見て0ている必要があります

GCのガベージコレクションによって後でPHP5.3

zvalを割り当てる際、単位zval_gc_infoします

 

コードをコピー
#define ALLOC_ZVAL(Z)\ 
    {行う\ 
        (Z)=(zvalを*)におけるemalloc(はsizeof(zval_gc_info))。\ 
        GC_ZVAL_INIT(Z)。\ 
    }(0)、一方

のtypedef構造体_zval_gc_info { 
    zvalをZ。
    組合{ 
        gc_root_buffer *バッファリング。
        次の* _zval_gc_info構造体。
    } U。
} zval_gc_info。

#define FREE_ZVAL(Z)\ 
    ん{\ 
        GC_REMOVE_ZVAL_FROM_BUFFER(Z)。\ 
        efree(Z)。\
    }(0)、一方
コードをコピー

 

 

コードをコピー
構造体_gc_root_buffer {typedefは
    、構造体_gc_root_buffer * PREV / *二重リンクリスト* / 
    次のstruct _gc_root_buffer *; 
    zend_object_handleハンドル; / *のzval * / 0でなければならない
    組合{ 
        PZ * zvalを。
        zend_object_handlers *ハンドラ。
    } U。
} gc_root_buffer。
コードをコピー

 

 

 

PHPのGC回復メカニズムが起動したとき、それは万gc_root_bufferのスペースを割り当て

コードをコピー
ZEND_APIボイドgc_init(TSRMLS_D)   
{   
    IF(GC_G(BUF)== NULL && GC_G(gc_enabled)){   
        GC_G(BUF)=(gc_root_buffer *)はmalloc(はsizeof(gc_root_buffer)* GC_ROOT_BUFFER_MAX_ENTRIES)。  
        GC_G(last_unused)=&GC_G(BUF)GC_ROOT_BUFFER_MAX_ENTRIES]。  
        gc_reset(TSRMLS_C)。  
    }   
}  
コードをコピー

 

場合解除($ A)、ここで詳述  キーはzvalをactive_systom_tableで発見された後、zvalを参照カウント-1であった、その値デストラクタを実行する、1の値は、減算後0である場合、即時放出を説明することができますメモリ、それは場所で、0より大きい場合gc_root_buffer

コードをコピー
ZEND_APIボイド_zval_ptr_dtor(zvalを** zval_ptr ZEND_FILE_LINE_DC)/ * {{{* /   
{    
    Z_DELREF_PP(zval_ptr)。  
    IF(Z_REFCOUNT_PP(zval_ptr)== 0){   
        TSRMLS_FETCH()。  
  
        (!* zval_ptr =&EG(uninitialized_zval)){もし   
            GC_REMOVE_ZVAL_FROM_BUFFER(* zval_ptr)。  
            zval_dtor(* zval_ptr)。  
            efree_rel(* zval_ptr)。  
        }   
    }他{   
        TSRMLS_FETCH()。  
  
        IF(Z_REFCOUNT_PP(zval_ptr)== 1){   
            Z_UNSET_ISREF_PP(zval_ptr)。  
        }   
  
        GC_ZVAL_CHECK_POSSIBLE_ROOT(* zval_ptr)。  
    }   
}  
コードをコピー

 

 

 

コードをコピー
#define GC_ZVAL_CHECK_POSSIBLE_ROOT(Z)/ 
    gc_zval_check_possible_root((Z)TSRMLS_CC)

静的zend_always_inline空隙gc_zval_check_possible_root(zvalを* Z TSRMLS_DC)
{ 
    IF(Z->タイプ== IS_ARRAY || Z->入力== IS_OBJECT){ 
        gc_zval_possible_root(Z軸TSRMLS_CC) ; 
    } 
} 

ZEND_API空隙gc_zval_possible_root(zvalを* ZV TSRMLS_DC)
{ 
    IF(UNEXPECTED(GC_G(free_list)!= NULL && 
                   GC_ZVAL_ADDRESS(ZV)!= NULL && 
                   GC_ZVAL_GET_COLOR(ZV)== GC_BLACK)&& 
                   (GC_ZVAL_ADDRESS(ZV)<GC_G(BUF )|| 
                    GC_ZVAL_ADDRESS(ZV)> = GC_G(last_unused))){
        / *ザ・のごみはzvalのがあることを行っによって削除されることを考えるとIS 
         GC * /実行されている現在* 
        ;リターンを
    } 

    IF(zv->タイプ== IS_OBJECT){ 
        ; GC_ZOBJ_CHECK_POSSIBLE_ROOT(ZV)
        リターン; 
    } 

    GC_BENCH_INC(zval_possible_root); //最後の二つが紫でない場合はZV gc_root_buffer、その後、処理された
     IF(GC_ZVAL_GET_COLOR(ZV)= GC_PURPLE!){ 
        GC_ZVAL_SET_PURPLE(ZV); //設定紫 IF {(!GC_ZVAL_ADDRESS(ZV))
            gc_root_buffer * = newRootトGC_G( )未使用; 
            IF(newRootト){ 
                GC_G(未使用)= newRoot-> PREV; 
            !}そうでなければ(GC_G(first_unused IF)= GC_G(last_unused)){
    

        

                newRootト= GC_G(first_unused)。
                GC_G(first_unused)++; 
            }他{ 
                (!GC_G(gc_enabled))なら、{ 
                    GC_ZVAL_SET_BLACK(ZV)。
                    返します。
                } 
                zv-> refcount__gc ++。
                gc_collect_cycles(TSRMLS_C)。
                zv-> refcount__gc--。
                newRootト= GC_G(未使用)。
                (!newRootト){もし
                    返します。
                } 
                GC_ZVAL_SET_PURPLE(ZV)。
                GC_G(未使用)= newRoot-> PREV。
            } 

            newRoot->次= GC_G(根).next。
            newRoot-> PREV =&GC_G(ルーツ); 
            GC_G(根).next-> PREV = newRootト。
            GC_G(根).next = newRootト。

            GC_ZVAL_SET_ADDRESS(ZV、newRootト)。//将gc_root_buffer放到zval_gc_info结构体中
 
            newRoot->ハンドル= 0; 
            newRoot-> u.pz = ZV。

            GC_BENCH_INC(zval_buffered)。
            GC_BENCH_INC(root_buf_length)。
            GC_BENCH_PEAK(root_buf_peak、root_buf_length)。
        } 
    } 
}
コードをコピー

 

 

gc_root_buferに現在のzvalを、それぞれがzval_gc_infoにzvalの色gc_root_bufferが紫に位置するかどうかに基づいて、一度だけ入れZVAL

 

#define GC_ZVAL_GET_COLOR(V)\
GC_GET_COLOR(((zval_gc_info *)(V)) - > u.buffered)

#define GC_GET_COLOR(V)\
(((zend_uintptr_t)(V))&GC_COLOR)

 

それは紫である場合には、紫へ

#define GC_ZVAL_SET_PURPLE(V)\
GC_SET_PURPLE(((zval_gc_info *)(V)) - > u.buffered)

#define GC_SET_PURPLE(V)\
(V)=((gc_root_buffer *)(((zend_uintptr_t)(V))| GC_PURPLE))

 

マクロGC_ZVAL_SET_ADDRESS(ZV、newRootト); gc_root_buffer newRootトは、対応する位置ZVを配置するために使用

コードをコピー
#define GC_COLOR 0x03の

に#define GC_BLACKは0x00 
の#define GC_WHITEが0x01 
の#define GC_GREY 0x02の
に#define GC_PURPLE 0x03の

に#define GC_ZVAL_SET_ADDRESS(V、A)\ 
    GC_SET_ADDRESS(((zval_gc_info *)(V)) - > u.buffered、(a)参照)

#define GC_SET_ADDRESS(V、A)\ 
    (V)=((gc_root_buffer *)((((zend_uintptr_t)(V))&GC_COLOR)|((zend_uintptr_t)(A))))
コードをコピー

 

 

メモリを割り当てるときGC_ZVAL_SET_ADDRESSマクロvがzval_gc_info最初のタイプに押し込ま、それ自体はzvalを、唯一zvalをパディングデータ構造ので、強いのzvalの*に、ユニットをzval_gc_infoすることであり、これはgc_root_buffer必要はない* buferメンバーのよう
zval_gc_val構造、zvalをZの最初のメンバーは、Zは、メモリアドレスは、アドレス自体zval_gc_infoあるため、

廃棄物処理を示すために色を使用してPHP GCで

32ビットマシンまたは64ビットマシンの両方にポインタを最後の二つは0で、

廃棄物処理をgc_collect_cycles

 


コードをコピー
ZEND_APIのint型gc_collect_cycles(TSRMLS_D)
{ 
    int型のカウント= 0; 

    {(!GC_G(根)は=&GC_G(根).next)場合
        zval_gc_info * P、Q *、* orig_free_list、* orig_next_to_free。

        (GC_G(gc_active))なら、{ 
            0を返します。
        } 
        GC_G(gc_runs)++; 
        GC_G(zval_to_free)= FREE_LIST_END。
        GC_G(gc_active)= 1。
        gc_mark_roots(TSRMLS_C)。
        gc_scan_roots(TSRMLS_C)。
        gc_collect_roots(TSRMLS_C)。

        orig_free_list = GC_G(free_list)。
        orig_next_to_free = GC_G(next_to_free)。
        P = GC_G(free_list)= GC_G(zval_to_free)。
        GC_G(zval_to_free)= NULL;
        GC_G(gc_active)= 0。

        / *最初の呼び出しデストラクタ* / 
        ながら(P!= FREE_LIST_END){ 
            IF(Z_TYPE(P-> Z)== IS_OBJECT){ 
                IF(EG(objects_store).object_buckets && 
                    EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。有効&& 
                    EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。bucket.obj.refcount <= 0 && 
                    EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。bucket.obj .dtor && 
                    !EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)] destructor_called){。

                      EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)] = 1 destructor_called。
                      EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)] bucket.obj.refcount ++。
                      EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。bucket.obj.dtor(EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。bucket.obj.object、Z_OBJ_HANDLE(P-> Z )TSRMLS_CC)。
                      EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)] bucket.obj.refcount--。
                  } 
            } 
            ++数えます。
            P = P - > u.next。
        } 

        / * zvalsを破棄* / 
        P = GC_G(free_list)。
        一方、(P = FREE_LIST_END!){ 
            GC_G(next_to_free)= P-> u.next。
            IF(Z_TYPE(P-> Z)== IS_OBJECT){
                IF(EG(objects_store).object_buckets && 
                    EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。有効&& 
                    EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)]。bucket.obj.refcount <= 0){ 
                    EG(objects_store).object_buckets [Z_OBJ_HANDLE(P-> Z)] = 1 bucket.obj.refcount。
                    Z_TYPE(P-> Z)= IS_NULL。
                    zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(P-> Z)、Z_OBJ_HT(P-> Z)TSRMLS_CC)。
                } 
            }そうであれば(Z_TYPE(P-> Z)== IS_ARRAY){ 
                Z_TYPE(P-> Z)= IS_NULL。
                zend_hash_destroy(Z_ARRVAL(P-> Z))。
                FREE_HASHTABLE(Z_ARRVAL(P->
            }他{ 
                zval_dtor(&P-> Z)。
                Z_TYPE(P-> Z)= IS_NULL。
            } 
            P = GC_G(next_to_free)。
        } 

        / *フリーzvals * / 
        P = GC_G(free_list)。
        一方、(P = FREE_LIST_END!){ 
            Q = P-> u.next。
            FREE_ZVAL_EX(&P-> Z)。
            P = Q。
        } 
        GC_G(収集)+ =数えます。
        GC_G(free_list)= orig_free_list。
        GC_G(next_to_free)= orig_next_to_free。
    } 

    カウントを返します。
}
コードをコピー

 

 
gc_mark_roots(TSRMLS_C);スパムアレイのu.pz各要素は1-れる参照カウント、,. ZVAL横断u.pz灰色に紫色に変化した色マーカー、トラバースgc_root_buffer、レイ
参照カウント=場合、gc_collect_rootsトラバースgc_root_bufferを参照カウント> 0は、誰かが黒に設定し、使用することができる示している場合= 0次いで、白に設定では、スパムとして表さ
 
コードをコピー
静的ボイドgc_mark_roots(TSRMLS_D)
{ 
    gc_root_buffer *電流= GC_G(根).next。

    しばらく(現在!=&GC_G(根)){ 
        場合(電流- >ハンドル){ 
            場合(EG(objects_store).object_buckets){ 
                //处理对象、暂时不用看
            } 
        }他{ 
            場合(GC_ZVAL_GET_COLOR(電流- > U。 PZ)== GC_PURPLE){ 
                TSRMLS_CC u.pz zval_mark_grey(電流- >)。
            }他{ 
                GC_ZVAL_SET_ADDRESS(電流- > u.pz、NULL); 
                GC_REMOVE_FROM_BUFFER(現在)
            } 
        } 
        電流=電流- >次に、
    } 
}
コードをコピー
 

 

 
コードをコピー
静的ボイドzval_mark_grey(zvalを* PZ TSRMLS_DC)
{ 
    バケット* P。

tail_call:
    IF(GC_ZVAL_GET_COLOR(PZ)= GC_GREY!){ 
        P = NULL; 
        GC_BENCH_INC(zval_marked_grey)。
        GC_ZVAL_SET_COLOR(PZ、GC_GREY)。

        IF(Z_TYPE_P(PZ)== IS_OBJECT && EG(objects_store).object_buckets){ 
            //对象的处理、暂时不用管
        }そうであれば(Z_TYPE_P(PZ)== IS_ARRAY){ 
            IF(Z_ARRVAL_P(PZ)==&EG( symbol_table)){ 
                GC_ZVAL_SET_BLACK(PZ)。
            }他{ 
                P = Z_ARRVAL_P(PZ) - > pListHead。
            } 
        } 
        一方(P!= NULL){
            PZ = *(zvalを**)のp-> pDataを。
            IF(Z_TYPE_P(PZ)= IS_ARRAY || Z_ARRVAL_P(PZ)=&EG(symbol_table)!){ 
                pz-> refcount__gc--。
            } 
            IF(P-> pListNext == NULL){ 
                後藤tail_call。
            }他{ 
                zval_mark_grey(PZのTSRMLS_CC)。
            } 
            P = P-> pListNext。
        } 
    } 
}
コードをコピー

 

 第二の通過gc_root_buffer、ZV色は灰色であり、参照カウント> 0、黒(スパムではない)に設定されているときに参照カウント= 0、その後、白に設定されている場合

コードをコピー
静的ボイドgc_scan_roots(TSRMLS_D)
{ 
    gc_root_buffer *電流= GC_G(根).next。

    一方、(!電流=&GC_G(根)){ 
        IF(電流- >ハンドル){ 
            zvalをZ。

            INIT_PZVAL(&Z)。
            Z_OBJ_HANDLE(Z)=電流- >ハンドル。
            Z_OBJ_HT(Z)=電流- > u.handlers。
            zobj_scan(&Z TSRMLS_CC)。
        }他{ 
            zval_scan(電流- > TSRMLS_CC u.pz)。
        } 
        電流=電流- >次に、
    } 
}
コードをコピー

 

 

コードをコピー
静的INT zval_scan(zvalを* PZのTSRMLS_DC)
{ 
    バケット* P。

tail_call:     
    IF(GC_ZVAL_GET_COLOR(PZ)== GC_GREY){ 
        P = NULL; 
        IF(pz-> refcount__gc> 0){ 
            zval_scan_black(PZのTSRMLS_CC)。
        }他{ GC_ZVAL_SET_COLOR(PZ、GC_WHITE)。
            IF(Z_TYPE_P(PZ)== IS_OBJECT && EG(objects_store).object_buckets){ 
               //处理オブジェクト
            他}(Z_TYPE_P(PZ)== IS_ARRAY){もし
                あれば(Z_ARRVAL_P(PZ)==&EG(symbol_table)){ 
                    GC_ZVAL_SET_BLACK (PZ)。
                }他{ 
                    P = Z_ARRVAL_P(PZ) - > pListHead。
                }
           
            } 
        } 
        ながら(!p = NULL){ 
            IF(P-> pListNext == NULL){ 
                PZ = *(zvalを**)p> pDataを。
                後藤tail_call; 
            }他{ 
                zval_scan(*(zvalを**)p> pDataをTSRMLS_CC)。
            } 
            P = P-> pListNext。
        } 
    } 
    0を返します。
}
コードをコピー

 

 

Gc_root_bufferリンクリストトラバーサル、単色ZVリストの配置は白データ、完全に回復されます

コードをコピー
静的ボイドgc_collect_roots(TSRMLS_D)
{ 
    gc_root_buffer *電流= GC_G(根).next。

    しばらく(現在!=&GC_G(根)){ 
        場合(電流- >ハンドル){ 
            場合(EG(objects_store).object_buckets){ 
                構造体_store_object * OBJ =&EG(objects_store).object_buckets [電流- >ハンドル] .bucket.obj ; 
                zvalをZ。

                GC_SET_ADDRESS(obj->緩衝、NULL); 
                INIT_PZVAL(&Z)。
                Z_OBJ_HANDLE(Z)=電流- >ハンドル。
                Z_OBJ_HT(Z)=電流- > u.handlers。
                zobj_collect_white(&ZのTSRMLS_CC)。
            } 
        }他{
            GC_ZVAL_SET_ADDRESS(電流- > u.pz、NULL); 
            (TSRMLS_CC u.pzの電流>)zval_collect_white。
        } 

        GC_REMOVE_FROM_BUFFER(現在)
        現在=の電流>次。
    } 
}
コードをコピー

 

 

コードをコピー
静的ボイドzval_collect_white(zvalを* PZ TSRMLS_DC)
{ 
    バケット* P。

tail_call:
    IF(((*)(PZ))zval_gc_info - > u.buffered ==(gc_root_buffer *)GC_WHITE){ 
        P = NULL; 
        GC_ZVAL_SET_BLACK(PZ)。

        IF(Z_TYPE_P(PZ)== IS_OBJECT && EG(objects_store).object_buckets){ 
            ... 
        }他{ 
            IF(Z_TYPE_P(PZ)== IS_ARRAY){ 
                P = Z_ARRVAL_P(PZ) - > pListHead。
            } 
        } 

        / *参照カウントを復元し、解放するために、リストに入れ* / 
        pz-> refcount__gc ++; 
        ((zval_gc_info *)PZ) - > u.next = GC_G(zval_to_free)。
        GC_G(zval_to_free)=(zval_gc_info *)PZ。

        (!P = NULL){しばらく
            PZ = *(zvalを**)のp-> pDataを。
            もし(!!Z_TYPE_P(PZ)= IS_ARRAY || Z_ARRVAL_P(PZ)=&EG(symbol_table)){ 
                pz-> refcount__gc ++; 
            } 
            IF(P-> pListNext == NULL){ 
                後藤tail_call。
            }他{ 
                zval_collect_white(PZ TSRMLS_CC)。
            } 
            P = P-> pListNext。
        } 
    } 
}
コードをコピー

おすすめ

転載: www.cnblogs.com/yangjinqiang/p/11129308.html