源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

基于一个简单定长内存池的实现方法详解

  • 时间:2020-03-26 09:56 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:基于一个简单定长内存池的实现方法详解
    主要分为 3 个部分,memoryPool 是管理内存池类,block 表示内存块,chunk 表示每个存储小块。它们之间的关系为,memoryPool 中有一个指针指向某一起始 block,block 之前通过 next 指针构成链表结构的连接,每个 block 包含指定数量的 chunk。每次分配内存的时候,分配 chunk 中的数据地址。 [img]http://files.jb51.net/file_images/article/201305/2013050710241119.jpg[/img] [b]主要数据结构设计:[/b] [b]Block: [/b]
[u]复制代码[/u] 代码如下:
struct block {     block * next;//指向下一个block指针     unsigned int numofChunks;     unsigned int numofFreeChunks;//剩余free的chunk数量     unsigned int blockNum;//该block的编号     char * data;     queue<int> freepos; //记录可用chunk序号 };
MemoryPool:
[u]复制代码[/u] 代码如下:
class memoryPool {     unsigned int initNumofChunks; //每个block的chunk数量     unsigned int chunkSize;//每个chunk的数据大小     unsigned int steps;//每次扩展的chunk数量     unsigned int numofBlocks;//当前管理多少个blocks     block * blocksPtr;//指向起始block     block * blocksPtrTail;//指向末尾block     block * firstHasFreeChunksBlock;//指向第一个不为空的block };
[b]Chunk: [/b]ChunkNum:该 chunk 所在 block 里的编号 blockAddress: 该 chunk 所对应的 block,主要用于 free 这个 chunk 的时候,能够快速找到所属 block,并进行相应更新 data:实际供使用的数据起始位置 [b]关键操作说明:[/b] [b]内存分配:[/b] 从 firstHasFreeChunksBlock 开始查找第一个有 free 位置的 block,如果找到,则则获取该 block 的 freepos 的队首元素,返回该元素序号对应的 chunk 的数据地址,并将 freepos 的队首元素弹出,其他相关属性更新。如果找不到,则新增 steps 个 chunk,再重复上面的过程。 [b]内存释放:[/b] 传入待释放的地址指针p,通过对p的地址移动可以找到chunk中的 ChunkNum 和 blockAddress 两个数据,通过 blockAddress 可以找到该 chunk 所属的 block,然后将ChunkNum 添加到该 block 的 freepos 中,其他相应属性更新。 [b]使用方法: [/b]
[u]复制代码[/u] 代码如下:
memoryPool * mp = new memoryPool (256);     char * s = (char *)mp->allocate();   // 一些操作   mp->freeMemory(s);       delete mp;
不足: 没考虑线程安全问题,该实现方案在单线程下可以正常运行。 [b]程序源代码: [/b]
[u]复制代码[/u] 代码如下:
#include <iostream> #include <queue> #include <string.h> #include <ctime> using namespace std; struct block {     block * next;     unsigned int numofChunks;//指向下一个block指针     unsigned int numofFreeChunks;//剩余free的chunk数量     unsigned int blockNum;//该block的编号     char * data;     //记录可用chunk序号     queue<int> freepos;     block(unsigned int _numofChunks ,unsigned int _chunkSize, unsigned int _blockNum){         numofChunks =  _numofChunks;         numofFreeChunks = _numofChunks;         blockNum = _blockNum;         next = NULL;         data = new char [numofChunks * (sizeof(unsigned int) + sizeof(void *) + _chunkSize)];         char * p = data;         //每个chunk的结构:4byte的chunk序号 + 4byte的所属block地址 + 真正的数据         for(int i=0;i<numofChunks;i++){             char * ptr = p + i * (_chunkSize +  sizeof(unsigned int) + sizeof(void *));             unsigned int * num = (unsigned int *)(ptr);             *num = i;             ptr += sizeof(void *);             int * blockpos = (int *) ptr;             *blockpos = (int)this;             freepos.push(i);         }     }     ~block(){         delete [] data;     } }; class memoryPool { public :     memoryPool(unsigned int _chunkSize = 256, unsigned int _initNumofChunks = 4096, unsigned int _steps = 64){         initNumofChunks = _initNumofChunks;         chunkSize = _chunkSize;         steps = _steps;         numofBlocks = steps;         //创建内存池时,初始化一定数量的内存空间         block * p = new block(initNumofChunks, chunkSize, 0);         blocksPtr = p;         for(int i=1;i<steps;i++){             p->next = new block(initNumofChunks, chunkSize, i);             p = p->next;             blocksPtrTail = p;         }         firstHasFreeChunksBlock = blocksPtr;     }     ~memoryPool(){         block  * p = blocksPtr;         while(blocksPtr!=NULL){             p = blocksPtr->next;             delete blocksPtr;             blocksPtr = p;         }     }     /*     从firstHasFreeChunksBlock开始查找第一个有free位置的block,     如果找到,则则获取该block的freepos的对首元素,     返回该元素序号对应的chunk的数据地址,并将freepos的队首元素弹出,     其他相关属性更新。如果找不到,则新增steps个chunk,再重复上面的过程。     */     void * allocate(){         block * p = firstHasFreeChunksBlock;         while(p != NULL && p->numofFreeChunks <= 0) p = p->next;         if(p == NULL){             p = blocksPtrTail;             increaseBlocks();             p = p->next;             firstHasFreeChunksBlock = p;         }         unsigned int pos =  p->freepos.front();         void * chunkStart = (void *)(p->data + pos * (chunkSize +  sizeof(unsigned int) + sizeof(void *)));         void * res = chunkStart + sizeof(unsigned int) + sizeof(void *);         p->freepos.pop();         p->numofFreeChunks --;         return res;     }     void increaseBlocks(){         block * p = blocksPtrTail;         for(int i=0; i<steps; i++){             p->next = new block(initNumofChunks, chunkSize, numofBlocks);             numofBlocks++;             p = p->next;             blocksPtrTail = p;         }     }     /*     传入待释放的地址指针_data,     通过对_data的地址移动可以找到chunk中的ChunkNum和blockAddress两个数据,     通过blockAddress可以找到该chunk所属的block,     然后将ChunkNum添加到该block的freepos中,其他相应属性更新。     */     void freeMemory(void * _data){         void * p = _data;         p -= sizeof(void *);         int * blockpos = (int *) p;         block * b = (block *) (*blockpos);         p -= sizeof(unsigned int);         int * num = (int *) p;         b->freepos.push(*num);         b->numofFreeChunks ++;         if (b->numofFreeChunks > 0 && b->blockNum < firstHasFreeChunksBlock->blockNum)             firstHasFreeChunksBlock = b;     } private :     unsigned int initNumofChunks; //每个block的chunk数量     unsigned int chunkSize;//每个chunk的数据大小     unsigned int steps;//每次扩展的chunk数量     unsigned int numofBlocks;//当前管理多少个blocks     block * blocksPtr;//指向起始block     block * blocksPtrTail;//指向末尾block     block * firstHasFreeChunksBlock;//指向第一个不为空的block }; //test void echoPositionNum(char * p){     p -= (sizeof(void *) + sizeof(unsigned int));     int * num = (int *) p;     cout<<*num<<endl; } //测试 void test0(){     memoryPool mp;     char * s1 = (char *)mp.allocate();     char * s2 = (char *)mp.allocate();     char str [256];     char str2 [256];     char str3 [256];     for(int i=0; i<255; i++) {         str[i] = 'a';str2[i] = 'b';str3[i] = 'c';     }     str[255] = '\0';     str2[255] = '\0';     strcpy(s1,str);     strcpy(s2,str2);     str3[255] = '\0';     echoPositionNum(s1);     cout<<s1<<endl;     mp.freeMemory(s1);     echoPositionNum(s2);     cout<<s2<<endl;     char * s3 = (char *)mp.allocate();     strcpy(s3,str3);     echoPositionNum(s3);     cout<<s3<<endl; } void test1(){     clock_t clock_begin = clock();     const int N = 50000;     char * s[N];     int round = 100;     while(round>=0){         round --;         for(int i=0;i<N;i++){             s[i] = new char[256];         }         for(int i=0;i<N;i++){              delete [] s[i];         }     }     clock_t clock_end = clock();     cout<<"Time cost\t"<<clock_end - clock_begin<<endl; } void test2(){     memoryPool mp(256);     clock_t clock_begin = clock();     const int N = 50000;     char * s[N];     int round = 100;     while(round>=0){         round --;         for(int i=0;i<N;i++){             s[i] = (char *)mp.allocate();         }         for(int i=0;i<N;i++){             mp.freeMemory(s[i]);         }     }     clock_t clock_end = clock();     cout<<"Time cost\t"<<clock_end - clock_begin<<endl; } int main() {     test0();     test1();     test2();     return 0; }
[b]运行结果: [/b] [img]http://files.jb51.net/file_images/article/201305/2013050710241121.png[/img]
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部