zoukankan      html  css  js  c++  java
  • HM 内存池设计(1)内存池设计

    综合 参考了

    a.C++ 应用程序性能优化,第 6 章:内存池
    http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html

    b.ARP内存池的设计。 http://www.cnblogs.com/bangerlee/archive/2011/09/01/2161437.html

    1.MemBlock

    typedef struct MemBlock
    {
    	uint32_t	index;//size
    	uint32_t	nfree;//可用的最小内存单元数
    	uint32_t	nfirst;//下一个最小可用内存单元编号
    	struct MemBlock*	pNextBlock;//下一个index值相同的MemBlock
    #ifdef MEM_ANALYSIS
    	uint32_t	max_used;//达到的用到的chunk数目最大值
    #endif
    }MemBlock;
     

    MemBlock 结构与a.的结构类似,index源自ARP中的index。一个memblock由MemBlock+nfree个chunk内存单元组成。

    chunk的size为BOUNDARY_SIZE*(index+1)字节.每个chunk的头4个字节记录了所在的MemBlock的地址(如果没有pNextBlock可直接用index获得,或通过地址范围计算),

    5-8个字节存放下一个可用的chunk的id.

    之后又加入了struct MemBlock* pNextBlock;指针,当nfree为0或该index的memblock已没有可用chunk时,malloc一个新的memblock并挂在其后(单向链表).

    2.memblok 的管理mempool

    typedef struct MemPool
    {

    MemBlock *freeblock[MAX_INDEX];
    char *pMemory;
    }MemPool;

    pMemory 指向所分配的一整块大内存池,freeblock[i]指向index为i的memblock.

    源代码:

    /*
     ============================================================================
     Name        : mempool.h
     Author      : mlj
     Version     : 0.1
     ============================================================================
     */
    
    #ifndef MEMPOOL_
    #define MEMPOOL_
    #include <stdint.h>
    
    #define MEM_ANALYSIS //统计memory的信息
    #define  MAX_INDEX 20 
    typedef struct MemBlock
    {
    	uint32_t	index;//size
    	uint32_t	nfree;//可用的最小内存单元数
    	uint32_t	nfirst;//下一个最小可用内存单元编号
    	struct MemBlock*	pNextBlock;//下一个index值相同的MemBlock
    #ifdef MEM_ANALYSIS
    	uint32_t	max_used;//达到的用到的chunk数目最大值
    #endif
    }MemBlock;
    
    typedef struct MemPool
    {
    	MemBlock *freeblock[MAX_INDEX];
    	char *pMemory;
    }MemPool;
    #endif
    /*
     ============================================================================
     Name        : mempool.c
     Author      : mlj
     Version     : 0.1
     ============================================================================
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <memory.h>
    #include "mempool.h"
    
    char max_free_chunk[MAX_INDEX]={
    	0,10,10,10,10,
    	10,10,10,10,10,
    	0,0,0,0,0,
    	0,0,0,0,0};
    
    MemPool mypool;
    
    #define BOUNDARY_INDEX 12
    #define BOUNDARY_SIZE (1 << BOUNDARY_INDEX)
    
    #define CHUNK_HEAD_SIZE ( sizeof(MemBlock*)+sizeof(uint32_t) ) 
    #define CHUNK_DATA_SIZE(index)	( (size_t)BOUNDARY_SIZE*(index+1))  // 4096*(1<<19)  默认为int 类型,会越界
    #define MEMBLOCK_SIZE(index)	( sizeof(MemBlock) + max_free_chunk[(index)]*( CHUNK_HEAD_SIZE + CHUNK_DATA_SIZE(index) ) )
     
    #define APR_ALIGN(size, boundary)   (((size)+ ((boundary) - 1)) &~((boundary) - 1))
    
    
    void MemBlock_init(MemBlock *block,uint32_t max_free_chunk)
    {
    	uint32_t i = 0;
    	char *p = NULL;
    	block->nfree = max_free_chunk;
    	block->nfirst = 0;
    	block->pNextBlock = NULL;
    #ifdef MEM_ANALYSIS
    	block->max_used = 0;
    #endif
    	p = (char*)block;
    	((char*)p) += sizeof(MemBlock); //第0个chunk头地址
    	for(i=0;i<block->nfree;i++)
    	{
    		( *((MemBlock**)p) ) = (MemBlock*)block; //chunk 头四个字节存放所在的MemBlock的地址
    		((char*)p) += sizeof(MemBlock*);
    		*((uint32_t*)p) = i+1; //5-8个字节存放下一个可用的chunk的index
    		((char*)p) += sizeof(uint32_t)+CHUNK_DATA_SIZE(block->index);
    	}
    }
    
    void MemPool_create(MemPool *pool)
    {
    	size_t pool_size = 0;//
    	size_t i;
    	char* p = NULL;
    	for (i=0;i<MAX_INDEX;i++)
    	{
    		pool_size += MEMBLOCK_SIZE(i);
    	}
    	
    	p = (char *)malloc(pool_size);
    	if(p == NULL)
    	{
    		printf("memory malloc failed!/n");
    		exit(0);
    	}
    	
    	memset(p,0,pool_size);
    	pool->pMemory = p;
    
    	for (i=0;i<MAX_INDEX;i++)
    	{
    		pool->freeblock[i] = (MemBlock*) (p);
    		pool->freeblock[i]->index = i;
    		MemBlock_init(pool->freeblock[i],max_free_chunk[i]);
    		((char*)p) += MEMBLOCK_SIZE(i);//注意转为char* 在加偏移
    	}	
    }
    
    void MemPool_destroy(MemPool *pool)
    {
    	size_t i;
    #ifdef MEM_ANALYSIS
    	size_t pool_size = 0;//max_free_chunk[19] 不为0时,size_t的数据范围会不够
    	for (i=0;i<MAX_INDEX;i++)
    	{
    		pool_size += MEMBLOCK_SIZE(i);
    	}
    	printf("MemPool analysis:\n");
    	printf("Total malloc memory size:%dKB  %dM\n",pool_size>>10,pool_size>>20);
    	printf("index   :");
    	for (i=0;i<MAX_INDEX/2;i++)
    	{
    		printf("%4d",i);
    	}
    	printf("\nmax_used:");
    	for (i=0;i<MAX_INDEX/2;i++)
    	{
    		MemBlock* pblock = NULL;
    		uint32_t max_used = 0;
    		pblock = mypool.freeblock[i];
    		do 
    		{
    			max_used += pblock->max_used;
    		}while (pblock=pblock->pNextBlock);
    		printf("%4d",max_used);
    	}
    	printf("\nindex   :");
    	for (i=MAX_INDEX/2;i<MAX_INDEX;i++)
    	{
    		printf("%4d",i);
    	}
    	printf("\nmax_used:");
    	for (i=MAX_INDEX/2;i<MAX_INDEX;i++)
    	{
    		MemBlock* pblock = NULL;
    		uint32_t max_used = 0;
    		pblock = mypool.freeblock[i];
    		do 
    		{
    			max_used += pblock->max_used;
    		}while (pblock=pblock->pNextBlock);
    		printf("%4d",max_used);
    	}
    #endif
    
    	for (i=0;i<MAX_INDEX;i++)
    	{
    		MemBlock* pblock = NULL;
    		pblock = mypool.freeblock[i];
    		while (pblock->pNextBlock)
    		{
    			MemBlock* tmp = pblock->pNextBlock;
    			pblock->pNextBlock = tmp->pNextBlock;
    			free(tmp);
    		}
    	}
    	free(pool->pMemory);
    	pool->pMemory = NULL;
    }
    
    void* MemPool_malloc(size_t in_size)
    {
    	size_t size;
    	size_t index;
        size = APR_ALIGN(in_size , BOUNDARY_SIZE);
        if (size < in_size) {
            return NULL;
        }
        if (size < BOUNDARY_SIZE)
            size = BOUNDARY_SIZE;
    
        /* Find the index for this node size by
         * dividing its size by the boundary size
         */
        index = (size >> BOUNDARY_INDEX) - 1;
        
        if (index > MAX_INDEX) {
            return NULL; //大于max_index的大小内存的处理
        }
    
    	if (index<=MAX_INDEX)
    	{
    		MemBlock* pblock = NULL;
    		pblock = mypool.freeblock[index];
    		 //寻找block链表上第一个存在空闲chunk的block
    		do 
    		{
    			if (pblock->nfree>0) //找到,退出
    			{
    				break;
    			}
    			else if (pblock->pNextBlock == NULL) //已满,下一memblock又不存在
    			{
    				char *p = NULL;
    				if (max_free_chunk[index] == 0)
    				{
    					max_free_chunk[index] = 1;
    				}
    				
    				p = (char*) malloc(MEMBLOCK_SIZE(index));
    				if (p == NULL)
    				{
    					printf("memory malloc failed!/n");
    					exit(0);
    				}
    				memset(p,0,MEMBLOCK_SIZE(index));				
    				pblock->pNextBlock = (MemBlock*) (p);
    				pblock->pNextBlock->index = index;
    				pblock=pblock->pNextBlock;
    				MemBlock_init(pblock,max_free_chunk[index]);
    				break;
    			}
    			else
    			{
    				pblock=pblock->pNextBlock;
    			}
    		}while (pblock);
    		
    		
    		if (pblock->nfree > 0)
    		{
    			uint32_t chunk_id = pblock->nfirst;//待分配的chunk的id
    			char* pchunk = (char*)( pblock ) + sizeof(MemBlock)+ CHUNK_DATA_SIZE(index)*chunk_id;//第index个chunk的首地址
    			pchunk = pchunk + sizeof(MemBlock*) ;//向后偏移四个字节,指向chunk id 区
    			pblock->nfirst = *((uint32_t*)pchunk) ;//更新下一个可用chunk的id
    			*((uint32_t*)pchunk) = chunk_id; //已分配出去的chunk,chunkid区记下自己的id
    			pblock->nfree--;
    #ifdef MEM_ANALYSIS
    			{
    				uint32_t used_chunk = max_free_chunk[index]-pblock->nfree;
    				if (used_chunk>pblock->max_used)
    				{
    					pblock->max_used = used_chunk;
    				}
    			}
    #endif
    			return ( (char*)pchunk + sizeof(uint32_t) );
    		}
    		else
    		{
    			return NULL;
    		}
    	}
    	return NULL;
    }
    
    void MemPool_free(void* _Memory)
    {
    	MemBlock *pblock = NULL;
    	pblock = *( (MemBlock**)((char*)_Memory - CHUNK_HEAD_SIZE) ); //获取该chunk所在的block地址
    
    	if (pblock->index <=MAX_INDEX)
    	{//释放的chunk 挂到最前面,第一个可用的chunk
    		uint32_t chunk_id = pblock->nfirst;
    		char* poffset = ((char*)_Memory - sizeof(uint32_t)) ;//chunk_id地址
    		pblock->nfirst =  * ( (uint32_t*)(poffset) );
    		* ( (uint32_t*)(poffset) ) = chunk_id ;
    		memset(_Memory,0,CHUNK_DATA_SIZE(pblock->index));//数据区置0 
    	}
    }
    
    int main()
    {
    	char* p1[10];
    	int i;
    	MemPool_create(&mypool);
    	for (i=0;i<6;i++)
    	{
    		p1[i]=(char*) MemPool_malloc(1024<<i);
    	}
    	for (i=0;i<6;i++)
    	{
    		MemPool_free(p1[i]);
    		p1[i] = NULL;	
    	}
    
    	MemPool_destroy(&mypool);
    }
  • 相关阅读:
    小程序路由
    机器学习笔记—支持向量机(1)
    用极大似然估计法推出朴素贝叶斯法中的先验概率估计公式
    机器学习笔记—生成学习
    机器学习笔记—再谈广义线性模型
    机器学习笔记—指数分布簇和广义线性模型
    机器学习笔记—Logistic 回归
    机器学习笔记—局部权重线性回归
    机器学习笔记—线性回归
    机器学习笔记1
  • 原文地址:https://www.cnblogs.com/mlj318/p/2540426.html
Copyright © 2011-2022 走看看