內存池性能優化 固定內存塊使用 之 鏈表實現

本篇就: 固定內存塊使用 作一定分析,並提供鏈表實現作爲實例說明.
然, 對於內存申請方面的優化, 本篇可能只能作爲一種補充或者只能是一種特殊情況的特殊應用而已, 而並非完全的解決之道.


上接:
內存池性能研究: http://blog.csdn.net/davemin/archive/2008/09/10/2910770.aspx

 

問題:
實現A:
BYTE* pBuffer1 = new BYTE[ 10 ];
BYTE* pBuffer2 = new BYTE[ 10 ];

實現B:
BYTE* pBuffer = new BYTE[ 20 ];
BYTE* pBuffer1 = pBuffer;
BYTE* pBuffer2 = pBuffer + 10;


本文出自: 阿呆 http://blog.csdn.net/davemin
宣傳: VC 十年技術羣 30107096 歡迎高手加入,本羣只研究VC


分析:

很顯然, 實現B只需要申請一次內存, 而實現A需要申請2次內存. 因此就性能和對於系統穩定來說,實現B 要優秀的多.


結論:


介於內存池性能以及穩定性考慮的其他方案之一: 使用固定內存塊, 爲基本固定應用提供內存需求. 此, 不失爲良策,
亦是性能最優化, 最穩定之方案.

 


應用:


如果你需要管理N個同類對象(N 爲區間固定值), 如: 管理100-200個人員信息.  管理0-2000個產品信息.

我們通常用的方法就是鏈表: list

 


1. list 結構分析與影響性能之分析.

list 內部結構結點基本結構是: tag_node{ ptr, prev, next }; 這樣的形式. 是一個雙向的指針.

目前常用的list 的實現, 大多是這樣的原理:
A. 先申請X 個節點的內存, 如果節點數在X以內, 就不需要繼續申請內存.
B. 如果節點數增加到大於X的數量了, 重新申請內存塊, 提供給新的節點以及以後的節點使用. 
C. 如果節點數爲0, 清理掉所有申請的內存.

這裏有幾個影響性能的因素:
a. X 爲多少, 和可能的總節點數量是多少之間存在問題. 如果x 非常小, 總節點數量巨大, 意味着,需要申請幾乎極大次數次內存.
   但x 這個值多數鏈表不提供外部的直接管理和設置.
   也就是說你知道這樣做不好,想要節省申請內存的次數也不行.

b. 如果這個鏈表經常性的清0, 然後又頻繁增加, 頻繁清0, 也導至內存的申請和清除工作巨增.
   但又不容易去直接改變這一點.

c. 以上兩點, 即便使用了內存池也同樣存在. 因爲我上篇已經說明了: 內存池的工作也是需要開銷的,需要時間的.

 

2. 固定內存之基本實現方案,  固定內存鏈表實現基本方案

a. 如實例B一樣, 先申請一塊大內存, 然後慢慢用.
b. 固定內存鏈表, 也是一樣實現. 所有節點使用同一塊內存.
c. 在節點數清0時, 不清除內存. 除非調用析構.
d. 實現一個管理固定內存塊的鏈表ManagerList.
e. ManagerList分配節點給其他鏈表使用, 可以分配給一個或者是多個鏈表使用.
f. 1->n 這樣的一種方式對於實現應用情況來說, 更加靈活方便.

 


本文出自: 阿呆 http://blog.csdn.net/davemin
宣傳: VC 十年技術羣 30107096 歡迎高手加入,本羣只研究VC

 


c. 我實現的固定內存鏈表示例代碼

A. 接口定義:

  1. #ifndef _IDVList_H_
  2. #define _IDVList_H_
  3. /*
  4.  list all values node, not save the value, but the node.
  5.  for using memory .. .
  6. // dave dai 0808
  7. */
  8. template <typename Value>
  9. struct tag_ListNail
  10. {
  11.  tag_ListNail< Value>* pPrev;
  12.  tag_ListNail< Value>* pNext; 
  13.  Value value;
  14.  BOOL bFree;
  15.  tag_ListNail()
  16.  {
  17.   Clear();
  18.  };
  19.  void Clear()
  20.  {
  21.   pPrev = NULL;
  22.   pNext = NULL;  
  23.   RtlZeroMemory( &value, sizeof( Value ) );
  24.   bFree = FALSE;
  25.  };
  26.  inline BOOL IsFree()
  27.  {
  28.   return bFree;
  29.  }
  30.  inline void SetValue(Value* pValue)
  31.  {
  32.   if( NULL == pValue )
  33.    bFree = TRUE;
  34.   else
  35.   {
  36.    RtlCopyMemory( &value, pValue, sizeof( Value ) );
  37.    bFree = FALSE;
  38.   }
  39.  }
  40.  inline void OnRemoved()
  41.  {
  42.   bFree = TRUE;
  43.  }
  44. };
  45. template <typename Value>
  46. interface IListV;
  47. template <typename Value>
  48. interface IListNailMngr
  49. {
  50.  virtual void Init( int nCountMax, CRITICAL_SECTION* pCS = NULL ) = 0;
  51.  virtual void Start(int nCount) = 0;
  52.  virtual BOOL IsEmpty() = 0;
  53.  virtual DWORD GetCount() = 0;
  54.  virtual void MoveTo(IListV<Value>* pListV, int nCount) = 0;
  55.  virtual void MoveToTail( int index ) = 0;
  56.  virtual void SetAt(int index, Value* pValue) = 0;
  57.  virtual tag_ListNail< Value >* GetFreeNail(Value* pValue) = 0;
  58. };
  59. template <typename Value>
  60. interface IListV
  61. {
  62.  IListNailMngr<Value>* m_pMngr;
  63.  // not delete any node.
  64.  virtual void RemoveAll() = 0;
  65.  virtual void AddTail( Value* pValue ) = 0;
  66.  virtual void AddHead( Value* pValue ) = 0;
  67.  virtual void AddTailNail( tag_ListNail< Value >* pNail ) = 0;
  68.  virtual void AddHeadNail( tag_ListNail< Value >* pNail ) = 0;
  69.  virtual void SetAt(POSITION pos, Value* pValue) = 0;
  70.  virtual POSITION GetHeadPosition() = 0;
  71.  virtual POSITION GetTailPosition() = 0;
  72.  virtual Value* GetNext( POSITION& pos ) = 0;
  73.  virtual Value* GetPrev( POSITION& pos ) = 0;
  74.  virtual Value* GetAt( POSITION pos ) = 0;
  75.  virtual Value* GetHead() = 0;
  76.  virtual Value* GetTail() = 0;
  77.  virtual DWORD GetCount() = 0;
  78.  virtual BOOL IsEmpty() = 0;
  79.  virtual BOOL RemoveAt( POSITION pos ) = 0;
  80.  virtual Value* RemoveHead() = 0;
  81.  virtual Value* RemoveTail() = 0;
  82.  // utility
  83.  virtual void MoveTo( IListV* pList, int index = 0, int count = -1 ) = 0;
  84. };

 

 

 

B. 實現代碼:

 

  1. class CLock
  2. {
  3. public:
  4.  CLock(CRITICAL_SECTION& cs)
  5.  {
  6.   m_pcs = &cs;
  7.   EnterCriticalSection( m_pcs );
  8.  };
  9.  CLock(CRITICAL_SECTION* pCS)
  10.  {
  11.   m_pcs = pCS;
  12.   if( m_pcs )
  13.    EnterCriticalSection( m_pcs );
  14.  };
  15.  ~CLock()
  16.  {
  17.   if( m_pcs )
  18.    LeaveCriticalSection( m_pcs );
  19.  };
  20. protected:
  21.  CRITICAL_SECTION* m_pcs;
  22. };
  23. //
  24. // CListNailMngr 此類用來管理固定內存塊, 並分配結點給其他鏈表直接使用.
  25. //
  26. template <typename Value>
  27. class CListNailMngr : public IListNailMngr<Value>
  28. {
  29. protected:
  30.  tag_ListNail< Value >* m_pHead;
  31.  tag_ListNail< Value >* m_pTail;
  32.  LONG m_nCount;
  33.  LONG m_nCountMax;
  34.  BYTE* m_pContextsNodeBuffer;
  35.  CRITICAL_SECTION* m_pTcs;
  36. public
  37.  CListNailMngr()
  38.  {
  39.   m_pHead = NULL;
  40.   m_pTail = NULL;
  41.   m_nCount = 0;
  42.   m_nCountMax = 0;
  43.   m_pContextsNodeBuffer = NULL;
  44.   m_pTcs = NULL;
  45.  };
  46.  virtual ~CListNailMngr()
  47.  {
  48.   if( m_pContextsNodeBuffer )
  49.    delete  m_pContextsNodeBuffer;
  50.  };
  51.  inline BOOL IsEmpty()
  52.  {
  53.   return !m_pHead;
  54.  };
  55.  inline DWORD GetCount()
  56.  {
  57.   return m_nCount;
  58.  };
  59.  virtual void Init(int nCountMax, CRITICAL_SECTION* pCS = NULL)
  60.  {
  61.   m_pTcs = pCS;
  62.   m_nCountMax = nCountMax;
  63.   //
  64.   DWORD dwSizeNode = sizeof( tag_ListNail< Value > );
  65.   DWORD dwSizeNodeAll = nCountMax * dwSizeNode;
  66.   m_pContextsNodeBuffer = new BYTE[ dwSizeNodeAll ];
  67.  }
  68.  virtual void Start(int nCount)
  69.  {
  70.   DWORD dwSizeNode = sizeof( tag_ListNail< Value > );
  71.   DWORD dwSizeNodeAll = m_nCountMax * dwSizeNode;
  72.   // clear
  73.   RtlZeroMemory( m_pContextsNodeBuffer, dwSizeNodeAll );
  74.   //
  75.   BYTE* pCurNode = m_pContextsNodeBuffer;
  76.   tag_ListNail< Value >* pOld = NULL;
  77.   forint i = 0; i < nCount; i ++ )
  78.   {
  79.    tag_ListNail< Value >* p = (tag_ListNail< Value >*)  pCurNode;
  80.    //
  81.    pCurNode += dwSizeNode;
  82.    // 
  83.    if( pOld )
  84.    {
  85.     pOld->pNext = p;
  86.     p->pPrev = pOld;
  87.    }
  88.    pOld = p;
  89.    //
  90.    m_nCount ++;
  91.   }
  92.   m_pHead = (tag_ListNail< Value >*)FindIndex( 0 );
  93.   m_pTail = (tag_ListNail< Value >*)FindIndex( m_nCount - 1 );
  94.   ASSERT( pOld == m_pTail );
  95.  };
  96.  POSITION FindIndex( int index )
  97.  {
  98.   if( index >= m_nCountMax )
  99.    return NULL;
  100.   BYTE* pCurNode = m_pContextsNodeBuffer + index * sizeof( tag_ListNail< Value > );
  101.   return (POSITION) pCurNode;
  102.  };
  103.  virtual void MoveTo(IListV<Value>* pListV, int nCount)
  104.  {
  105.   while( nCount -- )
  106.   {
  107.    tag_ListNail< Value >* pHead = _RemoveHeadNail();
  108.    if( !pHead )
  109.     break;
  110.    pListV->AddTailNail( pHead );
  111.   }
  112.  };
  113.  virtual Value* RemoveHead()
  114.  {
  115.   tag_ListNail<Value>* pNail = _RemoveHeadNail();
  116.   if( pNail )
  117.   {
  118.    pNail->OnRemoved();
  119.    return &pNail->value;
  120.   }
  121.   return NULL;
  122.  } 
  123.  virtual tag_ListNail< Value >* GetFreeNail(Value* pValue)
  124.  {
  125.   CLock lock( m_pTcs );
  126.   tag_ListNail< Value >* pCurNode = NULL;
  127.   forint i = 0; i < m_nCountMax; i ++ )
  128.   {
  129.    pCurNode = (tag_ListNail< Value >*) ( m_pContextsNodeBuffer + i * sizeof( tag_ListNail< Value > ) );
  130.    if( pCurNode->IsFree() )
  131.    {
  132.     pCurNode->SetValue( pValue );
  133.     return pCurNode;
  134.    }
  135.   }
  136.   return NULL;
  137.  };
  138.  virtual void SetAt(int index, Value* pValue)
  139.  {
  140.   tag_ListNail< Value >* pNail = (tag_ListNail< Value >*)FindIndex( index );
  141.   pNail->SetValue( pValue );
  142.  };
  143.  void MoveToTail( int index )
  144.  {
  145.   tag_ListNail< Value >* pNail = (tag_ListNail< Value >*)FindIndex( index );
  146.   if( pNail && _RemoveNail( pNail ) )
  147.   {
  148.    _AddTailNail( pNail );
  149.   }
  150.  };
  151. protected:
  152.  void _AddTailNail( tag_ListNail< Value >* pNail )
  153.  {
  154.   CLock lock( m_pTcs );
  155.   pNail->pNext = NULL;
  156.   pNail->pPrev = NULL;
  157.   if( !m_pHead )
  158.   {
  159.    m_pHead = pNail;
  160.    m_pTail = pNail;
  161.   }
  162.   else
  163.   {
  164.    pNail->pPrev = m_pTail;
  165.    m_pTail->pNext = pNail;
  166.    //
  167.    m_pTail = pNail;
  168.   }
  169.   ::InterlockedIncrement( &m_nCount );
  170.  };
  171.  BOOL _RemoveNail( tag_ListNail<Value>* pNail )
  172.  {
  173.   CLock lock( m_pTcs );
  174.   if( !m_pHead )
  175.   {
  176.    return NULL;
  177.   }
  178.   if( pNail == m_pHead )
  179.   {
  180.    return (BOOL)_RemoveHeadNail();
  181.   }
  182.   else if( pNail == m_pTail )
  183.   {
  184.    return (BOOL)_RemoveTailNail(); 
  185.   }
  186.   else
  187.   {
  188.    tag_ListNail<Value>* prev = pNail->pPrev;
  189.    tag_ListNail<Value>* next = pNail->pNext;
  190.    prev->pNext = next;
  191.    next->pPrev = prev;
  192.    ::InterlockedDecrement( &m_nCount );
  193.    return TRUE;
  194.   }
  195.   return FALSE;
  196.  };
  197.  tag_ListNail<Value>* _RemoveHeadNail()
  198.  {
  199.   CLock lock( m_pTcs );
  200.   if( !m_pHead )
  201.   {
  202.    return NULL;
  203.   }
  204.   tag_ListNail<Value>* pRet = m_pHead;
  205.   m_pHead = m_pHead->pNext;
  206.   if( m_pHead )
  207.    m_pHead->pPrev = NULL;
  208.   else
  209.    m_pTail = NULL;
  210.   ::InterlockedDecrement( &m_nCount );
  211.   return pRet;
  212.  };
  213.  tag_ListNail<Value>* _RemoveTailNail()
  214.  {
  215.   CLock lock( m_pTcs );
  216.   if( !m_pTail )
  217.   {
  218.    return NULL;
  219.   }
  220.   tag_ListNail<Value>* pRet = m_pTail;
  221.   m_pTail = m_pTail->pPrev;
  222.   if( m_pTail )
  223.    m_pTail->pNext = NULL;
  224.   else
  225.    m_pHead = NULL;
  226.   ::InterlockedDecrement( &m_nCount );
  227.   
  228.   return pRet;
  229.  };
  230. };
  231. //
  232. // IListV 的實現就很簡單了, 可以參考其他list 的實現. 或者加入VC十年技術羣 30107096 詢問.
  233. //

 

結尾:


希望本篇只是拋磚引玉, 拋磚引屎也行, 希望大家多多研究內存池性能優化之工作.

我的內存池性能優化也只是剛剛開始, 本篇只能作爲一種補充或者只能是一種特殊情況的特殊應用而已, 而並非完全的解決之道.

 

 

發佈了60 篇原創文章 · 獲贊 2 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章