總結(jié)下常見的C++內(nèi)存池,以備以后查詢。
應(yīng)該說沒有一個(gè)內(nèi)存池適合所有的情況, 根據(jù)不同的需求選擇正確的內(nèi)存池才是正道.
(1)最簡單的固定大小緩沖池
適用于頻繁分配和釋放固定大小對象的情況, 關(guān)于這個(gè)內(nèi)存池,我這里總結(jié)過:一個(gè)高效的內(nèi)存池實(shí)現(xiàn)
(2)dlmalloc 應(yīng)該來說相當(dāng)優(yōu)秀的內(nèi)存池, 支持大對象和小對象,并且已被廣泛使用。到這里下載:ftp://g.oswego.edu/pub/misc/malloc.c 關(guān)于dlmalloc的內(nèi)部原理和使用資料可以參考:內(nèi)存分配器dlmalloc 2.8.3源碼淺析.doc
(3) SGI STL 中的內(nèi)存分配器( allocator )
SGI STL 的 allocator 應(yīng)該是目前設(shè)計(jì)最優(yōu)秀的 C++ 內(nèi)存分配器之一了,它的運(yùn)作原理候捷老師在《 STL 源碼剖析》里講解得非常清楚。基本思路是設(shè)計(jì)一個(gè) free_list[16] 數(shù)組,負(fù)責(zé)管理從 8 bytes 到 128 bytes 不同大小的內(nèi)存塊( chunk ),每一個(gè)內(nèi)存塊都由連續(xù)的固定大小( fixed size block )的很多 chunk 組成,并用指針鏈表串接起來。比如說
free_list[3]->start_notuse->next_notuse->next_notuse->...->end_notuse;
當(dāng)用戶要獲取此大小的內(nèi)存時(shí),就在 free_list 的鏈表找一個(gè)最近的 free chunk 回傳給用戶,同時(shí)將此 chunk 從 free_list 里刪除,即把此 chunk 前后 chunk 指針鏈結(jié)起來。用戶使用完釋放的時(shí)候,則把此chunk 放回到 free_list 中,應(yīng)該是放到最前面的 start_free 的位置。這樣經(jīng)過若干次 allocator 和 deallocator 后, free_list 中的鏈表可能并不像初始的時(shí)候那么是 chunk 按內(nèi)存分布位置依次鏈接的。假如free_list 中不夠時(shí), allocator 會自動(dòng)再分配一塊新的較大的內(nèi)存區(qū)塊來加入到 free_list 鏈表中。
可以自動(dòng)管理多種不同大小內(nèi)存塊并可以自動(dòng)增長的內(nèi)存池,這是 SGI STL 分配器設(shè)計(jì)的特點(diǎn)。
(4) Loki 中的小對象分配器( small object allocator )
Loki 的分配器與 SGI STL 的原理類似,不同之處是它管理 free_list 不是固定大小的數(shù)組,而是用一個(gè) vector 來實(shí)現(xiàn),因此可以用戶指定 fixed size block 的大小,不像 SGI STL 是固定最大 128 bytes 的。另外它管理 free chunks 的方式也不太一樣, Loki 是由一列記錄了 free block 位置等信息的 Chunk 類的鏈表來維護(hù)的, free blocks 則是分布在另外一個(gè)連續(xù)的大內(nèi)存區(qū)間中。而且 free Chunks 也可以根據(jù)使用情況自動(dòng)增長和減少合適的數(shù)目,避免內(nèi)存分配得過多或者過少。
(5) Boost 的 object_pool
Boost 中的 object_pool 也是一個(gè)可以根據(jù)用戶具體應(yīng)用類的大小來分配內(nèi)存塊的,也是通過維護(hù)一個(gè) free nodes 的鏈表來管理的。可以自動(dòng)增加 nodes 塊,初始是 32 個(gè) nodes ,每次增加都以兩倍數(shù)向 system heap 要內(nèi)存塊。 object_pool 管理的內(nèi)存塊需要在其對象銷毀的時(shí)候才返還給 system heap 。
(6)ACE 中的 ACE_Cached_Allocator 和 ACE_Free_List
ACE 框架中也有一個(gè)可以維護(hù)固定大小的內(nèi)存塊的分配器,原理與上面講的內(nèi)存池都差不多。它是通過在 ACE_Cached_Allocator 中定義個(gè) Free_list 鏈表來管理一個(gè)連續(xù)的大內(nèi)存塊的,里面包含很多小的固定大小的未使用的區(qū)塊( free chunk ),同時(shí)還使用 ACE_unbounded_Set 維護(hù)一個(gè)已使用的 chuncks ,管理方式與上面講的內(nèi)存池類似。也可以指定 chunks 的數(shù)目,也可以自動(dòng)增長,定義大致如下所示:
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的開源項(xiàng)目gperftools, 主頁在這里:https://code.google.com/p/gperftools/,該內(nèi)存池也被大家廣泛好評,并且在google的各種開源項(xiàng)目中被使用, 比如webkit就用到了它。
posted on 2013-04-08 20:53
Richard Wei 閱讀(17176)
評論(0) 編輯 收藏 引用 所屬分類:
C++