自己做的一个固定大小对象内存池,效率大概为原始的new/delete的2倍
生活随笔
收集整理的這篇文章主要介紹了
自己做的一个固定大小对象内存池,效率大概为原始的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 WIN32class 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; }; #endifint _tmain(int argc, _TCHAR* argv[]) {const int nTimes = 209600;const int n = 8000;CSimpleBuffer *pArray[nTimes];CMyTiming runTimeInfo;printf("total new times %d\n", 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] = '\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\n", 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] = '\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\n", runTimeInfo.getTiming());return 0; } View Code?
轉載于:https://www.cnblogs.com/kingstarer/p/6986636.html
總結
以上是生活随笔為你收集整理的自己做的一个固定大小对象内存池,效率大概为原始的new/delete的2倍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#将内容导出到Word到指定模板
- 下一篇: 数据库-索引