C/C++的內存分配通過malloc或new)可能需要花費很多時。
更糟糕的是,隨著時間的流逝,內存memory)將形成碎片,所以一個應用程序的運行會越來越慢。當它運行了很長時間和/或執行了很多的內存分配釋放)操作的時候。特別是,你經常申請很小的一塊內存,堆heap)會變成碎片的。
解決方案:你自己的內存池一個可能的)解決方法是內存池Memory Pool)。
在啟動的時候,一個“內存池”Memory Pool)分配一塊很大的內存,並將會將這個大塊block)分成較小的塊smaller chunks)。每次你從內存池申請內存空間時,它會從先前已經分配的塊chunks)中得到,而不是從操作系統。最大的優勢在於:
1:非常少幾沒有) 堆碎片
2: 比通常的內存申請/釋放比如通過malloc, new等)的方式快另外,你可以得到以下好處:1:檢查任何一個指針是否在內存池裡2:寫一個“堆轉儲Heap-Dump)”到你的硬盤對事後的調試非常有用)
3: 某種“內存洩漏檢測memory-leak detection)”:當你沒有釋放所有以前分配的內存時,內存池Memory Pool)會拋出一個斷言assertion)。
SMemoryChunk.h
#ifndef __SMEMORYCHUNK_H__ #define __SMEMORYCHUNK_H__ typedef unsigned char TByte ; struct SMemoryChunk { TByte *Data; //數據 std::size_t DataSize; //該內存塊的總大小 std::size_t UsedSize; //實際使用的大小 bool IsAllocationChunk; SMemoryChunk *Next; //指向鏈表中下一個塊的指針。 }; #endif
IMemoryBlock.h
#ifndef __IMEMORYBLOCK_H__ #define __IMEMORYBLOCK_H__ class IMemoryBlock { public : virtual ~IMemoryBlock() {}; virtual void *GetMemory(const std::size_t &sMemorySize) = 0; virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize) = 0; }; #endif
CMemoryPool.h
#ifndef __CMEMORYPOOL_H__ #define __CMEMORYPOOL_H__ #include "IMemoryBlock.h" #include "SMemoryChunk.h" static const std::size_t DEFAULT_MEMORY_POOL_SIZE = 1000;//初始內存池的大小 static const std::size_t DEFAULT_MEMORY_CHUNK_SIZE = 128;//Chunk的大小 static const std::size_t DEFAULT_MEMORY_SIZE_TO_ALLOCATE = DEFAULT_MEMORY_CHUNK_SIZE * 2; class CMemoryPool : public IMemoryBlock { public: CMemoryPool(const std::size_t &sInitialMemoryPoolSize = DEFAULT_MEMORY_POOL_SIZE, const std::size_t &sMemoryChunkSize = DEFAULT_MEMORY_CHUNK_SIZE, const std::size_t &sMinimalMemorySizeToAllocate = DEFAULT_MEMORY_SIZE_TO_ALLOCATE, bool bSetMemoryData = false ); virtual ~CMemoryPool(); //從內存池中申請內存 virtual void* GetMemory(const std::size_t &sMemorySize); virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize); private: //申請內存OS bool AllocateMemory(const std::size_t &sMemorySize); void FreeAllAllocatedMemory(); //計算可以分多少塊 unsigned int CalculateNeededChunks(const std::size_t &sMemorySize); //計算內存池最合適的大小 std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize); //建立鏈表.每個結點Data指針指向內存池中的內存地址 bool LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock); //重新計算塊(Chunk)的大小1024--896--768--640--512------------ bool RecalcChunkMemorySize(SMemoryChunk* ptrChunk, unsigned int uiChunkCount); SMemoryChunk* SetChunkDefaults(SMemoryChunk *ptrChunk); //搜索鏈表找到一個能夠持有被申請大小的內存塊(Chunk).如果它返回NULL,那麼在內存池中沒有可用的內存 SMemoryChunk* FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize); std::size_t MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const; void SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize); SMemoryChunk* SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip); private: SMemoryChunk *m_ptrFirstChunk; SMemoryChunk *m_ptrLastChunk; SMemoryChunk *m_ptrCursorChunk; std::size_t m_sTotalMemoryPoolSize; //內存池的總大小 std::size_t m_sUsedMemoryPoolSize; //以使用內存的大小 std::size_t m_sFreeMemoryPoolSize; //可用內存的大小 std::size_t m_sMemoryChunkSize; //塊(Chunk)的大小 unsigned int m_uiMemoryChunkCount; //塊(Chunk)的數量 unsigned int m_uiObjectCount; bool m_bSetMemoryData ; std::size_t m_sMinimalMemorySizeToAllocate; }; #endif