用了《Modern C++ Design》上的那个Chunk,在Chunk查找Block的时间是O(1),但是在MemPool的ChunkList里面查找某内存地址却需要O(n)的时间复杂度,因为我的算法只是线性的便利ChunkLisk的链表,所以但内存池里面同时存在大量小对象时候,效果不是很好,比普通的new还差,但是如果内存池内同时存在的小对象的数目较小的时候,可以获得不错的性能,计划version2.0要改进算法,但是尝试加Map做O(logn)的查找,效果很不好,常数太大了,如果加hash又耗太多内存,暂时没什么想法,估计要改数据结构了,+个freelist可以实现new操作O(1)但是free操作很难搞,怎样快速定位某个内存属于哪个Chunk呢?有点难度,再看看书,再想想。
Chunk.h
 #ifndef CHUNK_H
#ifndef CHUNK_H
 #define CHUNK_H
#define CHUNK_H

 #include <cassert>
#include <cassert>


 struct Chunk
struct Chunk  {
{
 //初始化一个Chunk
    //初始化一个Chunk
 void init(size_t blockSize, unsigned char blocks);
    void init(size_t blockSize, unsigned char blocks); 
 //分配一个block
    //分配一个block
 void* allocate(size_t blockSize);
    void* allocate(size_t blockSize); 
 //回收一个block
    //回收一个block
 void deallocate(void* p, size_t blockSize);
    void deallocate(void* p, size_t blockSize); 
 //Chunk的起始地址
    //Chunk的起始地址
 unsigned char* pData_;
    unsigned char* pData_; 
 //第一个可用的block
    //第一个可用的block
 unsigned char firstAvailableBlock_;
    unsigned char firstAvailableBlock_; 
 //block的块数
    //block的块数
 unsigned char blocksAvailable_;
    unsigned char blocksAvailable_; 
 //析构函数释放内存
    //析构函数释放内存
 ~Chunk();
    ~Chunk();
 };
};


 void Chunk::init(size_t blockSize, unsigned char blocks)
void Chunk::init(size_t blockSize, unsigned char blocks)  {
{
 //从操作系统申请一个Chunk的内存
    //从操作系统申请一个Chunk的内存
 pData_ = new unsigned char[blockSize * blocks];
    pData_ = new unsigned char[blockSize * blocks];
 firstAvailableBlock_ = 0;
    firstAvailableBlock_ = 0;
 blocksAvailable_ = blocks;
    blocksAvailable_ = blocks;
 unsigned char *p = pData_;
    unsigned char *p = pData_;
 //每个可用的block存放它下一个可用的block的编号
    //每个可用的block存放它下一个可用的block的编号

 for (unsigned char i = 1; i < blocks; i++, p += blockSize)
    for (unsigned char i = 1; i < blocks; i++, p += blockSize)  {
{
 *p = i;
        *p = i;
 }
    }
 }
}


 void* Chunk::allocate(size_t blockSize)
void* Chunk::allocate(size_t blockSize)  {
{
 if (blocksAvailable_ == 0) return 0;
    if (blocksAvailable_ == 0) return 0;
 unsigned char* pRet = pData_ + (firstAvailableBlock_ * blockSize);
    unsigned char* pRet = pData_ + (firstAvailableBlock_ * blockSize);
 //更新第一个可用的block
    //更新第一个可用的block
 firstAvailableBlock_ = *pRet;
    firstAvailableBlock_ = *pRet;
 blocksAvailable_--;
    blocksAvailable_--;
 return pRet;
    return pRet;
 }
}


 void  Chunk::deallocate(void* p, size_t blockSize)
void  Chunk::deallocate(void* p, size_t blockSize)  {
{
 //判断回收的地址是否合法
    //判断回收的地址是否合法
 assert(p >= pData_);
    assert(p >= pData_);
 unsigned char* toRel = static_cast<unsigned char*>(p);
    unsigned char* toRel = static_cast<unsigned char*>(p);
 //判断是否合法
    //判断是否合法
 assert((toRel - pData_) % blockSize == 0);
    assert((toRel - pData_) % blockSize == 0);
 *toRel = firstAvailableBlock_;
    *toRel = firstAvailableBlock_;
 firstAvailableBlock_ = static_cast<unsigned char>((toRel - pData_) / blockSize);
    firstAvailableBlock_ = static_cast<unsigned char>((toRel - pData_) / blockSize);
 //判断是否产生精度误差
    //判断是否产生精度误差
 assert(firstAvailableBlock_ == ((toRel - pData_) / blockSize));
    assert(firstAvailableBlock_ == ((toRel - pData_) / blockSize));
 blocksAvailable_++;
    blocksAvailable_++;
 }
}


 Chunk::~Chunk()
Chunk::~Chunk()  {
{
 delete[] pData_;
    delete[] pData_;
 }
}
 #endif
#endif
MemPool.h
 #ifndef MEMPOOL_H
#ifndef MEMPOOL_H
 #define MEMPOOL_H
#define MEMPOOL_H

 #include "Chunk.h"
#include "Chunk.h"


 struct ChunkList
struct ChunkList  {
{
 Chunk* valChunk_;
    Chunk* valChunk_;
 ChunkList* next_;
    ChunkList* next_;

 ChunkList() : valChunk_(new Chunk), next_(0)
    ChunkList() : valChunk_(new Chunk), next_(0)  {}
{}

 ~ChunkList()
    ~ChunkList()  {delete valChunk_;}
{delete valChunk_;}
 };
};


 class MemPool
class MemPool  {
{
 public :
public :
 MemPool(size_t blockSize);
    MemPool(size_t blockSize);
 ~MemPool();
    ~MemPool();
 void* alloc(size_t size);
    void* alloc(size_t size);
 void free(void* p, size_t size);
    void free(void* p, size_t size);
 private :
private :
 //新分配一个Chunk
    //新分配一个Chunk
 ChunkList* allocChunk();
    ChunkList* allocChunk(); 
 //释放一个Chunk
    //释放一个Chunk
 void freeChunk(ChunkList* pChunkList);
    void freeChunk(ChunkList* pChunkList);

 //一个Chunk所拥有的Block数
    //一个Chunk所拥有的Block数
 static const int BLOCKS;
    static const int BLOCKS;
 //free的Chunk
    //free的Chunk
 ChunkList* headOfChunkList_;
    ChunkList* headOfChunkList_;
 size_t blockSize_;
    size_t blockSize_;
 };
};

 const int MemPool::BLOCKS = 255;
const int MemPool::BLOCKS = 255;


 MemPool::MemPool(size_t blockSize) : blockSize_(blockSize), headOfChunkList_(0)
MemPool::MemPool(size_t blockSize) : blockSize_(blockSize), headOfChunkList_(0)  {};
{};


 MemPool::~MemPool()
MemPool::~MemPool()  {
{

 while (headOfChunkList_)
    while (headOfChunkList_)  {
{
 freeChunk(headOfChunkList_);
        freeChunk(headOfChunkList_);
 }
    }
 }
}


 void* MemPool::alloc(size_t size)
void* MemPool::alloc(size_t size)  {
{

 if (size != blockSize_)
    if (size != blockSize_)  {
{
 return ::operator new(size);
        return ::operator new(size);
 }
    }
 //查找可用的Block
    //查找可用的Block
 ChunkList* p = headOfChunkList_;
    ChunkList* p = headOfChunkList_;
 while (p && !p->valChunk_->blocksAvailable_) p = p->next_;
    while (p && !p->valChunk_->blocksAvailable_) p = p->next_;

 if (!p) p = allocChunk();
    if (!p) p = allocChunk();
 void* pRet = p->valChunk_->allocate(blockSize_);
    void* pRet = p->valChunk_->allocate(blockSize_);
 return pRet;
    return pRet;
 }
}



 void MemPool::free(void* p, size_t size)
void MemPool::free(void* p, size_t size)  {
{
 if (!p) return ;
    if (!p) return ;

 if (size != blockSize_)
    if (size != blockSize_)  {
{
 ::operator delete(p);
        ::operator delete(p);
 return ;
        return ;
 }
    }
 //查找p所属的Chunk
    //查找p所属的Chunk
 ChunkList* pTmp = headOfChunkList_;
    ChunkList* pTmp = headOfChunkList_;

 while (pTmp)
    while (pTmp)  {
{
 if (p >= pTmp->valChunk_->pData_ && p < pTmp->valChunk_->pData_ + (blockSize_ * BLOCKS)) break;
        if (p >= pTmp->valChunk_->pData_ && p < pTmp->valChunk_->pData_ + (blockSize_ * BLOCKS)) break;
 pTmp = pTmp->next_;
        pTmp = pTmp->next_;
 }
    }
 if (!pTmp) return ;
    if (!pTmp) return ;
 pTmp->valChunk_->deallocate(p, blockSize_);
    pTmp->valChunk_->deallocate(p, blockSize_);
 }
}


 ChunkList* MemPool::allocChunk()
ChunkList* MemPool::allocChunk()  {
{
 ChunkList* pTmpChunkList = new ChunkList;
    ChunkList* pTmpChunkList = new ChunkList;
 //新建一个Chunk
    //新建一个Chunk
 pTmpChunkList->valChunk_->init(blockSize_, BLOCKS);
    pTmpChunkList->valChunk_->init(blockSize_, BLOCKS);
 //把这个Chunk加入到ChunkList的链表头
    //把这个Chunk加入到ChunkList的链表头
 pTmpChunkList->next_ = headOfChunkList_;
    pTmpChunkList->next_ = headOfChunkList_;
 headOfChunkList_ = pTmpChunkList;
    headOfChunkList_ = pTmpChunkList;
 return pTmpChunkList;
    return pTmpChunkList;
 }
}


 void MemPool::freeChunk(ChunkList* pChunkList)
void MemPool::freeChunk(ChunkList* pChunkList)  {
{
 //在链表中查找
    //在链表中查找
 if (!pChunkList) return ;
    if (!pChunkList) return ;
 ChunkList* p, * q;
    ChunkList* p, * q;
 p = headOfChunkList_;
    p = headOfChunkList_;
 q = p->next_;
    q = p->next_;

 if (p == pChunkList)
    if (p == pChunkList)  {
{
 //在表头
        //在表头
 headOfChunkList_ = p->next_;
        headOfChunkList_ = p->next_;
 delete pChunkList;
        delete pChunkList;
 return ;
        return ;
 }
    }

 while (q && q != pChunkList)
    while (q && q != pChunkList)  {
{
 p = q;
        p = q;
 q = q->next_;
        q = q->next_;
 }
    }

 if (q)
    if (q)  {
{
 //查找成功
        //查找成功
 p->next_ = q->next_;
        p->next_ = q->next_;
 delete pChunkList;
        delete pChunkList;
 }
    }
 }
}


 #endif
#endiftest.cpp
 #include <iostream>
#include <iostream>
 #include "MemPool.h"
#include "MemPool.h"
 #include "time.h"
#include "time.h"
 using namespace std;
using namespace std;


 class TestClassA
class TestClassA  {
{
 public :
public :
 int a;
    int a;
 static void* operator new(size_t size);
    static void* operator new(size_t size);
 static void operator delete(void *p, size_t size);
    static void operator delete(void *p, size_t size);
 static MemPool memPool;
    static MemPool memPool;
 };
};


 inline void* TestClassA::operator new(size_t size)
inline void* TestClassA::operator new(size_t size)  {
{
 return memPool.alloc(size);
    return memPool.alloc(size);
 }
}


 inline void TestClassA::operator delete(void* p, size_t size)
inline void TestClassA::operator delete(void* p, size_t size)  {
{
 memPool.free(p, size);
    memPool.free(p, size);
 }
}

 MemPool TestClassA::memPool(sizeof(TestClassA));
MemPool TestClassA::memPool(sizeof(TestClassA));


 class TestClassB
class TestClassB  {
{
 public :
public :
 int b;
    int b;
 };
};

 const int CTIMES = 100000;
const int CTIMES = 100000;

 TestClassA* pa[CTIMES];
TestClassA* pa[CTIMES];
 TestClassB* pb[CTIMES];
TestClassB* pb[CTIMES];


 int main()
int main()  {
{
 //测试新建100000个SmallObjet所需要的时间
    //测试新建100000个SmallObjet所需要的时间
 int i;
    int i;
 clock_t begB = clock();
    clock_t begB = clock();

 for (i=0; i<CTIMES; i++)
    for (i=0; i<CTIMES; i++)  {
{
 pb[i] = new TestClassB;
        pb[i] = new TestClassB;
 }
        }
 clock_t endB = clock();
    clock_t endB = clock();
 printf("Not Used MemPool Time For New = %d ms\n", endB - begB);
    printf("Not Used MemPool Time For New = %d ms\n", endB - begB);
 
    

 clock_t begA = clock();
    clock_t begA = clock();

 for (i=0; i<CTIMES; i++)
    for (i=0; i<CTIMES; i++)  {
{
 pa[i] = new TestClassA;
        pa[i] = new TestClassA;
 }
    }
 clock_t endA = clock();
    clock_t endA = clock();
 printf("Used MemPool Time For New = %d ms\n", endA - begA);
    printf("Used MemPool Time For New = %d ms\n", endA - begA);

 
    
 begB = clock();
    begB = clock();

 for (i=0; i<CTIMES; i++)
    for (i=0; i<CTIMES; i++)  {
{
 delete pb[i];
        delete pb[i];
 }
    }
 endB = clock();
    endB = clock();
 printf("Not Used MemPool Time For Delete = %d ms\n", endB - begB);
    printf("Not Used MemPool Time For Delete = %d ms\n", endB - begB);
 
    

 begA = clock();
    begA = clock();

 for (i=0; i<CTIMES; i++)
    for (i=0; i<CTIMES; i++)  {
{
 delete pa[i];
        delete pa[i];
 }
    }
 endA = clock();
    endA = clock();
 printf("Used MemPool Time For Delete = %d ms\n", endA - begA);
    printf("Used MemPool Time For Delete = %d ms\n", endA - begA);

 
    
 begB = clock();
    begB = clock();

 for (i=0; i<CTIMES; i++)
    for (i=0; i<CTIMES; i++)  {
{
 pb[i] = new TestClassB;
        pb[i] = new TestClassB;
 delete pb[i];
        delete pb[i];
 }
    }
 endB = clock();
    endB = clock();
 printf("Not Used MemPool Time For New/Delete = %d ms\n", endB - begB);
    printf("Not Used MemPool Time For New/Delete = %d ms\n", endB - begB);
 
    

 begA = clock();
    begA = clock();

 for (i=0; i<CTIMES; i++)
    for (i=0; i<CTIMES; i++)  {
{
 pa[i] = new TestClassA;
        pa[i] = new TestClassA;
 delete pa[i];
        delete pa[i];
 }
    }
 endA = clock();
    endA = clock();
 printf("Used MemPool Time For New/Delete = %d ms\n", endA - begA);
    printf("Used MemPool Time For New/Delete = %d ms\n", endA - begA);

 return 0;
    return 0;
 }
}
运行结果:
Not Used MemPool Time For New = 46 ms
Used MemPool Time For New = 16 ms
Not Used MemPool Time For Delete = 47 ms
Used MemPool Time For Delete = 266 ms
Not Used MemPool Time For New/Delete = 93 ms
Used MemPool Time For New/Delete = 16 ms
Press any key to continue
可以看到明显当内存池有大量小对象同时存在的时候,回收的时间很慢,其余时候效果还是不错的。
	posted on 2008-04-20 17:53 
豪 阅读(667) 
评论(0)  编辑 收藏 引用