efficient c++,单线程内存池

基于 http://www.cnblogs.com/diegodu/p/4555018.html operator new的知识基础上 介绍这个章节的内容

 

对于一般直接 new 与delete 性能较差,可以自己管理写内存的申请与释放。其实一般的operator new 和operator delete 直接调用 malloc 和 free的。

版本0:

class Rational
{
public:
    Rational(int a=0, int b =1 ): n(a),d(b){}
private:
    int n;
    int d;
};

版本1:专用的内存管理器

#include <stddef.h> // for size_t
#include <iostream>

using namespace std;

class NextOnFreeList {
    public:
        NextOnFreeList *next;
};

class Rational {
    public:
        Rational (int a = 0, int b = 1 ) : n(a), d(b) {}
        inline void *operator new(size_t size);
        inline void operator delete(void *doomed, size_t size);

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

    private:
        static NextOnFreeList *freeList; // A free list of Rational objects.
        static void expandTheFreeList();
        enum { EXPANSION_SIZE = 32};

        int n; // Numerator
        int d; // Denominator
};

inline
void * Rational::operator new(size_t size)
{
    if (0 == freeList) {// If the list is empty, fill it up.
        expandTheFreeList();
    }

    NextOnFreeList *head = freeList;
    freeList = head->next;

    return head;
}

inline
void Rational::operator delete(void *doomed, size_t size)
{
    NextOnFreeList *head = static_cast <NextOnFreeList *> (doomed);
    head->next = freeList;
    freeList = head;
}

void Rational::expandTheFreeList()
{
    // We must allocate an object large enough to contain the next
    // pointer.
    size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ?
        sizeof(Rational) : sizeof(NextOnFreeList *);

//    NextOnFreeList *runner = static_cast <NextOnFreeList *>(new char[size]);
    NextOnFreeList *runner = (NextOnFreeList *)(new char[size]);

    freeList = runner;
    for (int i = 0; i < EXPANSION_SIZE; i++) {
        //runner->next = static_cast <NextOnFreeList *> (new char[size]);
        runner->next = (NextOnFreeList *)(new char[size]);
        runner = runner->next;
    }

    runner->next = 0;

    cout << "expand" << endl;
}

void Rational::deleteMemPool()
{
    NextOnFreeList *nextPtr;
    for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
        freeList = freeList->next;
        delete [] nextPtr;
    }
}
//测试code

NextOnFreeList *Rational::freeList = 0;

int main()
{
    Rational *array[1000];

    Rational::newMemPool();

    // Start timing here

    for (int j = 0; j < 500; j++) {
        for (int i = 0; i < 1000; i++) {
            array[i] = new Rational(i);
        }
        for (int i = 0; i < 1000; i++) {
            delete array[i];
        }
    }

    // Stop timing here

    Rational::deleteMemPool();

    return 0;
}

这版本是通过重载 目标类 中的new 与delete 实现内存管理,只适用于目标类,但是速度是最快的。

实现方式是维护一个链表,类中静态声明链表头,链表维护一串空间,通过类型转换在  目标类 和 链表指针 之间转换。

如果内存不够(freelist=NULL)是一次申请较多内存进行维护。

链表的添加删除(对于函数释放空间与申请空间)是在链首操作。

书上47 行 52行通过 静态类型转换不成功,改为了 强制转换,在 g++ 中能够编译运行。

主要在主函数中调用静态函数 链表的申请与释放。

版本2:固定大小对象的内存池

考虑版本1,可以通过模板实现管理特定的对象。最主要的参数是类的大小。

实现是专门声明一个管理内存的内存池类,使用模板实现,提供alloc() free() 接口,给类申请与释放内存。

内存池类的实现是自身有一个MemoryPool<T>* next 指针用来指向维护的链表,内存的操作都在链首位置。

#include <stddef.h>
#include <iostream>

using namespace std;

template <class T>
class MemoryPool {
    public:
        MemoryPool (size_t size = EXPANSION_SIZE);
        ~MemoryPool ();

        // Allocate a T element from the free list.
        inline void* alloc (size_t size);

        // Return a T element to the free list.
        inline void free (void *someElement);
    private:
        // next element on the free list.
        MemoryPool<T> *next;

        // If the freeList is empty, expand it by this amount.
        enum { EXPANSION_SIZE = 32};

        // Add free elements to the free list
        void expandTheFreeList(int howMany = EXPANSION_SIZE);
};

template <class T>
MemoryPool <T> :: MemoryPool (size_t size)
{
    expandTheFreeList(size);
}

    template < class T > 
MemoryPool < T > :: ~MemoryPool ()
{
    MemoryPool<T> *nextPtr = next;
    for (nextPtr = next; nextPtr != NULL; nextPtr = next) {
        next = next->next;
        cout << nextPtr << endl;
        //delete [] nextPtr;
        //delete  nextPtr;
        delete [](char*)nextPtr;  //不太明白为什么这样是对的,上面的方法不行。。
                    //明白了,因为new的时候就是用char字节的方法申请的,delete的时候要对应。。
} } template < class T > inline void* MemoryPool < T > :: alloc (size_t) { if (!next) { expandTheFreeList(); } MemoryPool<T> *head = next; next = head->next; return head; } template < class T > inline void MemoryPool < T > :: free (void *doomed) { MemoryPool<T> *head = static_cast <MemoryPool<T> *> (doomed); head->next = next; next = head; } template < class T > void MemoryPool < T > :: expandTheFreeList(int howMany) { // We must allocate an object large enough to contain the // next pointer. size_t size = (sizeof(T) > sizeof(MemoryPool<T> *)) ? sizeof(T) : sizeof(MemoryPool<T> *); //MemoryPool<T> *runner = static_cast <MemoryPool<T> *>(new char [size]); MemoryPool<T> *runner = (MemoryPool<T> *)(new char [size]); next = runner; for (int i = 0; i < howMany ; i++) { //runner->next = static_cast <MemoryPool<T> *> new char [size]; runner->next = (MemoryPool<T> *)( new char [size]); runner = runner->next; } runner->next = NULL; } class Rational { public: Rational (int a = 0, int b = 1 ) : n(a), d(b) {} void *operator new(size_t size) { return memPool->alloc(size); } void operator delete(void *doomed,size_t size) { memPool->free(doomed); } static void newMemPool() { memPool = new MemoryPool <Rational>; } static void deleteMemPool() { delete memPool; } private: int n; // Numerator int d; // Denominator static MemoryPool <Rational> *memPool; }; MemoryPool <Rational> *Rational::memPool = 0; int main() { Rational *array[1000]; Rational::newMemPool(); // Start timing here for (int j = 0; j < 500; j++) { for (int i = 0; i < 1000; i++) { array[i] = new Rational(i); } for (int i = 0; i < 1000; i++) { delete array[i]; } } // Stop timing here Rational::deleteMemPool(); }

 

posted @ 2015-06-05 17:07  穆穆兔兔  阅读(394)  评论(0编辑  收藏  举报