常見C++記憶體池技術
阿新 • • 發佈:2018-12-27
總結下常見的C++記憶體池,以備以後查詢。
應該說沒有一個記憶體池適合所有的情況, 根據不同的需求選擇正確的記憶體池才是正道.
(1)最簡單的固定大小緩衝池
適用於頻繁分配和釋放固定大小物件的情況, 關於這個記憶體池,我這裡總結過:一個高效的記憶體池實現
(2)dlmalloc
應該來說相當優秀的記憶體池, 支援大物件和小物件,並且已被廣泛使用。到這裡下載:ftp://g.oswego.edu/pub/misc/malloc.c
關於dlmalloc的內部原理和使用資料可以參考:記憶體分配器dlmalloc 2.8.3原始碼淺析.doc
(3) SGI STL 中的記憶體分配器( allocator )
free_list的連結串列找一個最近的free chunk回傳給使用者,同時將此chunk 從free_list裡刪除,即把此chunk前後chunk指標鏈結起來。使用者使用完釋放的時候,則把此chunk放回到free_list中,應該是放到最前面的start_free的位置。這樣經過若干次allocator和deallocator後,free_list中的連結串列可能並不像初始的時候那麼是chunk按記憶體分佈位置依次連結的。假如free_list中不夠時,allocator會自動再分配一塊新的較大的記憶體區塊來加入到free_list連結串列中。 SGI STL分配器設計的特點。
(4) Loki 中的小物件分配器( small object allocator )
Loki 的分配器與SGI STL 的原理類似,不同之處是它管理free_list 不是固定大小的陣列,而是用一個vector來實現,因此可以使用者指定fixed size block的大小,不像SGI STL 是固定最大128 bytes的。另外它管理free chunks的方式也不太一樣,Loki 是由一列記錄了free block位置等資訊的Chunk類的連結串列來維護的,free blocks則是分佈在另外一個連續的大記憶體區間中。而且free Chunks 也可以根據使用情況自動增長和減少合適的數目,避免記憶體分配得過多或者過少。
(5) Boost 的 object_pool
Boost中的object_pool也是一個可以根據使用者具體應用類的大小來分配記憶體塊的,也是通過維護一個free nodes的連結串列來管理的。可以自動增加nodes塊,初始是32 個nodes,每次增加都以兩倍數向system heap要記憶體塊。object_pool管理的記憶體塊需要在其物件銷燬的時候才返還給system heap。
(6)ACE中的 ACE_Cached_Allocator和 ACE_Free_List
class ACE_Cached_Allocator : public ACE_New_Allocator<T> {
public:
// Create a cached memory pool with @a n_chunks chunks
// each with sizeof (TYPE) size. ACE_Cached_Allocator(SIZET n_chunks = ACE_DEFAULT_INIT_CHUNKS);
T* allocate();
void deallocate(T* p);
private:
// List of memory that we have allocated. Fast_Unbounded_Set<char *> _allocated_chunks;
// Maintain a cached memory free list. ACE_Cached_Free_List<ACE_Cached_Mem_Pool_Node<T> > _free_list;
};(7)TCMalloc
應該說沒有一個記憶體池適合所有的情況, 根據不同的需求選擇正確的記憶體池才是正道.
(1)最簡單的固定大小緩衝池
適用於頻繁分配和釋放固定大小物件的情況, 關於這個記憶體池,我這裡總結過:一個高效的記憶體池實現
(2)dlmalloc
應該來說相當優秀的記憶體池, 支援大物件和小物件,並且已被廣泛使用。到這裡下載:ftp://g.oswego.edu/pub/misc/malloc.c
關於dlmalloc的內部原理和使用資料可以參考:記憶體分配器dlmalloc 2.8.3原始碼淺析.doc
(3) SGI STL 中的記憶體分配器( allocator )
SGI STL 的allocator應該是目前設計最優秀的C++ 記憶體分配器之一了,它的運作原理候捷老師在《STL原始碼剖析》裡講解得非常清楚。基本思路是設計一個free_list[16]陣列,負責管理從8 bytes到128 bytes不同大小的記憶體塊(chunk),每一個記憶體塊都由連續的固定大小(fixed size block)的很多chunk 組成,並用指標連結串列串接起來。比如說
free_list[3]->start_notuse->next_notuse->next_notuse->...->end_notuse;
當用戶要獲取此大小的記憶體時,就在
可以自動管理多種不同大小記憶體塊並可以自動增長的記憶體池,這是
(4) Loki 中的小物件分配器( small object allocator )
Loki 的分配器與SGI STL 的原理類似,不同之處是它管理free_list 不是固定大小的陣列,而是用一個vector來實現,因此可以使用者指定fixed size block的大小,不像SGI STL 是固定最大128 bytes的。另外它管理free chunks的方式也不太一樣,Loki 是由一列記錄了free block位置等資訊的Chunk類的連結串列來維護的,free blocks則是分佈在另外一個連續的大記憶體區間中。而且free Chunks 也可以根據使用情況自動增長和減少合適的數目,避免記憶體分配得過多或者過少。
(5) Boost 的 object_pool
Boost中的object_pool也是一個可以根據使用者具體應用類的大小來分配記憶體塊的,也是通過維護一個free nodes的連結串列來管理的。可以自動增加nodes塊,初始是32 個nodes,每次增加都以兩倍數向system heap要記憶體塊。object_pool管理的記憶體塊需要在其物件銷燬的時候才返還給system heap。
(6)ACE中的 ACE_Cached_Allocator和 ACE_Free_List
ACE框架中也有一個可以維護固定大小的記憶體塊的分配器,原理與上面講的記憶體池都差不多。它是通過在ACE_Cached_Allocator中定義個Free_list連結串列來管理一個連續的大記憶體塊的,裡面包含很多小的固定大小的未使用的區塊(free chunk),同時還使用ACE_unbounded_Set維護一個已使用的chuncks,管理方式與上面講的記憶體池類似。也可以指定chunks的數目,也可以自動增長,定義大致如下所示:
template<class T>class ACE_Cached_Allocator : public ACE_New_Allocator<T> {
public:
// Create a cached memory pool with @a n_chunks chunks
// each with sizeof (TYPE) size. ACE_Cached_Allocator(SIZET n_chunks = ACE_DEFAULT_INIT_CHUNKS);
T* allocate();
void deallocate(T* p);
private:
// List of memory that we have allocated. Fast_Unbounded_Set<char *> _allocated_chunks;
// Maintain a cached memory free list. ACE_Cached_Free_List<ACE_Cached_Mem_Pool_Node<T> > _free_list;
};(7)TCMalloc
Google的開源專案gperftools, 主頁在這裡:https://code.google.com/p/gperftools/,該記憶體池也被大家廣泛好評,並且在google的各種開源專案中被使用, 比如webkit就用到了它。
posted on 2013-04-08 20:53 Richard Wei 閱讀(10884) 評論(0) 編輯 收藏 引用 所屬分類: C++