本篇就: 固定内存块使用 作一定分析,并提供链表实现作为实例说明.
然, 对于内存申请方面的优化, 本篇可能只能作为一种补充或者只能是一种特殊情况的特殊应用而已, 而并非完全的解决之道.
上接:
内存池性能研究: 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. 接口定义:
- #ifndef _IDVList_H_
- #define _IDVList_H_
- /*
- list all values node, not save the value, but the node.
- for using memory .. .
- // dave dai 0808
- */
- template <typename Value>
- struct tag_ListNail
- {
- tag_ListNail< Value>* pPrev;
- tag_ListNail< Value>* pNext;
- Value value;
- BOOL bFree;
- tag_ListNail()
- {
- Clear();
- };
- void Clear()
- {
- pPrev = NULL;
- pNext = NULL;
- RtlZeroMemory( &value, sizeof( Value ) );
- bFree = FALSE;
- };
- inline BOOL IsFree()
- {
- return bFree;
- }
- inline void SetValue(Value* pValue)
- {
- if( NULL == pValue )
- bFree = TRUE;
- else
- {
- RtlCopyMemory( &value, pValue, sizeof( Value ) );
- bFree = FALSE;
- }
- }
- inline void OnRemoved()
- {
- bFree = TRUE;
- }
- };
- template <typename Value>
- interface IListV;
- template <typename Value>
- interface IListNailMngr
- {
- virtual void Init( int nCountMax, CRITICAL_SECTION* pCS = NULL ) = 0;
- virtual void Start(int nCount) = 0;
- virtual BOOL IsEmpty() = 0;
- virtual DWORD GetCount() = 0;
- virtual void MoveTo(IListV<Value>* pListV, int nCount) = 0;
- virtual void MoveToTail( int index ) = 0;
- virtual void SetAt(int index, Value* pValue) = 0;
- virtual tag_ListNail< Value >* GetFreeNail(Value* pValue) = 0;
- };
- template <typename Value>
- interface IListV
- {
- IListNailMngr<Value>* m_pMngr;
- // not delete any node.
- virtual void RemoveAll() = 0;
- virtual void AddTail( Value* pValue ) = 0;
- virtual void AddHead( Value* pValue ) = 0;
- virtual void AddTailNail( tag_ListNail< Value >* pNail ) = 0;
- virtual void AddHeadNail( tag_ListNail< Value >* pNail ) = 0;
- virtual void SetAt(POSITION pos, Value* pValue) = 0;
- virtual POSITION GetHeadPosition() = 0;
- virtual POSITION GetTailPosition() = 0;
- virtual Value* GetNext( POSITION& pos ) = 0;
- virtual Value* GetPrev( POSITION& pos ) = 0;
- virtual Value* GetAt( POSITION pos ) = 0;
- virtual Value* GetHead() = 0;
- virtual Value* GetTail() = 0;
- virtual DWORD GetCount() = 0;
- virtual BOOL IsEmpty() = 0;
- virtual BOOL RemoveAt( POSITION pos ) = 0;
- virtual Value* RemoveHead() = 0;
- virtual Value* RemoveTail() = 0;
- // utility
- virtual void MoveTo( IListV* pList, int index = 0, int count = -1 ) = 0;
- };
B. 实现代码:
- class CLock
- {
- public:
- CLock(CRITICAL_SECTION& cs)
- {
- m_pcs = &cs;
- EnterCriticalSection( m_pcs );
- };
- CLock(CRITICAL_SECTION* pCS)
- {
- m_pcs = pCS;
- if( m_pcs )
- EnterCriticalSection( m_pcs );
- };
- ~CLock()
- {
- if( m_pcs )
- LeaveCriticalSection( m_pcs );
- };
- protected:
- CRITICAL_SECTION* m_pcs;
- };
- //
- // CListNailMngr 此类用来管理固定内存块, 并分配结点给其他链表直接使用.
- //
- template <typename Value>
- class CListNailMngr : public IListNailMngr<Value>
- {
- protected:
- tag_ListNail< Value >* m_pHead;
- tag_ListNail< Value >* m_pTail;
- LONG m_nCount;
- LONG m_nCountMax;
- BYTE* m_pContextsNodeBuffer;
- CRITICAL_SECTION* m_pTcs;
- public:
- CListNailMngr()
- {
- m_pHead = NULL;
- m_pTail = NULL;
- m_nCount = 0;
- m_nCountMax = 0;
- m_pContextsNodeBuffer = NULL;
- m_pTcs = NULL;
- };
- virtual ~CListNailMngr()
- {
- if( m_pContextsNodeBuffer )
- delete m_pContextsNodeBuffer;
- };
- inline BOOL IsEmpty()
- {
- return !m_pHead;
- };
- inline DWORD GetCount()
- {
- return m_nCount;
- };
- virtual void Init(int nCountMax, CRITICAL_SECTION* pCS = NULL)
- {
- m_pTcs = pCS;
- m_nCountMax = nCountMax;
- //
- DWORD dwSizeNode = sizeof( tag_ListNail< Value > );
- DWORD dwSizeNodeAll = nCountMax * dwSizeNode;
- m_pContextsNodeBuffer = new BYTE[ dwSizeNodeAll ];
- }
- virtual void Start(int nCount)
- {
- DWORD dwSizeNode = sizeof( tag_ListNail< Value > );
- DWORD dwSizeNodeAll = m_nCountMax * dwSizeNode;
- // clear
- RtlZeroMemory( m_pContextsNodeBuffer, dwSizeNodeAll );
- //
- BYTE* pCurNode = m_pContextsNodeBuffer;
- tag_ListNail< Value >* pOld = NULL;
- for( int i = 0; i < nCount; i ++ )
- {
- tag_ListNail< Value >* p = (tag_ListNail< Value >*) pCurNode;
- //
- pCurNode += dwSizeNode;
- //
- if( pOld )
- {
- pOld->pNext = p;
- p->pPrev = pOld;
- }
- pOld = p;
- //
- m_nCount ++;
- }
- m_pHead = (tag_ListNail< Value >*)FindIndex( 0 );
- m_pTail = (tag_ListNail< Value >*)FindIndex( m_nCount - 1 );
- ASSERT( pOld == m_pTail );
- };
- POSITION FindIndex( int index )
- {
- if( index >= m_nCountMax )
- return NULL;
- BYTE* pCurNode = m_pContextsNodeBuffer + index * sizeof( tag_ListNail< Value > );
- return (POSITION) pCurNode;
- };
- virtual void MoveTo(IListV<Value>* pListV, int nCount)
- {
- while( nCount -- )
- {
- tag_ListNail< Value >* pHead = _RemoveHeadNail();
- if( !pHead )
- break;
- pListV->AddTailNail( pHead );
- }
- };
- virtual Value* RemoveHead()
- {
- tag_ListNail<Value>* pNail = _RemoveHeadNail();
- if( pNail )
- {
- pNail->OnRemoved();
- return &pNail->value;
- }
- return NULL;
- }
- virtual tag_ListNail< Value >* GetFreeNail(Value* pValue)
- {
- CLock lock( m_pTcs );
- tag_ListNail< Value >* pCurNode = NULL;
- for( int i = 0; i < m_nCountMax; i ++ )
- {
- pCurNode = (tag_ListNail< Value >*) ( m_pContextsNodeBuffer + i * sizeof( tag_ListNail< Value > ) );
- if( pCurNode->IsFree() )
- {
- pCurNode->SetValue( pValue );
- return pCurNode;
- }
- }
- return NULL;
- };
- virtual void SetAt(int index, Value* pValue)
- {
- tag_ListNail< Value >* pNail = (tag_ListNail< Value >*)FindIndex( index );
- pNail->SetValue( pValue );
- };
- void MoveToTail( int index )
- {
- tag_ListNail< Value >* pNail = (tag_ListNail< Value >*)FindIndex( index );
- if( pNail && _RemoveNail( pNail ) )
- {
- _AddTailNail( pNail );
- }
- };
- protected:
- void _AddTailNail( tag_ListNail< Value >* pNail )
- {
- CLock lock( m_pTcs );
- pNail->pNext = NULL;
- pNail->pPrev = NULL;
- if( !m_pHead )
- {
- m_pHead = pNail;
- m_pTail = pNail;
- }
- else
- {
- pNail->pPrev = m_pTail;
- m_pTail->pNext = pNail;
- //
- m_pTail = pNail;
- }
- ::InterlockedIncrement( &m_nCount );
- };
- BOOL _RemoveNail( tag_ListNail<Value>* pNail )
- {
- CLock lock( m_pTcs );
- if( !m_pHead )
- {
- return NULL;
- }
- if( pNail == m_pHead )
- {
- return (BOOL)_RemoveHeadNail();
- }
- else if( pNail == m_pTail )
- {
- return (BOOL)_RemoveTailNail();
- }
- else
- {
- tag_ListNail<Value>* prev = pNail->pPrev;
- tag_ListNail<Value>* next = pNail->pNext;
- prev->pNext = next;
- next->pPrev = prev;
- ::InterlockedDecrement( &m_nCount );
- return TRUE;
- }
- return FALSE;
- };
- tag_ListNail<Value>* _RemoveHeadNail()
- {
- CLock lock( m_pTcs );
- if( !m_pHead )
- {
- return NULL;
- }
- tag_ListNail<Value>* pRet = m_pHead;
- m_pHead = m_pHead->pNext;
- if( m_pHead )
- m_pHead->pPrev = NULL;
- else
- m_pTail = NULL;
- ::InterlockedDecrement( &m_nCount );
- return pRet;
- };
- tag_ListNail<Value>* _RemoveTailNail()
- {
- CLock lock( m_pTcs );
- if( !m_pTail )
- {
- return NULL;
- }
- tag_ListNail<Value>* pRet = m_pTail;
- m_pTail = m_pTail->pPrev;
- if( m_pTail )
- m_pTail->pNext = NULL;
- else
- m_pHead = NULL;
- ::InterlockedDecrement( &m_nCount );
- return pRet;
- };
- };
- //
- // IListV 的实现就很简单了, 可以参考其他list 的实现. 或者加入VC十年技术群 30107096 询问.
- //
结尾:
希望本篇只是抛砖引玉, 抛砖引屎也行, 希望大家多多研究内存池性能优化之工作.
我的内存池性能优化也只是刚刚开始, 本篇只能作为一种补充或者只能是一种特殊情况的特殊应用而已, 而并非完全的解决之道.