C++实现多线程全局内存池(性能优化)

C++实现多线程全局内存池(性能优化)

http://blog.csdn.net/f_r_e_e_x/article/details/51615329

原创 2016年06月08日 20:48:56
[cpp] view plain copy
 
  1.  #include <Windows.h>  
  2. #include <iostream>  
  3. #include <map>  
  4. #include <string>  
  5. #include <assert.h>  
  6. #include <list>  
  7. #include <map>  
  8. #include <set>  
  9. #include <vector>  
  10. #include <time.h>  
  11.   
  12. typedef int s32;  
  13. typedef unsigned int u32;  
  14. typedef char c8;  
  15. typedef long long s64;  
  16. typedef unsigned long long u64;  
  17. typedef void* LPVOID;  
  18. typedef unsigned char* LPBYTE;  
  19.   
  20. class LockObject  
  21. {  
  22.     public:  
  23.         LockObject()  
  24.         {  
  25.             InitializeCriticalSection(&mLock);  
  26.         }  
  27.         ~LockObject()  
  28.         {  
  29.             DeleteCriticalSection(&mLock);  
  30.         }  
  31.   
  32.         void Lock()  
  33.         {  
  34.             EnterCriticalSection(&mLock);     
  35.         }  
  36.   
  37.         void UnLock()  
  38.         {  
  39.             LeaveCriticalSection(&mLock);  
  40.         }  
  41.   
  42.         bool TryLock()  
  43.         {  
  44.             return TryEnterCriticalSection(&mLock);  
  45.         }  
  46.     private:  
  47.         LockObject(const LockObject &other)  
  48.         {}  
  49.         LockObject& operator = (const LockObject &other)  
  50.         {}  
  51.     private:  
  52.         CRITICAL_SECTION mLock;  
  53. };  
  54. class ScopeLock  
  55. {  
  56.     public:  
  57.   
  58.         ScopeLock(CRITICAL_SECTION &lock)  
  59.             :mlock(lock)  
  60.         {  
  61.             EnterCriticalSection(&mlock);  
  62.         }  
  63.         ScopeLock(LockObject &lock)  
  64.             :mlock( reinterpret_cast<CRITICAL_SECTION&>(lock) )  
  65.         {  
  66.             EnterCriticalSection(&mlock);  
  67.         }  
  68.         ~ScopeLock()  
  69.         {  
  70.             LeaveCriticalSection(&mlock);  
  71.         }  
  72.   
  73.     private:  
  74.         ScopeLock( const ScopeLock &other)  
  75.             :mlock(other.mlock)  
  76.         {}  
  77.         ScopeLock& operator = (const ScopeLock &other)  
  78.         {}  
  79.     private:  
  80.         CRITICAL_SECTION &mlock;  
  81. };  
  82.   
  83. typedef struct MemoryChunk  
  84. {  
  85.     u64 mID;  
  86.     LPVOID mpData;  
  87.     u64 mDataSize;  
  88.     u64 mUsedSize;  
  89.     MemoryChunk *mpNext;  
  90. }* MemoryChunkPtr;  
  91.   
  92. class MemoryPool  
  93. {  
  94.     public:  
  95.         MemoryPool( u64 InitMemoryBlockBytes, u64 MinMemoryBlockBytes, u64 MemoryChunkBytes )  
  96.             :mMemoryChunkBytes( MemoryChunkBytes )  
  97.             ,mMinMemoryBlockBytes( MinMemoryBlockBytes )  
  98.         {  
  99.             mChunkIDPool =  
  100.             mTotalMemoryPoolBytes =  
  101.             mUsedMemoryBytes =  
  102.             mFreeMemoryBytes = 0;  
  103.   
  104.             mpBeginChunk =  
  105.             mpNearFreeChunk =  
  106.             mpEndChunk = nullptr;  
  107.             assert( InitMemoryBlockBytes >= MinMemoryBlockBytes );  
  108.             _AllocateMemory( __max( InitMemoryBlockBytes, MinMemoryBlockBytes ) );  
  109.         }  
  110.   
  111.         ~MemoryPool()  
  112.         {  
  113.             _Destory();  
  114.         }  
  115.   
  116.         template< typename T >  
  117.         T* GetMemory( u32 Count )  
  118.         {  
  119.             if( Count <= 0 )  
  120.             {  
  121.                 assert(false);  
  122.                 return nullptr;  
  123.             }  
  124.   
  125.             const auto p = static_cast< T* >( GetMemory( Count * sizeof( T ) ) );  
  126.             if( nullptr == p )  
  127.             {  
  128.                 assert( false );  
  129.                 return nullptr;  
  130.             }  
  131.   
  132.             for( auto i = 0; i < Count; ++i )  
  133.             {  
  134.                 new ( p + i )T();  
  135.             }  
  136.             return p;  
  137.         }  
  138.       
  139.         LPVOID GetMemory( u64 Bytes )  
  140.         {  
  141.             if( Bytes <= 0 )  
  142.             {  
  143.                 assert( false );  
  144.                 return nullptr;  
  145.             }  
  146.   
  147.             const auto AdjustMemoryBlockBytes = _AdjustMemoryBlockBytes( Bytes );  
  148.   
  149.             AllocChunk Chunk = { nullptr, nullptr, Bytes };  
  150.   
  151.             ScopeLock LockBody( mLock );  
  152.             if( false == _FindAllocateChunk( AdjustMemoryBlockBytes, Bytes, Chunk ) )  
  153.             {  
  154.                 if( false == _AllocateMemory( __max( mMinMemoryBlockBytes, AdjustMemoryBlockBytes ) ) )  
  155.                 {  
  156.                     assert(false);  
  157.                     return nullptr;  
  158.                 }  
  159.                 if( false == _FindAllocateChunk( AdjustMemoryBlockBytes, Bytes, Chunk ) )  
  160.                 {  
  161.                     assert(false);  
  162.                     return nullptr;  
  163.                 }  
  164.             }  
  165.   
  166.             mUsedMemoryBytes += AdjustMemoryBlockBytes;  
  167.             mFreeMemoryBytes = mTotalMemoryPoolBytes - mUsedMemoryBytes;  
  168.   
  169.             if( mpNearFreeChunk == Chunk.mpBeginChunk )  
  170.             {  
  171.                 mpNearFreeChunk = Chunk.mpEndChunk;  
  172.             }  
  173.   
  174.             mAllocBlocks.insert( std::make_pair( Chunk.mpBeginChunk->mpData, Chunk ) );  
  175.             return Chunk.mpBeginChunk->mpData;  
  176.         }  
  177.   
  178.         template<typename T>  
  179.         void ReleaseMemory( T* p )  
  180.         {  
  181.             if( nullptr == p )  
  182.             {  
  183.                 assert( false );  
  184.                 return;  
  185.             }  
  186.   
  187.             ScopeLock LockBody( mLock );  
  188.   
  189.             const auto Search = mAllocBlocks.find( p );  
  190.             if( Search == mAllocBlocks.end() )  
  191.             {  
  192.                 assert( false );  
  193.                 return;  
  194.             }  
  195.           
  196.             AllocChunk &Chunk = Search->second;  
  197.   
  198.             const auto Count = reinterpret_cast< T* >( reinterpret_cast< LPBYTE >( p ) + Chunk.mOriginalDataBytes ) - p;  
  199.             for(auto i = 0; i < Count; ++i)  
  200.             {  
  201.                 ( p + i )->~T();  
  202.             }  
  203.   
  204.             if( mpNearFreeChunk->mID > Chunk.mpBeginChunk->mID )  
  205.             {  
  206.                 mpNearFreeChunk = Chunk.mpBeginChunk;  
  207.             }  
  208.   
  209.             do  
  210.             {  
  211.                 Chunk.mpBeginChunk->mUsedSize = 0;  
  212.                 Chunk.mpBeginChunk = Chunk.mpBeginChunk->mpNext;  
  213.             }while( Chunk.mpBeginChunk != Chunk.mpEndChunk );  
  214.   
  215.             mAllocBlocks.erase( p );  
  216.         }  
  217.   
  218.         void ReleaseMemory( LPVOID p )  
  219.         {  
  220.             if( nullptr == p )  
  221.             {  
  222.                 assert( false );  
  223.                 return;  
  224.             }  
  225.             ScopeLock LockBody( mLock );  
  226.             const auto Search = mAllocBlocks.find( p );  
  227.             if( Search == mAllocBlocks.end() )  
  228.             {  
  229.                 assert( false );  
  230.                 return;  
  231.             }  
  232.           
  233.             AllocChunk &Chunk = Search->second;  
  234.   
  235.             if( mpNearFreeChunk->mID > Chunk.mpBeginChunk->mID )  
  236.             {  
  237.                 mpNearFreeChunk = Chunk.mpBeginChunk;  
  238.             }  
  239.   
  240.             do  
  241.             {  
  242.                 Chunk.mpBeginChunk->mUsedSize = 0;  
  243.                 Chunk.mpBeginChunk = Chunk.mpBeginChunk->mpNext;  
  244.             }while( Chunk.mpBeginChunk != Chunk.mpEndChunk );  
  245.   
  246.             mAllocBlocks.erase(p);  
  247.         }  
  248.     private:  
  249.         MemoryPool()  
  250.             :mMemoryChunkBytes( 0 )  
  251.             ,mMinMemoryBlockBytes( 0 )  
  252.         {}  
  253.         MemoryPool( const MemoryPool &other )  
  254.             :mMemoryChunkBytes( 0 )  
  255.             ,mMinMemoryBlockBytes( 0 )  
  256.         {}  
  257.         MemoryPool& operator = (const MemoryPool &other)  
  258.         {}  
  259.       
  260.         bool _AllocateMemory(u64 MemoryBlockSize)  
  261.         {  
  262.             const auto NewMemoryBlockSize = _AdjustMemoryBlockBytes( MemoryBlockSize );  
  263.   
  264.             auto pNewMemoryBlock = static_cast< LPBYTE >( malloc( NewMemoryBlockSize ) );  
  265.             if( nullptr == pNewMemoryBlock )  
  266.             {  
  267.                 assert(false);  
  268.                 return false;  
  269.             }  
  270.   
  271.             const auto NewChunkCount = NewMemoryBlockSize / mMemoryChunkBytes;  
  272.             auto pNewMemoryChunk = static_cast< MemoryChunkPtr >( malloc( NewChunkCount * sizeof( MemoryChunk ) ) );  
  273.             if( nullptr == pNewMemoryChunk )  
  274.             {  
  275.                 assert(false);  
  276.                 return false;  
  277.             }  
  278.   
  279.             mTotalMemoryPoolBytes += NewMemoryBlockSize;  
  280.   
  281.             if( false == _CreateNewChunkLink( pNewMemoryBlock, pNewMemoryChunk, NewChunkCount ) )  
  282.             {  
  283.                 assert(false);  
  284.                 return false;  
  285.             }  
  286.             return true;  
  287.         }  
  288.   
  289.         u64 _AdjustMemoryBlockBytes( u64 MemoryBlockSize )  
  290.         {  
  291.             const auto Mod = MemoryBlockSize % mMemoryChunkBytes;  
  292.             return Mod <= 0 ? MemoryBlockSize : MemoryBlockSize + mMemoryChunkBytes - Mod;  
  293.         }  
  294.   
  295.         bool _CreateNewChunkLink( LPBYTE pNewMemoryBlock, MemoryChunkPtr pNewMemoryChunk, u64 NewChunkCount )  
  296.         {  
  297.             if( nullptr == mpBeginChunk )  
  298.             {  
  299.                 mpBeginChunk =  
  300.                 mpNearFreeChunk =  
  301.                 mpEndChunk = pNewMemoryChunk;  
  302.   
  303.                 mpEndChunk->mID = ++mChunkIDPool;  
  304.                 mpEndChunk->mpData = pNewMemoryBlock;  
  305.                 mpEndChunk->mDataSize = mTotalMemoryPoolBytes;  
  306.                 mpEndChunk->mUsedSize = 0;  
  307.             }  
  308.   
  309.             u64 MemoryOffset = 0;  
  310.             for( auto i = 1; i < NewChunkCount; ++i )  
  311.             {  
  312.                 mpEndChunk->mpNext = pNewMemoryChunk + i;  
  313.                 mpEndChunk = mpEndChunk->mpNext;  
  314.                   
  315.                 MemoryOffset = i * mMemoryChunkBytes;  
  316.   
  317.                 mpEndChunk->mID = ++mChunkIDPool;  
  318.                 mpEndChunk->mpData = pNewMemoryBlock + MemoryOffset;  
  319.                 mpEndChunk->mDataSize = mTotalMemoryPoolBytes - MemoryOffset;  
  320.                 mpEndChunk->mUsedSize = 0;  
  321.             }  
  322.             mpEndChunk->mpNext = nullptr;  
  323.             HeadAddress Address = { pNewMemoryChunk, pNewMemoryBlock };  
  324.             mHeadAddresses.push_back( Address );  
  325.             return true;  
  326.         }  
  327.   
  328.         struct AllocChunk;  
  329.         bool _FindAllocateChunk( u64 MemoryBlockSize, u64 OriginalSize, AllocChunk &Chunk )  
  330.         {  
  331.             auto pTemp = mpNearFreeChunk;  
  332.             while( pTemp != nullptr && ( pTemp->mDataSize < MemoryBlockSize || pTemp->mUsedSize > 0 ) )  
  333.             {  
  334.                 pTemp = pTemp->mpNext;  
  335.             }  
  336.   
  337.             if( nullptr == pTemp )  
  338.             {  
  339.                 return false;  
  340.             }  
  341.             Chunk.mpBeginChunk = pTemp;  
  342.   
  343.             //  
  344.             u64 Counter = 0;  
  345.             for( Chunk.mpEndChunk = Chunk.mpBeginChunk; nullptr != Chunk.mpEndChunk && Counter < OriginalSize; Chunk.mpEndChunk = Chunk.mpEndChunk->mpNext )  
  346.             {  
  347.                 Counter += mMemoryChunkBytes;  
  348.                 if( Counter > OriginalSize )  
  349.                 {  
  350.                     Chunk.mpEndChunk->mUsedSize = Counter - OriginalSize;  
  351.                 }  
  352.                 else  
  353.                 {  
  354.                     Chunk.mpEndChunk->mUsedSize = mMemoryChunkBytes;  
  355.                 }  
  356.             }  
  357.             return true;  
  358.         }  
  359.   
  360.         void _Destory()  
  361.         {  
  362.             for( auto i = mHeadAddresses.begin(); i != mHeadAddresses.end(); ++i )  
  363.             {  
  364.                 free( i->m1);  
  365.                 free( i->m2 );  
  366.             }  
  367.             mHeadAddresses.clear();  
  368.             mAllocBlocks.clear();  
  369.         }  
  370.   
  371.     private:  
  372.   
  373.         MemoryChunkPtr mpBeginChunk;  
  374.         MemoryChunkPtr mpNearFreeChunk;  
  375.         MemoryChunkPtr mpEndChunk;  
  376.   
  377.         u64 mChunkIDPool;  
  378.         u64 mTotalMemoryPoolBytes;  
  379.         u64 mUsedMemoryBytes;  
  380.         u64 mFreeMemoryBytes;  
  381.         const u64 mMemoryChunkBytes;  
  382.         const u64 mMinMemoryBlockBytes;  
  383.         struct HeadAddress  
  384.         {  
  385.             LPVOID m1;  
  386.             LPVOID m2;  
  387.         };  
  388.         std::vector< HeadAddress > mHeadAddresses;  
  389.   
  390.         struct AllocChunk  
  391.         {  
  392.             MemoryChunkPtr mpBeginChunk;  
  393.             MemoryChunkPtr mpEndChunk;  
  394.             u64 mOriginalDataBytes;  
  395.         };  
  396.         std::map<LPVOID, AllocChunk> mAllocBlocks;  
  397.   
  398.         LockObject mLock;  
  399. };  

 

结构和上一个版本类似,所以就没写注释啦

 

posted @ 2018-03-19 19:36  sky20080101  阅读(134)  评论(0)    收藏  举报