再说内存池

来源:互联网 发布:windows live影音软件 编辑:程序博客网 时间:2024/05/24 06:23

根据<<提高C++性能的编程技术>>文章描述,对内存池各种情况进行了改写和对比

一下在vs2013下实践得到的数据

需要分配的内存

class CRational
{
public:
    CRational(int a = 0, int b = 1)
        : n_(a),
        d_(b)
    {
    }
private:
    int n_; // 分子
    int d_; // 分母
};

1、普通的内存分配

void CTest6_2::test1()
{
    CRational* pRation[1000];
    long l1 = time(NULL);

    for (int j = 0; j < 500; ++j)
    {
        for (int i = 0; i < 1000; ++i)
        {
            pRation[i] = new CRational(i);
        }
        for (int i = 0; i < 1000; ++i)
        {
            delete pRation[i];
        }
    }
    long l2 = time(NULL);

    cout << "test1: " << l2 - l1 << endl;
}

得到的时间是7S


2.单线程下的内存分配

CRationalEx* pRation[1000];
    long l1 = time(NULL);

    CRationalEx::newMemPool();
    for (int j = 0; j < 500; ++j)
    {
        for (int i = 0; i < 1000; ++i)
        {
            pRation[i] = new CRationalEx(i);
        }
        for (int i = 0; i < 1000; ++i)
        {
            delete pRation[i];
        }
    }
    CRationalEx::deleteMemPool();
    long l2 = time(NULL);

    cout << "test2: " << l2 - l1 << endl;

时间可以控制在1s内了

内存池的简单实现


class NextOnFreeList
{
public:
    NextOnFreeList()
        : p_next_(0)
    {

    }
    NextOnFreeList* p_next_; // 内存链路
};

// 单线程环境下的内存分配
class CRationalEx
{
public:
    inline void* operator new(size_t size);
    inline void operator delete(void* doomed, size_t size);

    static void newMemPool(){ expandTheFreeList(); }
    static void deleteMemPool();

    CRationalEx(int a = 0, int b = 1)
        : n_(a),
        d_(b)
    {
    }
private:
    int n_; // 分子
    int d_; // 分母

    static NextOnFreeList* p_free_list_;
    static void expandTheFreeList();
};

// 分配内存的算法


void CRationalEx::expandTheFreeList()
{
    size_t size = (sizeof(CRationalEx) > sizeof(NextOnFreeList*) ? sizeof(CRationalEx) : sizeof(NextOnFreeList));
    void* pchar = new char[size];   // 分配一个CRationalEx大小的空间
    NextOnFreeList* prunner = static_cast<NextOnFreeList*>(pchar);

    p_free_list_ = prunner;

    for (int i = 0; i < EXPANSION_SIZE; ++i)
    {
        pchar = new char[size];
        prunner->p_next_ = static_cast<NextOnFreeList*>(pchar);// next连接
        prunner = prunner->p_next_;
    }
    prunner->p_next_ = 0;
}


// 函数内联,保证了更快的速度,需要分配CRationalEx时,直接从内存池取用

inline void* CRationalEx::operator new(size_t size)
{
    if (!p_free_list_)
    {
        expandTheFreeList(); // 空间不够了,再分配32个CRationalEx
    }
    NextOnFreeList* phead = p_free_list_;
    p_free_list_ = phead->p_next_;
    return phead; // 返回首地址的空间出去,然后现有内存池指向下一个
}


inline void CRationalEx::operator delete(void* doomed, size_t size)
{
    NextOnFreeList* head = static_cast<NextOnFreeList*>(doomed); // 释放空间,即调用CRationalEx时,只是把内存池再还给NexOnFreeList
    head->p_next_ = p_free_list_;// 把地址拿过来,然后里面的next赋值成当前的head,这样把归还的地址放在最前面了,下次new取用也是从最前面取用
    p_free_list_ = head;
}

// 真正的释放内存池的内存

void CRationalEx::deleteMemPool()
{
    NextOnFreeList* pnext_ptr;
    for (pnext_ptr = p_free_list_; pnext_ptr != NULL; pnext_ptr = p_free_list_)
    {
        p_free_list_ = p_free_list_->p_next_;
        delete[] pnext_ptr;
    }
}


0 0
原创粉丝点击