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