日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

內存池技術

 JohnnyChan 2009-07-17

解決方案:你自己的內存池一個(可能的)解決方法是內存池(Memory Pool)。

    在啟動的時候,一個內存池Memory Pool)分配一塊很大的內存,并將會將這個大塊(block)分成較小的塊(smaller chunks)。每次你從內存池申請內存空間時,它會從先前已經(jīng)分配的塊(chunks)中得到,而不是從操作系統(tǒng)。最大的優(yōu)勢在于:

    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;                
//數(shù)據(jù) 
  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"


staticconst 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)的數(shù)量
    unsigned int m_uiObjectCount;

    
bool m_bSetMemoryData ; 
    std::size_t m_sMinimalMemorySizeToAllocate;


};

#endif

 



CMemoryPool.cpp

#include "stdafx.h"
#include "CMemorypool.h"

#include <math.h>
#include <assert.h>

static const int NEW_ALLOCATED_MEMORY_CONTENT = 0xFF ;


CMemoryPool::CMemoryPool(
const std::size_t &sInitialMemoryPoolSize,
                         
const std::size_t &sMemoryChunkSize,
                         
const std::size_t &sMinimalMemorySizeToAllocate,
                         
bool bSetMemoryData)
{
    m_ptrFirstChunk  = NULL;
    m_ptrLastChunk   = NULL;
    m_ptrCursorChunk = NULL;

    m_sTotalMemoryPoolSize = 0;
    m_sUsedMemoryPoolSize  = 0;
    m_sFreeMemoryPoolSize  = 0;

    m_sMemoryChunkSize   = sMemoryChunkSize;
    m_uiMemoryChunkCount = 0;
    m_uiObjectCount      = 0;

    m_bSetMemoryData               = !bSetMemoryData;
    m_sMinimalMemorySizeToAllocate = sMinimalMemorySizeToAllocate;

    AllocateMemory(sInitialMemoryPoolSize);
}

CMemoryPool::~CMemoryPool()
{

}

void* CMemoryPool::GetMemory(const std::size_t &sMemorySize)
{
    std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize);  
    SMemoryChunk* ptrChunk = NULL;
    
while(!ptrChunk)
    {

        ptrChunk = FindChunkSuitableToHoldMemory(sBestMemBlockSize);

        
//ptrChunk等于NULL表示內存池內存不夠用
        if(!ptrChunk)
        {
            sBestMemBlockSize = MaxValue(sBestMemBlockSize, CalculateBestMemoryBlockSize(m_sMinimalMemorySizeToAllocate));
            
//OS申請更多的內存
            AllocateMemory(sBestMemBlockSize);
        }
    }
    
//下面是找到可用的塊(Chunk)代碼
    m_sUsedMemoryPoolSize += sBestMemBlockSize;
    m_sFreeMemoryPoolSize -= sBestMemBlockSize;
    m_uiObjectCount++;
    
//標記該塊(Chunk)已用
    SetMemoryChunkValues(ptrChunk, sBestMemBlockSize);

    
return ((void *) ptrChunk->Data);
}

void CMemoryPool::FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize)
{





}

bool CMemoryPool::AllocateMemory(const std::size_t &sMemorySize)
{
    
//計算可以分多少塊(1000 / 128 = 8)
    unsigned int uiNeededChunks = CalculateNeededChunks(sMemorySize);

    
//當內存池的初始大小為1000字節(jié),塊(Chunk)大小128字節(jié),分8塊還差24字節(jié).怎么辦?
    //
解決方案:多申請24字節(jié)
    std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize);

    
//OS申請內存
    TByte *ptrNewMemBlock = (TByte*) malloc(sBestMemBlockSize);

    
//分配一個結構體SmemoryChunk的數(shù)組來管理內存塊
    SMemoryChunk *ptrNewChunks = (SMemoryChunk*) malloc((uiNeededChunks * sizeof(SMemoryChunk))); 


    m_sTotalMemoryPoolSize += sBestMemBlockSize;
    m_sFreeMemoryPoolSize += sBestMemBlockSize;
    m_uiMemoryChunkCount += uiNeededChunks;


    
if(m_bSetMemoryData)
    {
        memset(((
void *) ptrNewMemBlock), NEW_ALLOCATED_MEMORY_CONTENT, sBestMemBlockSize);
    }

    
return LinkChunksToData(ptrNewChunks, uiNeededChunks, ptrNewMemBlock);

}

unsigned 
int CMemoryPool::CalculateNeededChunks(const std::size_t &sMemorySize)
{
    
float f = (float) (((float)sMemorySize) / ((float)m_sMemoryChunkSize));
    
return ((unsigned int) ceil(f));
}

std::size_t CMemoryPool::CalculateBestMemoryBlockSize(
const std::size_t &sRequestedMemoryBlockSize)
{
    unsigned 
int uiNeededChunks = CalculateNeededChunks(sRequestedMemoryBlockSize);
    
return std::size_t((uiNeededChunks * m_sMemoryChunkSize));
}

bool CMemoryPool::LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock)
{

    SMemoryChunk *ptrNewChunk = NULL;
    unsigned 
int uiMemOffSet = 0; 
    
bool bAllocationChunkAssigned = false ;
    
for(unsigned int i = 0; i < uiChunkCount; i++)
    {    
        
//建立鏈表
        if(!m_ptrFirstChunk)
        {
            m_ptrFirstChunk = SetChunkDefaults(&(ptrNewChunks[0]));
            m_ptrLastChunk = m_ptrFirstChunk;
            m_ptrCursorChunk = m_ptrFirstChunk;
        }
        
else
        {
            ptrNewChunk = SetChunkDefaults(&(ptrNewChunks[i]));
            m_ptrLastChunk->Next = ptrNewChunk;
            m_ptrLastChunk = ptrNewChunk;
        }
        
//根據(jù)塊(Chunk)的大小計算下一塊的內存偏移地址
        uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize));

        
//結點指向內存偏移地址
        m_ptrLastChunk->Data = &(ptrNewMemBlock[uiMemOffSet]);


        
if(!bAllocationChunkAssigned)
        {
            m_ptrLastChunk->IsAllocationChunk = 
true;
            bAllocationChunkAssigned = 
true;
        }
    }


    
return RecalcChunkMemorySize(m_ptrFirstChunk, m_uiMemoryChunkCount);

}


bool CMemoryPool::RecalcChunkMemorySize(SMemoryChunk *ptrChunk, unsigned int uiChunkCount)
{
    unsigned 
int uiMemOffSet = 0 ;
    
for(unsigned int i = 0; i < uiChunkCount; i++)
    {
        
if(ptrChunk)
        {
            uiMemOffSet = (i * ((unsigned 
int) m_sMemoryChunkSize)) ;
            ptrChunk->DataSize = (((unsigned 
int) m_sTotalMemoryPoolSize) - uiMemOffSet);
            ptrChunk = ptrChunk->Next ;
        }
        
else
        {
            assert(
false && "Error : ptrChunk == NULL");
            
return false;
        }
    }
    
return true;
}

SMemoryChunk* CMemoryPool::SetChunkDefaults(SMemoryChunk* ptrChunk)
{
    
if(ptrChunk)
    {
        ptrChunk->Data = NULL;
        ptrChunk->DataSize = 0;
        ptrChunk->UsedSize = 0;
        ptrChunk->IsAllocationChunk = 
false;
        ptrChunk->Next = NULL;
    }
    
return ptrChunk;
}


SMemoryChunk *CMemoryPool::FindChunkSuitableToHoldMemory(
const std::size_t &sMemorySize)
{
    unsigned 
int uiChunksToSkip = 0;
    
bool bContinueSearch = true;
    SMemoryChunk *ptrChunk = m_ptrCursorChunk; 
    
for(unsigned int i = 0; i < m_uiMemoryChunkCount; i++)
    {
        
if(ptrChunk)
        {
            
if(ptrChunk == m_ptrLastChunk) 
            {
                ptrChunk = m_ptrFirstChunk;
            }

            
if(ptrChunk->DataSize >= sMemorySize)
            {
                
if(ptrChunk->UsedSize == 0)
                {
                    m_ptrCursorChunk = ptrChunk;
                    
return ptrChunk;
                }
            }
            uiChunksToSkip = CalculateNeededChunks(ptrChunk->UsedSize);
            
if(uiChunksToSkip == 0) uiChunksToSkip = 1;
            ptrChunk = SkipChunks(ptrChunk, uiChunksToSkip);
        }
        
else
        {
            bContinueSearch = 
false 
        }
    }
    
return NULL;
}

std::size_t CMemoryPool::MaxValue(
const std::size_t &sValueA, const std::size_t &sValueB) const
{
    
if(sValueA > sValueB)
    {
        
return sValueA;
    }
    
return sValueB;
}

void CMemoryPool::SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize)
{
    
if((ptrChunk))
    {
        ptrChunk->UsedSize = sMemBlockSize;
    }
    
else
    {
        assert(
false && "Error : Invalid NULL-Pointer passed");
    }
}

SMemoryChunk *CMemoryPool::SkipChunks(SMemoryChunk *ptrStartChunk, unsigned 
int uiChunksToSkip)
{
    SMemoryChunk *ptrCurrentChunk = ptrStartChunk;
    
for(unsigned int i = 0; i < uiChunksToSkip; i++)
    {
        
if(ptrCurrentChunk)
        {
            ptrCurrentChunk = ptrCurrentChunk->Next;
        }
        
else
        {

            assert(
false && "Error : Chunk == NULL was not expected.");
            
break ;
        }
    }
    
return ptrCurrentChunk;
}

   


測試
方法:

// 111.cpp : 定義控制臺應用程序的入口點。
//

#include "stdafx.h"
#include "CMemoryPool.h"
CMemoryPool* g_pMemPool = NULL;
class testMemoryPool
{
public:
    testMemoryPool(){
    }

    
void *operator new(std::size_t ObjectSize)
    {
        
return g_pMemPool->GetMemory(ObjectSize) ;
    }

private:
    
char a[25];
    
bool b;
    
long c;
};
//sizeof(32);


int _tmain(int argc, _TCHAR* argv[])
{

    g_pMemPool = 
new CMemoryPool();


    testMemoryPool* test = 
new testMemoryPool();




    
return 0;
}

 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多