http://www.cppblog.com/jaxe/archive/2009/09/17/96581.html
都知道频繁分配内存释放内存很耗系统资源,而且容易造成内存碎片。因此写了个简单的内存池实现,越简单越好,为什么?做复杂了效率还不如直接malloc。因此这个内存池采用链表连接内存块的方式,分配的是固定大小的内存块,从池中取内存和归还内存是用的空闲链表堆栈操作, 没有使用线程锁,如果要线程安全,建议在外部调用内存池的地方加锁。做过一个简单的测试,10万次内存池调用的效率大概比直接分配释放内存提高了30-50%。但是前提是内存池不能加锁(pthread_mutex),加锁的内存池效率和直接分配内存的效率差不多,有时候还要多点点。(测试的环境是每次2K,4个双核CPU,FREEBSD7)
代码实现:
struct
memblock
{
int used;
void* data;
struct memblock* next;
struct memblock* createnext;
} ;
{
int used;
void* data;
struct memblock* next;
struct memblock* createnext;
} ;
struct
mempool
{
int size; // memblock大小
int unused; // 空闲的memblock大小
int datasize; // 每次分配的数据大小(就是memblock.data)
struct memblock * free_linkhead; // 空闲memblock链表头
struct memblock * create_linkhead; // 所有创建的memblock链表头,内存池释放的时候使用,防止内存池释放的似乎还有memblock未归还的情况
};
typedef void ( * free_callback)( void * ); // 释放回调函数,释放membloc.data用,可以简单的直接用free函数
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个内存块
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;
// 将所有创建的memblock释放了
while ( pool -> create_linkhead != NULL ) {
block = pool -> create_linkhead;
pool -> create_linkhead = pool -> create_linkhead -> createnext;
// 执行free回调。
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 ; // 表示已使用
// 加入所有创建的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 ;
}
// 将归还的内存块放到空闲链表头。
block -> used = 0 ; // 表示空闲
block -> next = pool -> free_linkhead;
pool -> free_linkhead = block;
pool -> unused ++ ; // 空闲数+1
}
void *
mempool_get( struct mempool * pool )
{
struct memblock * block = NULL;
if ( pool -> free_linkhead ) {
// 从空闲链表头取出一个内存块
block = pool -> free_linkhead;
pool -> free_linkhead = pool -> free_linkhead -> next;
block -> next = NULL;
block -> used = 1 ; // 表示已使用
pool -> unused -- ; // 空闲内存块数-1
}
else {
// 没有空闲的内存块,创建一个
block = mempool_allocblock( pool );
}
return ( block );
}
{
int size; // memblock大小
int unused; // 空闲的memblock大小
int datasize; // 每次分配的数据大小(就是memblock.data)
struct memblock * free_linkhead; // 空闲memblock链表头
struct memblock * create_linkhead; // 所有创建的memblock链表头,内存池释放的时候使用,防止内存池释放的似乎还有memblock未归还的情况
};
typedef void ( * free_callback)( void * ); // 释放回调函数,释放membloc.data用,可以简单的直接用free函数
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个内存块
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;
// 将所有创建的memblock释放了
while ( pool -> create_linkhead != NULL ) {
block = pool -> create_linkhead;
pool -> create_linkhead = pool -> create_linkhead -> createnext;
// 执行free回调。
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 ; // 表示已使用
// 加入所有创建的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 ;
}
// 将归还的内存块放到空闲链表头。
block -> used = 0 ; // 表示空闲
block -> next = pool -> free_linkhead;
pool -> free_linkhead = block;
pool -> unused ++ ; // 空闲数+1
}
void *
mempool_get( struct mempool * pool )
{
struct memblock * block = NULL;
if ( pool -> free_linkhead ) {
// 从空闲链表头取出一个内存块
block = pool -> free_linkhead;
pool -> free_linkhead = pool -> free_linkhead -> next;
block -> next = NULL;
block -> used = 1 ; // 表示已使用
pool -> unused -- ; // 空闲内存块数-1
}
else {
// 没有空闲的内存块,创建一个
block = mempool_allocblock( pool );
}
return ( block );
}