zoukankan      html  css  js  c++  java
  • 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(); }
  • 相关阅读:
    数据的增、删、改(jQuery.Ajax)
    tomcat内置jdk(tomcat集成jdk)(windows环境)
    进行数据库进程的杀死
    矩阵与自然基向量
    实对称矩阵
    坐标变换
    设置PySpark的Python版本
    CentOS7中安装Python3.6
    一个矩阵有几个实特征向量
    centos7系统设置固定IP
  • 原文地址:https://www.cnblogs.com/diegodu/p/4555107.html
Copyright © 2011-2022 走看看