• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            內(nèi)存池設(shè)計


                   也許有人會問:內(nèi)存池是什么呢? 主要用來干什么的?
                 大家都知道,C++可以使用指針來操作堆內(nèi)存以獲得高效率的內(nèi)存訪問,一般會使用全局new, delete的內(nèi)存管理函數(shù)來申請和分配內(nèi)存,但在大量使用內(nèi)存分配的程序里----比如:網(wǎng)絡(luò)游戲服務(wù)器的消息,每一條消息就分配一塊內(nèi)存,等消息處理完后,又要釋放內(nèi)存,這樣來來回回的new, delete操作,效率會大大折扣,因為new,delete函數(shù)不可能預(yù)先知道你的對象要分配多大空間,每一個都要從當(dāng)前的堆中尋找一塊可用的空間來分配一個對象,最要命的是當(dāng)你delete后,內(nèi)存還要重新整理內(nèi)存塊,這樣頻繁操作將造成低效率結(jié)果。
              于是,一個新的思想誕生了,如果當(dāng)你滿足以下條件時,你可以使用內(nèi)存池來提高效率:
                   (1) 當(dāng)你頻繁地操作一類對象時,即你老是new 和 delete
                   (2) 當(dāng)你知道使用一類對象的最大對象數(shù)時
                  你可以使用內(nèi)存池,它是預(yù)先分配一定數(shù)量的一段內(nèi)存空間,這一段空間預(yù)先分配了某類對象的數(shù)量,然后也可以像使用new, delete那樣的方式來管理內(nèi)存,不同在于這一段內(nèi)存空間的管理使用者要調(diào)用內(nèi)存池提供的相應(yīng)函數(shù)(CreateObj, DestoryObj)來操作,而且堆內(nèi)存由CObjectPool來管理。這樣可以獲得高效率的內(nèi)存操作。
              為什么這樣子就可以高效率呢?恐怕你有點質(zhì)疑,人家平常都用new, delete也挺爽的。好了,還是看下面內(nèi)存池的設(shè)計思路吧!
              一、我們?yōu)榱诉m應(yīng)不同的類對象,我們使用了模板的接口類----CObjectPool
                  二、MemPool類,內(nèi)存池的核心類。負責(zé)內(nèi)存管理, 主要使用的數(shù)據(jù)結(jié)構(gòu)是鏈表結(jié)構(gòu), 結(jié)構(gòu)為: Object|index, Object是某一類對象的數(shù)據(jù), 而index是它在內(nèi)存中的索引號, 這個很有用, 它是用來維持[已分配列表] 和 [空閑列表] 的地址計算。注:(它是浪費了4個字節(jié)的空間,但它的功勞大于它的罪過,你說用不用呢?)

                接下來應(yīng)該貼代碼了吧,大家都關(guān)注這個實質(zhì)性的東西了!
            //============================================================================// FileName  :ObjectPool.h
            // CreateDate:2008-02-20
            // Author    :chenguihong
            // Des       :內(nèi)存池
            //-------------------------------------------------------------------------------------

            #ifndef __OBJECT_POOL_H__
            #define __OBJECT_POOL_H__

            #include "MemPool.h"

            template <class T>
            class CObjectPool
            {   
            public:
                CObjectPool(int ObjectReserve = 1000):m_MemPool(sizeof(T),ObjectReserve){}
               
             ~CObjectPool()
             {
              m_MemPool.Release();
             }

                T* CreateObj()
             {
              return static_cast<T*>(m_MemPool.Alloc());
             }
               
             void DestoryObj(void*p)
             {
              m_MemPool.DeAlloc(p);
             }

             int Release()
             {
              return m_MemPool.Release(); 
             }

            public:
             MemPool m_MemPool;
            };

            #endif


            //-----------------------------------------------------------------------
            //======================================================================
            // FileName  :MemPool.h
            // CreateDate:2008-02-20
            // Author    :chenguihong
            // Des       :線程安全的內(nèi)存池
            //-------------------------------------------------------------------------------------
            #ifndef   __MEM_POOL_H__
            #define   __MEM_POOL_H__

            #include <windows.h>
            #include "Mutex.h"

            class MemPool
            {
               

            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            //一塊內(nèi)存.內(nèi)存塊的固定大小為 blockSize * blocks.

            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            public:
                MemPool(size_t block_size, size_t block_reserved);
                bool Init(size_t block_size, size_t block_reserved);
                int Release();

                //----------------------------------------------------
                //查看還有多少空間可以用
                //----------------------------------------------------
                size_t Capacity();

                //----------------------------------------------------
                //分配一個內(nèi)存和釋放一個內(nèi)存
                //----------------------------------------------------
                void* Alloc();
                void  DeAlloc(void* p);

                //----------------------------------------------------
                //判斷一個指針是不是由這個Pool分配的。
                //----------------------------------------------------
                bool  Is_ptr(void* p);

            private:
                size_t      m_blockSize;       //每一個塊的大小,即FixedAlloctor能分配的大小. 當(dāng)

            m_blockSize不能為1.
                size_t      m_blocks;           //每個MemChunck中,Block的個數(shù).
                size_t      m_avaliableBlocks; // 內(nèi)存池中,空閑的塊的個數(shù)

                //內(nèi)存塊的地址
                unsigned char* m_pData;
                //第一個可用塊,一個可用塊的大小是由blockSize指定的.
                unsigned long m_firstAvailableBlock;
                unsigned long m_blocksAvailable; //是不是可用的空閑塊
             
             CMutex m_Mutex;
            };

            #endif


            //---------------------------------------------------------------------------------------

            /*
            MemPool.cpp
            */

            #include "MemPool.h"
            #include <cassert>
            #include <tchar.h>

            #include <iostream>
            using namespace std;

            /********************************************************
            內(nèi)存池分配器.也就是一個固定大小的內(nèi)存分配器.
            Object|index 結(jié)構(gòu)
            *********************************************************/

            MemPool::MemPool(size_t block_size, size_t block_reserved)
            {
             m_pData = NULL;
             m_avaliableBlocks = 0;

                Init(block_size,block_reserved);
            }

            bool MemPool::Init(size_t blockSize, size_t blocks)
            {
                assert(blockSize > 0);
                assert(blocks > 0 && blocks < 10000000); //暫定10000000個,應(yīng)該足夠了吧!

                m_pData = (unsigned char*) malloc((blockSize + sizeof(unsigned long)) * blocks);

             if(m_pData == NULL)
                    return false;

                m_firstAvailableBlock = 0;
             m_blocks = blocks;
                m_blocksAvailable = blocks;
             m_blockSize = blockSize;

             
                //填充內(nèi)存塊的鏈
                unsigned long i = 0;
                unsigned char* p = m_pData;
             unsigned long* pNext = NULL;

             for (; i != blocks; p += (blockSize + sizeof(unsigned long)))
                {
                    pNext = (unsigned long*) (p + blockSize); //200000個整型溢出啊,加大馬力
              *pNext = ++i;
                }

             return true;
            }

            int MemPool::Release()
            {
             //請確保調(diào)用者釋放指針方能執(zhí)行操作
             if(m_blocksAvailable < m_blocks)  //出錯說明有內(nèi)存申請了但還沒有被釋放
             {
              int Result = m_blocks - m_blocksAvailable;
              return Result; 
             }
             
             if(m_pData != NULL)
             {
              free((unsigned char*)m_pData);
              m_pData = NULL;
              return 0;
             }
            }

             

            void* MemPool::Alloc()
            {
             //多線程訪問要加鎖, 也可以用守衛(wèi)來自動完成(線程安全)
             Mutex_Guard sc(&m_Mutex);
             unsigned char* pResult = NULL;

             if(m_blocksAvailable > 0)
             {
              //把第一個可用返回給用戶
              //cout<<"申請到第"<<m_firstAvailableBlock+1<<"塊"<<endl;
              pResult = m_pData + (m_firstAvailableBlock * (m_blockSize + sizeof(unsigned

            long)));
              m_firstAvailableBlock = *(unsigned long*)(pResult + m_blockSize);
              memset(pResult, 0, m_blockSize); //清0
              m_blocksAvailable--;
             }
             else
             {
              return pResult;
             }
              
               
             return pResult;
            }

            void  MemPool::DeAlloc(void* p)
            {
             //多線程訪問要加鎖, 用守衛(wèi)來自動完成(線程安全)
             Mutex_Guard sc(&m_Mutex);

             assert(Is_ptr(p)); //檢查是不是非法指針

             unsigned char* toRelease = static_cast<unsigned char*>(p);

             //把釋放掉的塊加入到表頭里.新建一個表頭,表頭下一個塊指向原來的第一個可用塊
             * ((unsigned long*)(toRelease + m_blockSize)) = m_firstAvailableBlock;
             //第一個可用塊指向表頭
             m_firstAvailableBlock = (toRelease - m_pData) / (m_blockSize + sizeof(unsigned

            long));
             //塊對齊檢查
             assert(m_firstAvailableBlock == (toRelease - m_pData) / (m_blockSize + sizeof

            (unsigned long)));

             m_blocksAvailable++;

             //cout<<"釋放掉第"<<m_firstAvailableBlock+1<<"塊"<<endl;
            }


            bool MemPool::Is_ptr(void* p)
            {
             //內(nèi)存不在這個里面。也不是他分配的。
                if(p < m_pData  || p > (m_pData + (m_blockSize + sizeof(unsigned long)) * (m_blocks-1)))
              return false;

                //指針沒在blockSize邊界上對齊.肯定不是由這個MemPool分配的
                long result = ((unsigned char*)p - m_pData) % (m_blockSize + sizeof(unsigned long));
             if(result != 0)
              return false;
               
             return true;
            }

            //----------------------------------------------------
            //查看還有多少空間可以用
            //----------------------------------------------------
            size_t MemPool::Capacity()
            {
                return m_blocksAvailable;
            }

            使用方法:  CObjectPool<int> m_ObjectPool(10000); //10000個對象
                               int *p =  m_ObjectPool.CreateObj();  //相當(dāng)于new
                               m_ObjectPool.DestoryObj(p);            //相當(dāng)于delete

            好了,代碼到些結(jié)束,該出測試報告了吧!

            性能測試, 當(dāng)當(dāng)當(dāng)當(dāng).....

            與普通的系統(tǒng)函數(shù)new和delete作對比, 各自開10條線程進行內(nèi)存申請1,000,000對象, 每條線程反復(fù)地進

            行申請和釋放。

            在CPU:Pentium D 3.0G, 內(nèi)存1G的情況下:
            結(jié)果: (1) 采用內(nèi)存池用時:        5328ms
                  (2) 采用new 和 delete用時:27078ms

            如果程序中有什么BUG或有什么看法的話,歡迎留言/評論,謝謝!

             

            posted on 2008-04-16 09:01 RedLight 閱讀(1946) 評論(3)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)服務(wù)器開發(fā)

            評論

            # re: 內(nèi)存池設(shè)計[未登錄] 2008-11-18 04:35 張帥

            設(shè)計的挺好的,學(xué)到了,謝謝  回復(fù)  更多評論   

            # re: 內(nèi)存池設(shè)計 2012-10-13 02:08 Alven

            你這個只支持按堆的順序DeAlloc吧....用多線程可以么?  回復(fù)  更多評論   

            # re: 內(nèi)存池設(shè)計[未登錄] 2014-04-02 08:52 路人甲

            你這遠遠不到內(nèi)存池的概念吧!  回復(fù)  更多評論   

            <2010年7月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導(dǎo)航

            統(tǒng)計

            公告


            Name: Galen
            QQ: 88104725

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            相冊

            My Friend

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久99精品国产自在现线小黄鸭| 国产精品无码久久久久| 亚洲狠狠婷婷综合久久蜜芽| 大香伊人久久精品一区二区| 久久久久久人妻无码| 国内精品久久久久久久久| 热RE99久久精品国产66热| 久久综合狠狠综合久久| 精品人妻伦九区久久AAA片69 | 久久亚洲中文字幕精品有坂深雪| 国产美女久久久| 亚洲精品乱码久久久久久蜜桃 | 2020最新久久久视精品爱| 久久精品无码一区二区WWW | 久久青青色综合| 久久综合丝袜日本网| 一本色道久久综合亚洲精品| 99久久久久| 热久久这里只有精品| 久久婷婷五月综合色奶水99啪| 久久精品国产一区二区 | 久久精品中文闷骚内射| 欧美伊人久久大香线蕉综合69| 99久久这里只有精品| 久久人与动人物a级毛片| 久久精品无码专区免费| 久久久精品国产sm调教网站| 久久国产色av免费看| 久久国产AVJUST麻豆| 久久久久国产一区二区三区| 日本久久久精品中文字幕| 久久久国产精品亚洲一区 | 一本久久久久久久| 国产精品久久久久久久久| 久久综合狠狠综合久久综合88| 久久无码中文字幕东京热| 污污内射久久一区二区欧美日韩 | 欧美麻豆久久久久久中文| 九九久久精品无码专区| 久久国产成人精品国产成人亚洲| 久久夜色精品国产亚洲|