A perfect small memory management system. Support memory pools and object pools. We know that in frequent allocation of small memory, or some small objects, it is easy to cause memory, and the speed is also very slow. When you do Object sort in render queque, a large amount of temporary objects (New) are generated, and the speed is very slow. Only 350fps. When the memory pool is used, the speed rises to 520fps. The speed gap can be seen. The following is MEMPOOL I used in the project. Basically, plagiarize the algorithm of LOKI. Other parts of the memory manager, you can see other articles in my blog, with connections. /*Mempool.h*/#ifndef __mem_pool_h __ # define __mem_pool_h __ # include
Class MemPool {// / / A piece of memory. The size of the memory block is Blocksize * blocks. Class Memchunck {Friend Class MempoOL;
BOOL INIT (SIZE_T BLOCKSIZE, UNSIGNED Short Blocks); Void Reset (Size_t Blocksize, Unsigned Short Blocks); Void Release ();
Void * alloc (size_t blocksize); void dealloc (void * p, size_t blocksize);
BOOL IS_PTR (Void * P, Size_t Blocksize, Unsigned Short Blocks);
Private: // Members // The address of the memory block UNSigned char * m_pdata; // The first available block, the size of one available block is specified by blocksize. // So a Memchunch size is BlockSize * blocks unsigned short m_firstavailableblock; unsigned short m_blocksavailable;};
// PUBLIC: / * Create a memPool * / memPool () {} memPool (size_t block_size, size_t block_reserved); bool init (size_t block_size, size_t block_reserved); void clear (); void clear_unused (); // --------- ------------------------------------------- // How much is it for this MEMPOOL? Space // ------------------------------------------------------------------------------------------------------------------------------------ --------- Void Reserve (SIZE_T BLOCK_RESERVED); / / -------------------------------- -------------------- // Release the unused space. / / -------------------------------------------------------------------------------------------- ---- Size_t unused_block ();
/ / -------------------------------------------------------------------------------------------- ---- // See how much space can be used // --------------------------------- ---------------- Size_t Capacity ();
/ / -------------------------------------------------------------------------------------------- ---- // Assign a memory and release a memory // --------------------------------- ----------------- void * alloc (); void dealloc (void * p);
/ / -------------------------------------------------------------------------------------------- ---- // Judging a pointer is not allocated by this pool. / / -------------------------------------------------------------------------------------------- ---- BOOL IS_PTR (Void * P);
/ ** Information in memory pond requires a record 1: The size of each block, the size of FixedallOctor can allocate. When m_blocksize can't be 1. 2: Each Memchunck, the number of blocks. 3: In the memory pool, idle The number of blocks * / private: size_t m_blocksize; // The size of each block, that is, the size of the FixedallOctor can allocate. When M_BlockSize cannot be 1. size_t m_blocksperchunk; // Each Memchunch, the number of blocks of Block; SIZE_T M_AVALIABLOCKS; / / In the memory pool, the number of idle blocks
Typedef std :: Vector
INT M_LASTCHUNK;
// void * m_pdealloc;
// ******************************************************** ******* //// ********************************************************** ****************** # ifdef _Debug template
Using Namespace std; / ****** Memory pool distributor. That is, a fixed size memory distributor. The allocation algorithm is a homemade part, plug-in inspiration, so now the algorithm is basically the Fixedalloctor in LOKI.
****** // * m_pdata ---> [xxxxx ...] first available block -> [3 | _____ ...] [xxxxx ...] [| _____ ...] [ Xxxxx ...] * /
namespace DGE {bool MemPool :: MemChunck :: init (size_t blockSize, unsigned short blocks) {assert (blockSize> 0); assert (blocks> 0); // Overflow check assert ((blockSize * blocks) / blockSize == blocks );
m_pdata = (unsigned char *) malloc (blocksize * blocks); if (m_pdata == null) Return False; RESET (Blocksize, Blocks); Return True;
void * MemPool :: MemChunck :: alloc (size_t blockSize) {if (! m_blocksAvailable) return 0; // check the memory is still not aligned assert ((m_firstAvailableBlock * blockSize) / blockSize == m_firstAvailableBlock);
// Put the first available return to support unsigned char * preSult = m_pdata (m_firstavailableblock * blocksize); m_firstavailableblock = * presult; - m_blocksavailable;
Return PRESULT;
Void Mempool :: Memchunchck :: DEALLOC (Void * p, size_t blocksize) {assert (p> = m_pdata);
Unsigned char * ToreLease = static_cast
// Add the released block to the head. Create a new header, the next block points to the original first available block * (unsigned short *) ToreLease) = m_firstavailableblock; // First available block pointing head m_firstavailableblock = static_cast
m_blocksavailable;}
void MemPool :: MemChunck :: reset (size_t blockSize, unsigned short blocks) {assert (blockSize> 0); assert (blocks> 0); // check the Yi assert ((blockSize * blocks) / blockSize == blocks);
m_firstavailableblock = 0; m_blocksavailable = blocks;
// Fill the chain of the memory block unsigned short i = 0; unsigned char * p = m_pdata; for (; i! = Blocks; p = blocksize) {unsigned short * pnext = (unsigned short *) p; * pnext = i;}
}
Void Mempool :: Memchunch :: Release () {free ((void *) m_pdata);
Bool Mempool :: Memchunck :: IS_PTR (Void * p, size_t blocksize, unsigned short blocks) {if (p
/ / =========================================================================================================================================================================================== =============================================== // The following is the category of MEMPOOL. // Implementation. / / =========================================================================================================================================================================================== =======================================
Mempool :: Mempool (size_t block_size, size_t block_reserved) {init (block_size, block_reserved);}
Bool mempol :: init (size_t block_size, size_t block_reserved) {m_blocksize = block_size; m_blocksperchunk = defualt_chunk_size / block_size;
M_avaliableblocks = 0; size_t nchuncks = (block_reserved 1) / m_blocksperchunk;
for (size_t i = 0; i Return True;} Void mempool :: clear () {size_t nchuncks = m_chuncks.size (); for (size_t i = 0; i Void Mempool :: Clear_unused () {Memchunks :: item (); size_t n = m_chuncks.size (); while ((n -)! = 0) {--i; if (i-> M_blocksavailable == m_blocksperchunk) {i-> release (); m_chuncks.rase (i);}} m_lastchunk = 0; } / / -------------------------------------------------------------------------------------------- ---- / / How many bytes of bytes are reserved for this MEMPOOL ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- Void Mempool :: RESERVE (size_t block_reserved) {if (m_avaliableblocks> = block_reserved) return; size_t nChuncks = (block_reserved - m_avaliableBlocks 1) / m_blocksPerChunk; for (size_t i = 0; i / / -------------------------------------------------------------------------------------------- ---- // Release the unused space. / / -------------------------------------------------------------------------------------------- ---- Size_t mempool :: unused_block () {return m_avaliableblocks;} // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- // Check how much space can be used // ------------------ -------------------------------- Size_t mempool :: Capacity () {Return M_Chuncks.Size () * m_blocksperchunk * m_blocksize;} // ---------------------------------------------------------------- ---- // Assign a memory and release a memory // --------------------------------- ----------------- void * Mempool :: alloc () {// first assign by the last allocated Memchunch. // If the last block is, it returns. Void * Ret = m_chuncks [m_lastchunk] .alloc (m_blocksize); if (re) {m_avaliableBLOCKS -; Return Ret;} SIZE_T NCHUNCKS = m_chuncks.size (); / / Find a Memchunck for (size_t i = 0; I // Newly established a block. Put it to M_AVALIABLOCKS = (m_blocksperchunk - 1); return m_chuncks [m_lastchunk] .alloc (m_blocksize); } void MemPool :: dealloc (void * p) {{if (m_Chuncks [m_lastChunk] .is_ptr (p, m_blockSize, (unsigned short) m_blocksPerChunk) == true) {m_Chuncks [m_lastChunk] .dealloc (p, m_blockSize); m_avaliableBlocks ; Return;} size_t nchuncks = m_chuncks.size (); for (size_t i = 0; i / / -------------------------------------------------------------------------------------------- ---- // Judging a pointer is not allocated by this pool. / / -------------------------------------------------------------------------------------------- ---- BOOL MEMPOOL :: IS_PTR (Void * P) {size_t nchuncks = m_chuncks.size (); for (size_t i = 0; i #include "mempool.h" Using Namespace DGE; template #define IMP_Object_pool (Type, ObjectReServe) / COBJECTPOOL #ENDIF