Posted on 2009-09-17 22:34
浩毛 閱讀(7566)
評論(18) 編輯 收藏 引用 所屬分類:
C & C++
都知道頻繁分配內(nèi)存釋放內(nèi)存很耗系統(tǒng)資源,而且容易造成內(nèi)存碎片。因此寫了個簡單的內(nèi)存池實現(xiàn),越簡單越好,為什么?做復雜了效率還不如直接malloc。因此這個內(nèi)存池采用鏈表連接內(nèi)存塊的方式,分配的是固定大小的內(nèi)存塊,從池中取內(nèi)存和歸還內(nèi)存是用的空閑鏈表堆棧操作, 沒有使用線程鎖,如果要線程安全,建議在外部調(diào)用內(nèi)存池的地方加鎖。
做過一個簡單的測試,10萬次內(nèi)存池調(diào)用的效率大概比直接分配釋放內(nèi)存提高了30-50%。但是前提是內(nèi)存池不能加鎖(pthread_mutex),加鎖的內(nèi)存池效率和直接分配內(nèi)存的效率差不多,有時候還要多點點。(測試的環(huán)境是每次2K,4個雙核CPU,F(xiàn)REEBSD7)
代碼實現(xiàn):
struct memblock


{
int used;
void* data;
struct memblock* next;
struct memblock* createnext;
};
struct mempool
{
int size;//memblock大小
int unused;//空閑的memblock大小
int datasize;//每次分配的數(shù)據(jù)大小(就是memblock.data)
struct memblock* free_linkhead;//空閑memblock鏈表頭
struct memblock* create_linkhead;//所有創(chuàng)建的memblock鏈表頭,內(nèi)存池釋放的時候使用,防止內(nèi)存池釋放的似乎還有memblock未歸還的情況
};
typedef void (*free_callback)(void*);//釋放回調(diào)函數(shù),釋放membloc.data用,可以簡單的直接用free函數(shù)
void mempool_init(int initialSize,int datasize);//初始化mempool
void mempool_dealloc(struct mempool* pool,free_callback callback);//釋放mempool
void* mempool_get(struct mempool* pool);//獲取一個memblock
void mempool_release(struct mempool* pool,struct memblock* block);//歸還一個memblock
/*********************************
* mempool
* ******************************/
//malloc一個memblock
static struct memblock* mempool_allocblock( struct mempool* pool );
//------------------implement--------
void*
mempool_init( int initialSize, int datasize )
{
struct mempool* pool = malloc( sizeof( struct mempool ) );
pool->unused = 0;
pool->datasize = datasize;
pool->free_linkhead = NULL;
//預先初始化initialSize個內(nèi)存塊
pool->create_linkhead = NULL;
int i;
for ( i = 0; i < initialSize; i++ ) {
struct memblock* block = mempool_allocblock( pool );
mempool_release( pool, block );
}
return ( pool );
}
void
mempool_dealloc( struct mempool* pool, free_callback callback )
{
struct memblock* block = NULL;
//將所有創(chuàng)建的memblock釋放了
while ( pool->create_linkhead != NULL ) {
block = pool->create_linkhead;
pool->create_linkhead = pool->create_linkhead->createnext;
//執(zhí)行free回調(diào)。
if ( callback ) {
( *callback )( block->data );
}
free( block );
}
free( pool );
L_DEBUG( "%s:size(%d),unused(%d)", __func__, pool->size, pool->unused );
}
static struct memblock*
mempool_allocblock( struct mempool* pool )
{
struct memblock* block = malloc( sizeof( struct memblock ) );
block->data = malloc( sizeof( pool->datasize ) );
block->next = NULL;
block->used = 1;//表示已使用
//加入所有創(chuàng)建的memblock的鏈表頭
block->createnext = pool->create_linkhead;
pool->create_linkhead = block;
pool->size++;
return ( block );
}
void
mempool_release( struct mempool* pool, struct memblock* block )
{
if ( block == NULL ) {
L_WARN( "%s:release a NULL!", __func__ );
return;
}
if ( block->used != 1 ) {
L_WARN( "%s:used!=1", __func__ );
return;
}
//將歸還的內(nèi)存塊放到空閑鏈表頭。
block->used = 0;//表示空閑
block->next = pool->free_linkhead;
pool->free_linkhead = block;
pool->unused++;//空閑數(shù)+1
}
void*
mempool_get( struct mempool* pool )
{
struct memblock* block = NULL;
if ( pool->free_linkhead ) {
//從空閑鏈表頭取出一個內(nèi)存塊
block = pool->free_linkhead;
pool->free_linkhead = pool->free_linkhead->next;
block->next = NULL;
block->used = 1;//表示已使用
pool->unused--;//空閑內(nèi)存塊數(shù)-1
}
else {
//沒有空閑的內(nèi)存塊,創(chuàng)建一個
block = mempool_allocblock( pool );
}
return ( block );
}