• 自己做的一个固定大小对象内存池,效率大概为原始的new/delete的2倍


    提升不高,不过好处是可以多次申请小对象,一次释放。(只适应于无动态申请资源的class)

    vs2012测试情况如下:

    // CHchFixLenMemPool.h
    #pragma  once
    #ifndef __CHchFixLenMemPool_H__
    #define __CHchFixLenMemPool_H__
    #include <exception>
    #include <new>
    
    typedef struct __HchFixLenMemPoolLinkNode
    {
        __HchFixLenMemPoolLinkNode *m_next;
    }SHchFixLenMemPoolLinkNode;
    
    class CHchFixLenMemPool
    {
    public:
        CHchFixLenMemPool(size_t nFixLen, size_t nExpectObjectCnt = 0)
        { 
            if ( nFixLen < (sizeof(void *) > sizeof(size_t) ? sizeof(void *) : sizeof(size_t)) )
            {
                throw std::exception("nFixLen < max(sizeof(void *), sizeof(size_t))");
            }
    
            //必须对齐,不然有可能出现内存访问异常
            m_nFixLen = (nFixLen + sizeof(int) - 1) & ~(sizeof(int) - 1);
            m_nExpectObjectCnt = nExpectObjectCnt;
    
            if (m_nExpectObjectCnt < 1024)
            {
                m_nExpectObjectCnt = 1024;
            }
    
            m_allocSpaceLink = m_freeSpaceLink = NULL;
            allocFromSystem();
        }
    
        ~CHchFixLenMemPool()
        {
            //遍历链表节点
            while (m_allocSpaceLink)
            {
                SHchFixLenMemPoolLinkNode *pNext = m_allocSpaceLink->m_next;
                delete [](void *)m_allocSpaceLink;
                m_allocSpaceLink = pNext;
            }
        }
    
        void *alloc()
        {
            //如果存在已回收的空间,则直接分配出去
            if (m_freeSpaceLink != NULL)
            {
                void *p = m_freeSpaceLink;
                m_freeSpaceLink = m_freeSpaceLink->m_next;
                return p;
            }
    
            //不然需要从m_allocSpaceLink里面切一块出来
            char *pRetSpace = m_currAllocSpace; //pRetSpace指向待返回的空间
    
            //如果上次new出来的内存还没分配完,则直接分配即可
            if (m_nLeft != 0)
            {
                --m_nLeft;
                m_currAllocSpace += m_nFixLen;
                return pRetSpace;
            }
    
            //当前new出来的空间空间全部分配完 则需要重新向系统申请内存
            allocFromSystem();
    
            //这段跟前面分配逻辑是一样的
            //考虑到cpu流水线预测,刻意这样重复写代码 
            pRetSpace = m_currAllocSpace;
            --m_nLeft;
            m_currAllocSpace += m_nFixLen;
            return pRetSpace;
        }
    
        void free(void *pSpace)
        {
            if (pSpace == NULL)
            {
                return;
            }
    
            //如果回收空间链表为空,则直接修改m_allocSpaceLinke即可
            SHchFixLenMemPoolLinkNode *p = (SHchFixLenMemPoolLinkNode *)pSpace;
            if (m_allocSpaceLink == NULL)
            {
                m_allocSpaceLink = p;
                m_allocSpaceLink->m_next = NULL;
                return;
            }
    
            //否则将当前空间插到链表头
            p->m_next = m_freeSpaceLink;
            m_freeSpaceLink = p;
            return;
        }
    
    private:
        //从系统分配内存
        void allocFromSystem()
        {
            SHchFixLenMemPoolLinkNode *pNextLink = m_allocSpaceLink;
            //new失败会抛异常,不需要考虑
            m_allocSpaceLink = (SHchFixLenMemPoolLinkNode *)
                new char[sizeof(SHchFixLenMemPoolLinkNode) + m_nFixLen * m_nExpectObjectCnt];
    
            m_allocSpaceLink->m_next = pNextLink;
            m_nLeft = m_nExpectObjectCnt;
            m_currAllocSpace = ((char *)m_allocSpaceLink) + sizeof(SHchFixLenMemPoolLinkNode);
        }
    
        size_t m_nFixLen; //内存池定长
        size_t m_nLeft; //已申请未分配个数
        size_t m_nExpectObjectCnt; //每次申请多少个定长的空间
    
        //当前可分配的空间指针
        char *m_currAllocSpace;
    
        //回收空间链表 m_next指向下一个已回收空间
        SHchFixLenMemPoolLinkNode *m_freeSpaceLink;
    
        //已向系统申请的空间链表
        //链表中每个节点均指向new返回的指针
        //m_next指向下一个已向申请空间
        SHchFixLenMemPoolLinkNode *m_allocSpaceLink;
    };
    
    template<typename  T>
    T *newClassFromPool(CHchFixLenMemPool& objPool, const T& other)
    {
        T *pState = (T *)objPool.alloc();
        new(pState) T(other);
        return pState;
    }
    
    template<typename  T, typename  T1>
    T *newClassFromPool(CHchFixLenMemPool& objPool, const T1& param)
    {
        T *pState = (T *)objPool.alloc();
        new(pState) T(param);
        return pState;
    }
    
    template<typename  T>
    T *newClassFromPool(CHchFixLenMemPool& objPool)
    {
        T *pState = (T *)objPool.alloc();
        new(pState) T();
        return pState;
    }
    
    template<class T>
    void deleteClassFromPool(CHchFixLenMemPool& objPool, T * pState)
    {
        pState->~T();
        objPool.free(pState);
    }
    
    #ifdef __POP_NEW_FLAG__
    #pragma pop_macro("new")
    #endif
    
    #endif
    // testObjPool.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "CHchFixLenMemPool.h"
    #ifdef WIN32
    #include <Windows.h>
    #endif
    #include <stdio.h>
    
    class CSimpleBuffer
    {
    public:
        CSimpleBuffer(size_t size = 32)
        {
            m_memSize = size;
            m_pMem = new char[m_memSize];
        }
    
        CSimpleBuffer(const CSimpleBuffer& other)
        {
            m_memSize = other.m_memSize;
            m_pMem = new char[m_memSize];
            memcpy(m_pMem, other.m_pMem, m_memSize);
        }
    
        char *getMem()
        {
            return m_pMem;
        }
    
        size_t getMemSize()
        {
            return m_memSize;
        }
    
        ~CSimpleBuffer()
        {
            delete []m_pMem;
        }
    private:
        size_t m_memSize;
        char *m_pMem;
    };
    
    
    #ifdef WIN32
    
    class CMyTiming
    {
    public:
        CMyTiming()
        {
            m_startFlag = false;
        }
    
        bool startTiming() //开始计时
        {
            if (m_startFlag)
            {
                return false;
            }
            m_startFlag = true;
    
            QueryPerformanceFrequency(&m_litmp); /*获得时钟频率*/ 
            m_dff = m_litmp.QuadPart;
    
            QueryPerformanceCounter(&m_litmp); /*获得初始值*/ 
            m_qtBeg = m_litmp.QuadPart;
    
            return true;
        }
    
        double getTiming() //获得当前消耗时间
        {
            if (!m_startFlag)
            {
                return -1;
            }
    
    
            QueryPerformanceCounter(&m_litmp); /*获得终止值*/ 
            m_qtEnd = m_litmp.QuadPart;
            m_dfm = (m_qtEnd - m_qtBeg);
            m_dft = ((double) m_dfm) / m_dff; /*获得对应的时间值*/
            return m_dft;
        }
    
        void endTiming() //停止计时
        {
            m_startFlag = false;
        }
    private:
        bool m_startFlag;
        LARGE_INTEGER m_litmp;
        LONGLONG m_qtBeg, m_qtEnd, m_dff, m_dfm;
        double m_dft;
    };
    #endif
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const int nTimes = 209600;
        const int n = 8000;
        CSimpleBuffer *pArray[nTimes];
        CMyTiming runTimeInfo;
    
        printf("total new times %d
    ", nTimes * n);
        runTimeInfo.startTiming();
    
        for (int i = 0; i < n * nTimes; i++)
        {
            int nPos =  i / n;
            pArray[nPos] = new CSimpleBuffer(64);
            pArray[nPos]->getMem()[0] = '';
            if (i % n != (n - 1)) delete pArray[nPos];
        }
    
        for (int i = 0; i < nTimes; i++)
        {
            int nPos =  i / n;
            strcpy(pArray[nPos]->getMem(), "hell8ffff                                  fffff");
            pArray[nPos]->getMem()[i % 64] = '2';
            pArray[nPos]->getMem()[i % 32] =  i;
            if (i % n == (n - 1)) delete pArray[nPos];
        }
    
        printf("sec1 %.4f
    ", runTimeInfo.getTiming());
    
        runTimeInfo.endTiming();
        runTimeInfo.startTiming();
        CHchFixLenMemPool objPool(sizeof(CSimpleBuffer), 8096);
    
        for (int i = 0; i < n * nTimes; i++)
        {
            int nPos =  i / n;
            pArray[nPos] = newClassFromPool<CSimpleBuffer, size_t>(objPool, 64);
            pArray[nPos]->getMem()[0] = '';
            if (i % n != (n - 1)) deleteClassFromPool(objPool, pArray[nPos]);
        }
    
        for (int i = 0; i < nTimes; i++)
        {
            int nPos =  i / n;
            strcpy(pArray[nPos]->getMem(), "hell8ffff                                  fffff");
            pArray[nPos]->getMem()[i % 64] = '2';
            pArray[nPos]->getMem()[i % 32] =  i;
            if (i % n == (n - 1)) deleteClassFromPool(objPool, pArray[nPos]);
        }
    
        printf("sec2 %.4f
    ", runTimeInfo.getTiming());
        
        return 0;
    }
    View Code
  • 相关阅读:
    动态加载方法(定时任务)
    安装 asp.net core 出错
    .NET:权限管理
    关于随机数
    博客园首弹
    C# MVC从其他系统获取文件流,显示文件
    Python中操作MySQL步骤
    MySql之_增删改查
    数据库之_SQL注入
    为什么上传到youtube上的视频很模糊
  • 原文地址:https://www.cnblogs.com/kingstarer/p/6986636.html
Copyright © 2020-2023  润新知