青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

OldJiang.com

浩毛的博客

OldJiang.com
posts - 14, comments - 81, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    上一篇內(nèi)存池的實現(xiàn)其實更像一個后備列表的實現(xiàn)。使用上來說不是很方便,要申請的內(nèi)存塊是一個BLOCK結(jié)構(gòu)的一個個成員,而且每次從系統(tǒng)內(nèi)存堆中申請都是一小塊一小塊,也沒有考慮字節(jié)對齊。因此讓我們來看看新的一個內(nèi)存池的實現(xiàn)吧。
    這個內(nèi)存池是根據(jù)《c++應(yīng)用程序性能優(yōu)化》書里的固定尺寸的內(nèi)存池原理做了一些改動用C語言寫的。大家有興趣可以去看看,里面說的最詳細。
    簡單說下這個內(nèi)存池的原理,內(nèi)存池里由N個memblock以一個雙向鏈表組成,每個memblock的組成是一個HEAD塊+M個固定長度的memchunk組成,memchunk就是你將來要從池中申請的內(nèi)存塊。
    我們來看下如下幾個情況:

    1.內(nèi)存池初始化后,內(nèi)存池的memblock鏈表頭是NULL。

    2.第一次從池中申請一個memchunk,內(nèi)存池根據(jù)initsize和chunksize從系統(tǒng)內(nèi)存堆中申請一個(memblock head)+ chunksize*initsize的內(nèi)存塊,對block head部分數(shù)據(jù)字段進行初始化,并將每個chunk的頭4個字節(jié)來存放該memblock里下個可用chunk的編號,因為是固定長度的chunk,所以,可以很容易根據(jù)編號和chunk長度計算出chunk的地址。創(chuàng)建了memblock后,將第一個chunk (設(shè)為A) 返回給用戶,并將block head的first字段設(shè)置為chunk A頭4個字節(jié)的值(也就是下個可用chunk編號)。同時將創(chuàng)建的block加入到鏈表頭中。

    3.下次申請memchunk的時候,遍歷鏈表,找出有空閑chunk的BLOCK,對BLOCK進行和第一次申請時類似的處理。
同時檢查該BLOCK里還有多余的空閑chunk不,有的話就將該block移動到鏈表頭部。以提高下次申請時遍歷鏈表的速度。
如果遍歷完鏈表也沒有找到有空閑chunk的block,就從系統(tǒng)內(nèi)存堆中申請一個BLOCK,將之加入到鏈表頭。

     4.將申請的memchunk (假設(shè)為A)歸還給池的時候,遍歷memblock鏈表,根據(jù)A的地址來找出A所在的block。
      找到后根據(jù)這個 memchunk A 的地址計算出它的編號;
      將block->first 的編號存入A的頭4個字節(jié)中; 將block->first更改為A的編號。(就是chunk的鏈表操作)
      最后,將A所在的這個memblock移動到鏈表頭(因為有空閑chunk),以提高申請chunk時的速度。(鏈表只需遍歷一次)。在書中,這里還有個處理:如果該block的chunk都是空閑的,就把block釋放了(歸還給系統(tǒng)內(nèi)存堆),我沒有這樣做,打算單獨寫個清理的操作。
      
      大概原理就是這樣,考慮到和64位機兼容,chunk和block都按8字節(jié)對齊。代碼中的memheap就是mempool。只是名稱我該成heap了。。
      在后面的代碼中,對內(nèi)存池實現(xiàn)有比較詳細的注釋。

      回顧下這個內(nèi)存池的原理,明顯的優(yōu)點是減少了內(nèi)存碎片,字節(jié)對齊,但是有個顯而易見的問題是,如果內(nèi)存池中有大量(成千上萬)個memblock的話,對block的遍歷檢索將是一個性能瓶頸,申請chunk的操作還好點,內(nèi)部做了一些優(yōu)化處理,歸還chunk時查找鏈表的速度將比較慢,最壞的情況是有多少個memblock就檢索多少次。。可以考慮對這里做一些檢索上的優(yōu)化和更改,不用雙向鏈表,用其他方式來做。最簡單的優(yōu)化就是用游戲粒子系統(tǒng)里普遍使用的一種算法,將有空閑chunk的block放一個鏈表,沒有空閑chunk的block放另外一個鏈表,再做一些分配上的改動,也許能提高一些速度。

mempool.h

/*********************************
 * mempool
 *******************************
*/

#define MEMPOOL_ALIGNMENT 8//兼容64位系統(tǒng),按8字節(jié)對齊

struct memblock
{
    uint32_t        size;
//該Block下chunk內(nèi)存總長度;
    uint32_t        free;//空閑chunk數(shù)
    uint32_t        first;//第一個空閑chunk id
    uint32_t        dumpalign;//按8字節(jié)對齊,只是占位用
    struct memblock*    next_block;//指向下個Block
    struct memblock*    prev_block;//指向上個Block
    char        data[1];//chunk區(qū)首地址
}
;

struct memheap
{
    
struct memblock*    block_header;//Block雙向鏈表頭
    uint32_t        chunk_size;//chunk大小
    uint32_t        init_size;//第一次創(chuàng)建Block時的chunk數(shù)
    uint32_t        grow_size;//之后創(chuàng)建Block時的chunk數(shù)
  
//  uint32_t        max_size;//最大memory使用
  
//  uint32_t        blocknum;
}
;

//create and init struct memheap,返回memheap指針
void*    memheap_init(uint32_t chunksize,uint32_t initsize,uint32_t growsize);

//destruct memheap 
void    memheap_dealloc(struct memheap* pool);

//從內(nèi)存池申請一塊長度為chunk_size的內(nèi)存
inline
void*    memheap_alloc(struct memheap* pool);

//向內(nèi)存池歸還一塊內(nèi)存,成功則返回NULL  
inline 
void*    memheap_free(struct memheap* pool,void* p);

//清理內(nèi)存池多余的內(nèi)存
void    memheap_clean(struct memheap* pool,void* p);


mempool.c


/*********************************
 * mempool
 *******************************
*/

//將一個block從鏈表中移動到首部
#define MEMBLOCK_MOVE_TO_HEAD(HEAD,BLOCK)  \
    
if  ((BLOCK) != (HEAD)) { \
    
struct memblock* prev=(BLOCK)->prev_block; \
    
struct memblock* next=(BLOCK)->next_block; \
    
if (prev) prev->next_block=next;\
    
if (next) next->prev_block=prev;\
    (BLOCK)
->prev_block=NULL;\
    (BLOCK)
->next_block=(HEAD);\
    (HEAD)
->prev_block=(BLOCK); \
    (HEAD)
=(BLOCK);     }

    

//-----------------declare-----------------
//創(chuàng)建一個Block
static inline void* memblock_create(uint32_t chunksize,uint32_t num);

//------------------implement---------------
static inline void* 
memblock_create(uint32_t chunksize,uint32_t num)
{
    
//memblock長度 
    uint32_t length=sizeof(struct memblock) -sizeof(char*)  + num * chunksize;
    
struct memblock* block=G_MALLOC(length);
    
if (block==NULL){
    L_WARN(
"%s,malloc error.",__func__);
    
return (NULL);
    }

    
    block
->size=num * chunksize;
    block
->free=num-1;//因為創(chuàng)建后就分配出去,所以空閑chunk數(shù)num-1
    block->first=1;//同上,指向第二個chunk
    block->next_block=NULL;
    block
->prev_block=NULL;
   
    
//初始化chunk編號,每個chunk頭4個字節(jié)存放下個可用chunk的編號。
    char* offset=block->data;
    uint32_t i
=num-1;
    
for (i=1;i<num;i++){
    
*((uint32_t*)offset)=i;
    offset 
+= chunksize;
    }

    
return (block);
}


inline 
void*
memheap_alloc(
struct memheap* pool)
{
    
struct memblock* block=pool->block_header;

    
if (block==NULL){
    
//鏈表頭為空,第一次創(chuàng)建一個Block;并返回該block的第一個chunk
    block=memblock_create(pool->chunk_size , pool->init_size);
    pool
->block_header=block;

    
return (block->data);
    }


    
//查找有空閑chunk的Block
    while (block!=NULL && block->free==0)
    block
=block->next_block;
     
    
if (block){
    
//找到一塊block,根據(jù)block->first計算出空閑chunk的地址
    char* mem=block->data + (block->first*pool->chunk_size);
    
//更改first為找到的chunk的開始4個字節(jié)存放的編號
    block->first=*((uint32_t*)mem);
    block
->free--;//空閑chunk數(shù)減一
    
//將有空閑chunk的Block移動到鏈表頭部
    if (block!=pool->block_header && block->free>pool->block_header->free) {
        MEMBLOCK_MOVE_TO_HEAD(pool
->block_header,block)  
    }

    
    
return (mem);//分配出去的chunk的開始4個字節(jié)的內(nèi)容無用了
    }

    
else {
    
//沒有找到有空閑chunk的block。創(chuàng)建一個Block,并將之加入到鏈表頭
    block=memblock_create(pool->chunk_size , pool->grow_size);
    
    block
->next_block=pool->block_header;
    pool
->block_header->prev_block=block;
    pool
->block_header=block;
    
    
return (block->data);
    }
    
}


inline 
void*
memheap_free(
struct memheap* pool,void* p)
{
    
struct memblock* block=pool->block_header;
    
//更加p地址值找出p所在的Block
    while  (block && (p<(void*)block->data ||
       p
>= (void*)block->data+block->size))
    block
=block->next_block;

    
if (block==NULL) {
    L_WARN(
"%s,no memblock find",__func__);    
    
return (p);
    }


    uint32_t offset
=-(void*) block->data;
#ifndef NDEBUG 
     
//檢查p是否指向一個合法的chunk首地址 
    
// chunk_size肯定是偶數(shù),使用與運算實現(xiàn)取模
    
// offset % pool->chunk_size
    if ((offset & (pool->chunk_size-1))>0{    
    L_ERROR(
"%s,invalid pointer for free.",__func__);
    
return (p);
    }

#endif
    
//設(shè)置Block
    block->free++;//空閑chunk數(shù)加一
    *((uint32_t*)p)=block->first;//修改歸還的chunk的頭4個字節(jié)的值
    block->first=(uint32_t)(offset/pool->chunk_size);//first指向歸還的chunk

    
//將Block移動到鏈表頭部
    MEMBLOCK_MOVE_TO_HEAD(pool->block_header,block)  

    
return (NULL);
}



void*
memheap_init(uint32_t chunksize,uint32_t initsize,uint32_t growsize)
{
    
if (!initsize || !growsize) return (NULL);
    
    
struct memheap* pool=G_MALLOC(sizeof(struct memheap));

    
//保證chunk size最小能存放一個uint32_t大小的數(shù)
    if (chunksize<sizeof(uint32_t)) chunksize=sizeof(uint32_t);
    
//更改chunk size字節(jié)對齊(8字節(jié))
    pool->chunk_size=(chunksize+(MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1);

    pool
->block_header=NULL;
    pool
->init_size=initsize;
    pool
->grow_size=growsize;
  
//  pool->max_size=0;
   
// pool->blocknum=0;
    return (pool);
}


void
memheap_dealloc(
struct memheap* pool)
{

   
    
struct memblock* block=pool->block_header;
    
struct memblock* temp=NULL;
    
while (block){
    temp
=block;
    block
=block->next_block;
    G_FREE(temp);    
    }

    G_FREE(pool);
}

Feedback

# re: 一個簡單實用的內(nèi)存池實現(xiàn)之二 (C實現(xiàn))[未登錄]  回復(fù)  更多評論   

2009-09-27 19:35 by kkk
舉個范例就更好了
不知道我是不是太傻了

# re: 一個簡單實用的內(nèi)存池實現(xiàn)之二 (C實現(xiàn))  回復(fù)  更多評論   

2009-09-27 20:59 by 浩毛
C++ 應(yīng)用程序性能優(yōu)化,第 6 章:內(nèi)存池
http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html

# re: 一個簡單實用的內(nèi)存池實現(xiàn)之二 (C實現(xiàn))[未登錄]  回復(fù)  更多評論   

2009-09-30 12:51 by megax
>有的話就將該block移動到鏈表頭部。以提高下次申請時遍歷鏈表的速度。
直接一個指針保存最后一次分配的block不就行了?loki里面有個內(nèi)存池,非常非常棒。

# re: 一個簡單實用的內(nèi)存池實現(xiàn)之二 (C實現(xiàn))  回復(fù)  更多評論   

2009-10-02 22:37 by 凡客誠品
loki里面有個內(nèi)存池,非常非常棒

# re: 一個簡單實用的內(nèi)存池實現(xiàn)之二 (C實現(xiàn))[未登錄]  回復(fù)  更多評論   

2010-07-06 00:39 by Lu
請問博主怎么實現(xiàn)代碼折疊的功能呢?
OldJiang.com
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美福利精品| 久久一区国产| 国产精品人人爽人人做我的可爱| 欧美aaa级| 亚洲一区二区毛片| 亚洲精美视频| 欧美sm重口味系列视频在线观看| 亚洲天堂网在线观看| 亚洲激情视频网站| 亚洲一区久久久| 国产精品99久久久久久www| 亚洲国产裸拍裸体视频在线观看乱了中文 | 国产一区二区久久| 欧美日韩一区在线播放| 欧美视频中文一区二区三区在线观看 | 免费国产自线拍一欧美视频| 久久永久免费| 欧美日韩精品免费看| 欧美四级电影网站| 国产区精品在线观看| 1024国产精品| 99在线精品视频在线观看| 亚洲欧美网站| 欧美黄色网络| 欧美在线一二三区| 国产精品女主播一区二区三区| 久久av二区| 亚洲电影欧美电影有声小说| 麻豆av一区二区三区久久| 亚洲人成人一区二区在线观看| 久久精品99久久香蕉国产色戒| 日韩一级黄色大片| 国产一区激情| 亚洲人被黑人高潮完整版| 欧美三区美女| 亚洲精品中文在线| 亚洲高清毛片| 欧美高清自拍一区| 欧美~级网站不卡| 最新国产拍偷乱拍精品| 另类人畜视频在线| 麻豆精品传媒视频| 91久久精品视频| 久久人人97超碰国产公开结果| 亚洲一区欧美| 在线成人欧美| 亚洲美女色禁图| 国产一区二区三区高清播放| 久久精品九九| 欧美大片在线影院| 欧美一区日韩一区| 久久婷婷激情| 亚洲视频1区2区| 久久久久久亚洲精品中文字幕| 激情综合五月天| 亚洲私人影院在线观看| 激情综合中文娱乐网| 亚洲精品在线观看视频| 国产视频综合在线| 日韩午夜在线视频| 精品动漫3d一区二区三区免费版 | 狠狠色噜噜狠狠狠狠色吗综合| 亚洲欧美综合精品久久成人| 一本久久a久久精品亚洲| 久久精品主播| 亚洲国产精品成人精品| 亚洲一区二区动漫| 亚洲欧美国产日韩天堂区| 亚洲一区二区三区欧美 | 午夜精品久久久久久| 黄色一区二区在线观看| 亚洲国产三级在线| 国产一区二区三区四区老人| 亚洲国产日韩欧美| 亚洲高清自拍| 久久免费视频这里只有精品| 亚洲在线免费| 卡通动漫国产精品| 欧美第一黄网免费网站| 国产亚洲一本大道中文在线| 亚洲一区尤物| 午夜精品一区二区三区在线播放| 欧美日韩情趣电影| 一区二区精品在线观看| 亚洲精品一区久久久久久| 久久一二三区| 亚洲区欧美区| 午夜精品成人在线视频| 国产视频在线观看一区二区| 久久精品女人的天堂av| 欧美精品导航| 亚洲一区二区三区精品在线| 久久久精品tv| 一区二区免费在线播放| 国产精品视频福利| 另类av一区二区| 亚洲一区二区三区四区在线观看| 欧美中文在线观看| 最新日韩在线| 激情六月婷婷综合| 国产精品免费视频观看| 免费一级欧美在线大片| 亚洲图片欧美午夜| 亚洲欧洲一区二区在线观看| 久久久av毛片精品| 亚洲在线成人精品| 一区二区三区欧美| 伊人一区二区三区久久精品| 欧美三日本三级少妇三2023| 久久资源在线| 欧美综合77777色婷婷| 亚洲最新中文字幕| 夜夜嗨av一区二区三区四季av | 欧美日韩亚洲精品内裤| 久久影音先锋| 久久久久久亚洲综合影院红桃| 午夜影院日韩| 久久国产主播| 免费成人小视频| 欧美激情精品久久久久久久变态 | 最新日韩中文字幕| 国产永久精品大片wwwapp| 国产精品久久久久久久久久久久| 欧美日韩国产黄| 亚洲社区在线观看| 国产美女诱惑一区二区| 亚洲视频网站在线观看| 欧美 日韩 国产 一区| 午夜精品久久久久久久久| 欧美日本亚洲| 亚洲毛片视频| 亚洲视频在线一区| 欧美色欧美亚洲另类二区| 亚洲精品偷拍| 夜夜爽夜夜爽精品视频| 欧美风情在线| 欧美+日本+国产+在线a∨观看| 国内精品久久久久久久97牛牛| 亚洲小视频在线| 亚洲欧美综合| 国产精品久久久一区麻豆最新章节 | 性做久久久久久| 欧美一级艳片视频免费观看| 国产精品久久久久久久久久久久久| 一区二区三区国产精品| 一本色道久久综合狠狠躁的推荐| 牛牛影视久久网| 亚洲精品免费电影| 一区二区三区三区在线| 国产精品久久久久久久9999| 中文国产一区| 久久国产乱子精品免费女| 国内成人精品一区| 美女主播视频一区| 亚洲精品久久久久久一区二区| 亚洲日本aⅴ片在线观看香蕉| 久久午夜精品一区二区| 亚洲国产色一区| 亚洲免费在线播放| 国产亚洲第一区| 久久综合久久综合久久| 亚洲精品乱码久久久久久黑人 | 亚洲国产欧美在线| 欧美日韩大片| 午夜在线电影亚洲一区| 欧美成人一区二区三区在线观看| 欧美一区二区三区视频免费播放 | 亚洲最快最全在线视频| 国产精品一区二区a| 久久精品综合一区| 亚洲娇小video精品| 欧美一区二区免费| 在线视频观看日韩| 国产精品久久77777| 乱人伦精品视频在线观看| 宅男66日本亚洲欧美视频| 久久综合久久综合久久| 夜夜夜久久久| 影音先锋久久精品| 国产精品人人爽人人做我的可爱| 久久亚洲春色中文字幕久久久| 亚洲毛片在线免费观看| 久久亚洲欧美| 欧美黄色成人网| 亚洲一区二区高清| 亚洲三级观看| 狂野欧美激情性xxxx欧美| 亚洲天堂激情| 亚洲精品国产精品国自产在线 | av不卡在线| 欧美成人一区二区三区在线观看 | 一区二区日韩伦理片| 欧美69wwwcom| 久久成人在线| 亚洲视频网在线直播| 国产在线一区二区三区四区| 国产精品国产一区二区| 美女图片一区二区| 久久精品国产一区二区三| 亚洲欧美综合精品久久成人|