栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

    主要分为 3 个部分,memoryPool 是管理内存池类,block 表示内存块,chunk 表示每个存储小块。它们之间的关系为,memoryPool 中有一个指针指向某一起始 block,block 之前通过 next 指针构成链表结构的连接,每个 block 包含指定数量的 chunk。每次分配内存的时候,分配 chunk 中的数据地址。

主要数据结构设计:

Block:
复制代码 代码如下:
struct block {
    block * next;//指向下一个block指针
    unsigned int numofChunks;
    unsigned int numofFreeChunks;//剩余free的chunk数量
    unsigned int blockNum;//该block的编号
    char * data;
    queue freepos; //记录可用chunk序号
};

MemoryPool:
复制代码 代码如下:
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
};

Chunk:

ChunkNum:该 chunk 所在 block 里的编号

blockAddress: 该 chunk 所对应的 block,主要用于 free 这个 chunk 的时候,能够快速找到所属 block,并进行相应更新

data:实际供使用的数据起始位置

关键操作说明:

内存分配:

从 firstHasFreeChunksBlock 开始查找第一个有 free 位置的 block,如果找到,则则获取该 block 的 freepos 的队首元素,返回该元素序号对应的 chunk 的数据地址,并将 freepos 的队首元素弹出,其他相关属性更新。如果找不到,则新增 steps 个 chunk,再重复上面的过程。

内存释放:

传入待释放的地址指针p,通过对p的地址移动可以找到chunk中的 ChunkNum 和 blockAddress 两个数据,通过 blockAddress 可以找到该 chunk 所属的 block,然后将ChunkNum 添加到该 block 的 freepos 中,其他相应属性更新。

使用方法:
复制代码 代码如下:
memoryPool * mp = new memoryPool (256);  
  char * s = (char *)mp->allocate();
  // 一些操作
  mp->freeMemory(s);    
  delete mp;

不足:

没考虑线程安全问题,该实现方案在单线程下可以正常运行。

程序源代码:
复制代码 代码如下:
#include
#include
#include
#include
using namespace std;

struct block {
    block * next;
    unsigned int numofChunks;//指向下一个block指针
    unsigned int numofFreeChunks;//剩余free的chunk数量
    unsigned int blockNum;//该block的编号
    char * data;
    //记录可用chunk序号
    queue 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            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            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;
        }
    }

   
    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            p->next = new block(initNumofChunks, chunkSize, numofBlocks);
            numofBlocks++;
            p = p->next;
            blocksPtrTail = p;
        }
    }
   
    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<}

//测试
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] = '';
    str2[255] = '';
    strcpy(s1,str);
    strcpy(s2,str2);
    str3[255] = '';
    echoPositionNum(s1);

    cout<    mp.freeMemory(s1);
    echoPositionNum(s2);
    cout<    char * s3 = (char *)mp.allocate();
    strcpy(s3,str3);

    echoPositionNum(s3);
    cout<

}

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            s[i] = new char[256];
        }
        for(int i=0;i             delete [] s[i];
        }
    }
    clock_t clock_end = clock();
    cout<<"Time costt"<}

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            s[i] = (char *)mp.allocate();
        }
        for(int i=0;i            mp.freeMemory(s[i]);
        }
    }
    clock_t clock_end = clock();
    cout<<"Time costt"<

}
int main()
{
    test0();
    test1();
    test2();
    return 0;
}

运行结果:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/66739.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号