1. 程式人生 > >PostgreSQL的記憶體管理機制三:AllocSet/MemoryContext例項刪除和記憶體回收

PostgreSQL的記憶體管理機制三:AllocSet/MemoryContext例項刪除和記憶體回收

        話說MemoryContextMethods結構裡的函式實現了pg裡AllocSet/MemoryContext的記憶體管理機制,定義見下面。

typedef structMemoryContextMethods

{

     void    *(*alloc) (MemoryContext context, Sizesize);

     /* call this free_p in case someone #define's free() */

     void     (*free_p)(MemoryContext context, void *pointer);

     void    *(*realloc) (MemoryContext context, void *pointer, Size size);

     void     (*init)(MemoryContext context);

     void     (*reset)(MemoryContext context);

     void     (*delete) (MemoryContext context);

     Size     (*get_chunk_space) (MemoryContext context, void *pointer);

     bool     (*is_empty)(MemoryContext context);

     void     (*stats)(MemoryContext context);

#ifdef MEMORY_CONTEXT_CHECKING

     void     (*check)(MemoryContext context);

#endif

} MemoryContextMethods;

        其中delete由AllocSet的靜態函式AllocSetDelete()實現,具體簽名在下面。它實現了AllocSet相關的記憶體刪除機制。而MemoryContext即父類的記憶體刪除由MemoryContextDelete()實現,簽名在下面。這兩個方法各自負責本型別中成員的記憶體刪除工作,好像協作,完成了AllocSet/MemoryContext型別物件的刪除和記憶體回收工作。

static void AllocSetDelete(MemoryContextcontext)

void MemoryContextDelete(MemoryContext context)

        下面就寫MemoryContextMethods.delete的實現者負責AllocSet例項刪除的AllocSetDelete()這個函式以及相關的負責MemoryContext例項刪除的MemoryContextDelete()方法。先上圖,然後分塊解讀處理流程。

AllocSet/MemoryContext例項記憶體刪除流程圖

    先說紅色框吧,在紅色框部分,MemoryContextDelete方法檢查要刪除的context是否有效,然後呼叫MemoryContextDeleteChildren方法,檢查context的firstchild是否不為空,若不空就以firstchild指向的子context為引數呼叫MemoryContextDelete方法。這樣就以MemoryContextDelete方法和MemoryContextDeleteChildren方法形成了遞迴呼叫,以刪除當前的context及它的子context。

    接著看黃色框,在前面形成遞迴呼叫的基礎上,黃色框中主要是刪除context及其子context的nextchild指向的子context。

    再接著看藍色框,主要是在前面形成遞迴呼叫的基礎上,針對要刪除的context及其子context呼叫AllocSetDelelte方法,處理context的aset和blocks成員,把aset置空,把AllocBlock列表blocks中的block使用過的記憶體空間逐個置0X7F,然後調free釋放。這個blocks連結串列處理完後就到了綠色框中。

    現在看綠色框和紫色框,在綠色框中,還是在前面形成遞迴呼叫的基礎上,在綠色框中檢查要刪除的context的有效性,然後找到該context所在的AllockChunk型別例項chunk,根據該chunk找到其所屬的context,把要刪除的context和其所在的chunk所屬的context一起作為引數呼叫AllocSetFree方法去釋放要刪除的context所佔記憶體。AllocSetFree釋放記憶體在《pg的記憶體管理機制二》中已經討論過了,感興趣可以去看一下。

這樣就在以MemoryContextDelete方法和MemoryContextDeleteChildren方法形成的遞迴呼叫裡逐個刪除要刪除的context及其firstchild和nextchild成員“鏈”上的context。具體看流程圖吧。

        結合圖形看一個遞迴刪除MemoryContext型別例項時的順序的例子,圖中一個圓圈代表一個MemoryContext型別例項,在左下方的是MemoryContext的firstshild成員,在右下方的是nextchild成員。圖一是初始時的樣子,現在要刪除節點4,先順著4的firstchild遞迴到其最終葉子節點6,將其按上面說的過程刪除並釋放空間,如圖二。然後將節點4的nextchild節點7放到4的父節點3的nextchild子節點上,把節點3原來的nextchild子節點5放到節點7的nenxtchild子節點上,如圖三。這時已經處理完了節點4的兩個子節點,將節點4刪除。

就到這兒吧。