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

posts - 15,comments - 21,trackbacks - 0
      寫服務(wù)器的,通常會(huì)涉及到內(nèi)存池的東西,自己在這方面也看了寫了一些東西,有些體會(huì),寫出來(lái)跟大家分享下。
      內(nèi)存池基本包含以下幾個(gè)東西,第一,初始化。第二,分配內(nèi)存。第三,回收內(nèi)存。所謂初始化,就是在服務(wù)器啟動(dòng)的時(shí)候,或者第一次需要內(nèi)存的時(shí)候,系統(tǒng)分配很大的一塊內(nèi)存,方便之后的使用。分配內(nèi)存,就是從內(nèi)存池中取出需要的內(nèi)存給外部使用,當(dāng)然這里需要考慮的是當(dāng)內(nèi)存池中沒有內(nèi)存可分配時(shí)候的處理。回收內(nèi)存,簡(jiǎn)單來(lái)說(shuō),就是外面對(duì)象生命期結(jié)束了,將分配出去的內(nèi)存回收入內(nèi)存池中。好了簡(jiǎn)單概念就說(shuō)完了,我們先來(lái)看一種最簡(jiǎn)單的設(shè)計(jì)方式。
//為了方便描述,這里附上幾個(gè)簡(jiǎn)單的鏈表操作宏
#define INSERT_TO_LIST( head, item, prev, next ) \
do{ \
if ( head ) \
(head)->prev = (item); \
(item)->next = (head); \
(head) = (item);          \
}while(0)
#define REMOVE_FROM_LIST(head, item, prev, next) \
do{ \
if ( (head) == (item) ) \
{ \
(head) = (item)->next; \
if ( head ) \
(head)->prev = NULL; \
} \
else \
{ \
if ( (item)->prev ) \
(item)->prev->next = (item)->next;          \
\
if ( (item)->next ) \
(item)->next->prev = (item)->prev;          \
} \
}while(0)
struct student
{
      char name[32];
      byte sex;
      
      struct student *prev,*next;
};

static struct mem_pool
{
      //該指針用來(lái)記錄空閑節(jié)點(diǎn)
      
struct student *free;
      //該變量記錄分配結(jié)點(diǎn)個(gè)數(shù)
      size_t alloc_cnt;
}s_mem_pool;

//分配內(nèi)存“塊”的函數(shù)
bool mem_pool_resize(size_t size)
{
      //該函數(shù)創(chuàng)建size個(gè)不連續(xù)的對(duì)象,把他們通過鏈表的方式加入到s_mem_pool.free中
      for ( size_t i = 0;i < size;++i )
      {
            
struct student *p = (struct student *)malloc(sizeof(struct student));
            
if ( !p )
               return false;
            
            p->prev = p->next = NULL;
            INSERT_TO_LIST(s_mem_pool.free,p,prev,next);

      }

      s_mem_pool.alloc_cnt += size;
}

#define MEM_INIT_SIZE 512  
#define MEM_INC_SIZE 256
//初始化函數(shù)
bool mem_pool_init()
{
if ( !mem_pool_resize(MEM_INIT_SIZE) )
            return false;
return true;
}
struct student *get_data()
{
if ( s_mem_pool.free == NULL )
{
            if ( !mem_pool_resize(MEM_INC_SIZE) )
                  return NULL;
}
struct student *ret = s_mem_pool.free;
REMOVE_FROM_LIST(s_mem_pool.free,ret,prev,next)
return ret;
}
void free_data(struct student *p)
{
if ( !p )
            return;
memset(p,0,sizeof(struct student));
INSERT_TO_LIST(s_mem_pool.free,p,prev,next)
}
好了最簡(jiǎn)單的內(nèi)存池的大致框架就是這樣。我們先來(lái)看下他的過程。首先,在mem_pool_init()函數(shù)中,他先分配512個(gè)不連續(xù)的student對(duì)象。每分配出來(lái)一個(gè)就把它加入到free鏈表中,初始化完成后內(nèi)存池大概是這樣的

接下來(lái)就是從內(nèi)存池中取出一個(gè)對(duì)象get_data()。函數(shù)先去判斷是否有空閑的對(duì)象,有則直接分配,否則再向系統(tǒng)獲取一"塊"大的內(nèi)存。調(diào)用一次后的內(nèi)存池大概是這樣的

釋放對(duì)象,再把對(duì)象加入到Free鏈表中。
以上就是過程的簡(jiǎn)單分析,下面我們來(lái)看看他的缺點(diǎn)。
第一,內(nèi)存不是連續(xù)的,容易產(chǎn)生碎片
第二,一個(gè)類型就得寫一個(gè)這樣的內(nèi)存池,很麻煩
第三,為了構(gòu)建這個(gè)內(nèi)存池,每個(gè)沒對(duì)象必須加上一個(gè)prev,next指針
好了,我們來(lái)優(yōu)化一下它。我們重新定義下我們的結(jié)構(gòu)體
union student
{
    
int index;
    
struct
    {
        
char name[32];
        
byte sex;
    }s;
};

static struct mem_pool
{
    
//該下標(biāo)用來(lái)記錄空閑節(jié)點(diǎn)
    int free;
    
//內(nèi)存池
    union student *mem;
    
//已分配結(jié)點(diǎn)個(gè)數(shù)
    size_t alloc_cnt;
}s_mem_pool;

//分配內(nèi)存塊的函數(shù)
bool mem_pool_resize(size_t size)
{
    size_t new_size 
= s_mem_pool.alloc_cnt+size;
    union student 
*tmp = (union student *)realloc(s_mem_pool.mem,new_size*sizeof(union student));
    
if ( !tmp )
        
return false;
        
    memset(tmp
+s_mem_pool.alloc_cnt,0,size*sizeof(union student));
    size_t i 
= s_mem_pool.alloc_cnt;
    
for ( ;i < new_size - 1;++i )
    {
        tmp[i].index 
= i + 1;
    }
    
    tmp[i].index 
= -1;
    s_mem_pool.free 
= s_mem_pool.alloc_cnt;
    s_mem_pool.mem 
= tmp;
    s_mem_pool.alloc_cnt 
= new_size;
    
    
return true;
}

#define MEM_INIT_SIZE    512  
#define MEM_INC_SIZE    256
//初始化函數(shù)
bool mem_pool_init()
{
    
if ( !mem_pool_resize(MEM_INIT_SIZE) )
        
return false;
        
    
return true;
}

union student 
*get_data()
{
    
if ( s_mem_pool.free == -1 )
    {
        
if ( !mem_pool_resize(MEM_INC_SIZE) )
            
return NULL;
    }
    
    union student 
*ret = s_mem_pool.mem+s_mem_pool.free;
    s_mem_pool.free 
= ret->index;
    
return ret;
}

void free_data(union student *p)
{
    
if ( !p )
        
return;
    
    p
->index = s_mem_pool.free;
    s_mem_pool.free 
= p - s_mem_pool.mem;
}
我們來(lái)看看改進(jìn)了些什么。第一student改成了聯(lián)合體,這主要是為了不占用額外的內(nèi)存,也就是我們上面所說(shuō)的第三個(gè)缺點(diǎn),第二,我們使用了realloc函數(shù),這樣我們可以使我們分配出來(lái)的內(nèi)存是連續(xù)的。我們初始化的時(shí)候多了一個(gè)for循環(huán),這是為了記錄空閑對(duì)象的下標(biāo),當(dāng)我們?nèi)〕鲆粋€(gè)對(duì)象時(shí),free可以立刻知道下一個(gè)空閑對(duì)象的位置,釋放的時(shí)候,對(duì)象先記錄free此時(shí)的值,接著再把free賦值成該對(duì)象在數(shù)組的下標(biāo),這樣就完成了回收工作。
我們繼續(xù)分析這段代碼,問題在realloc函數(shù)上,如果我們的s_mem_pool.mem已經(jīng)很大了,在realloc的時(shí)候我們都知道,先要把原來(lái)的數(shù)據(jù)做一次拷貝,所以如果數(shù)據(jù)量很大的情況下做一次拷貝,是會(huì)消耗性能的。那這里有沒有好的辦法呢,我們進(jìn)一步優(yōu)化
思路大概是這樣
初始化

再次分配的時(shí)候,我們只需要重新分配新的內(nèi)存單元,而不需要拷貝之前的內(nèi)存單元。

因此基于此思路,我們修改我們的代碼
#include <stdio.h>
#include 
<stdlib.h>

struct student
{
    
int index;

    
char name[32];
    
byte sex;
};

static struct mem_pool
{
    
//該下標(biāo)用來(lái)記錄空閑節(jié)點(diǎn)
    int free;
    
//內(nèi)存池
    struct student **mem;
    
//已分配塊個(gè)數(shù)
    size_t block_cnt;
}s_mem_pool;

#define BLOCK_SIZE        256        //每塊的大小
//分配內(nèi)存塊的函數(shù)
bool mem_pool_resize(size_t block_size)
{
    size_t new_cnt 
= s_mem_pool.block_cnt + block_size;
    
struct student **tmp = (struct student **)realloc(s_mem_pool.mem,new_size*sizeof(struct student *));
    
if ( !tmp )
        
return false;
        
    memset(tmp
+s_mem_pool.block_cnt,0,size*sizeof(struct student*));
    
for ( size_t i = s_mem_pool.block_cnt;i < new_cnt;++i )
    {
        tmp[i] 
= (struct student *)calloc(BLOCK_SIZE,sizeof(struct student));
        
if ( !tmp[i] )
            
return false;
            
        size_t j 
= 0;
        
for(;j < BLOCK_SIZE - 1;++j )
        {
            tmp[i][j].index 
= i*BLOCK_SIZE+j+1;
        }
        
        
if ( i != new_cnt-1 )
            tmp[i][j].index 
= (i+1)*BLOCK_SIZE;
        
else
            tmp[i][j].index 
= -1;
    }
    
    s_mem_pool.free 
= s_mem_pool.alloc_cnt*BLOCK_SIZE;
    s_mem_pool.mem 
= tmp;
    s_mem_pool.block_cnt 
= new_cnt;
    
    
return true;
}
 
#define MEM_INC_SIZE    10
//初始化函數(shù)
bool mem_pool_init()
{
    
if ( !mem_pool_resize(MEM_INIT_SIZE) )
        
return false;
        
    
return true;
}

struct student *get_data()
{
    
if ( s_mem_pool.free == -1 )
    {
        
if ( !mem_pool_resize(MEM_INC_SIZE) )
            
return NULL;
    }
    
    
struct student *ret = s_mem_pool.mem[s_mem_pool.free/BLOCK_SIZE]+s_mem_pool.free%BLOCK_SIZE;
    
int pos = s_mem_pool.free;
    s_mem_pool.free 
= ret->index;
    ret
->index = pos;
    
return ret;
}

void free_data(struct student *p)
{
    
if ( !p )
        
return;
    
    
int pos = p->index;
    p
->index = s_mem_pool.free;
    s_mem_pool.free 
= pos;
}
這里不一樣的地方主要在mem_pool_resize函數(shù)中,mem變成了2級(jí)指針,每次realloc的時(shí)候只需要分配指針數(shù)組的大小,無(wú)須拷貝對(duì)象,這樣可以提高效率,但是為了在釋放的時(shí)候把對(duì)象放回該放的位置,我們這里在結(jié)構(gòu)體里加入了index變量,記錄它的下標(biāo)。在內(nèi)存池里,它表示下個(gè)空閑對(duì)象的下標(biāo),在內(nèi)存池外,它表示在內(nèi)存池中的下標(biāo)。總的來(lái)說(shuō)滿足了一個(gè)需求,卻又帶來(lái)了新的問題,有沒有更好的方法呢,答案是肯定,不過今天先寫到這里,明天繼續(xù)。
posted on 2012-07-19 11:41 梨樹陽(yáng)光 閱讀(3558) 評(píng)論(2)  編輯 收藏 引用 所屬分類: C

FeedBack:
# re: 淺談內(nèi)存池幾種設(shè)計(jì)方式[未登錄]
2012-07-20 07:55 | 123
上圖談思路就行了,上代碼也是直接拖過不看的。
共享代碼可以直接給個(gè)下載鏈接  回復(fù)  更多評(píng)論
  
# re: 淺談內(nèi)存池幾種設(shè)計(jì)方式
2012-07-23 09:27 | egmkang
額....這年頭,還真有人去設(shè)計(jì)內(nèi)存池啊
有沒有試過tcmalloc和jemalloc,用自己的內(nèi)存池和別人的內(nèi)存分配器比一下,試試  回復(fù)  更多評(píng)論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲日本一区二区三区| 中文有码久久| 亚洲第一天堂无码专区| 欧美在线看片a免费观看| 99re6热在线精品视频播放速度| 日韩视频一区二区在线观看 | 亚洲小视频在线观看| 欧美激情视频在线播放| 日韩亚洲国产精品| 亚洲精品免费网站| 国产精品一区久久| 美女国内精品自产拍在线播放| 欧美在线一二三四区| 亚洲激情av在线| 一区二区欧美日韩| 黄色一区二区在线| 亚洲精品中文字| 欧美色网在线| 玖玖国产精品视频| 欧美日韩一区二| 久久久久久一区二区三区| 男女精品视频| 久久久久久久网| 国产精品扒开腿做爽爽爽视频| 欧美成人69av| 国产日韩精品视频一区| 99视频一区二区| 欧美乱大交xxxxx| 91久久国产综合久久蜜月精品| 欧美一区二区三区在线| 美女视频黄a大片欧美| 国产精品99久久久久久久久| 亚洲男人天堂2024| 亚洲视频导航| 欧美精品www| 亚洲欧洲一区二区在线播放| 国产一区二区三区四区hd| 亚洲伊人久久综合| 欧美一级免费视频| 国产精品乱码一区二三区小蝌蚪| 最新国产乱人伦偷精品免费网站| 韩国一区二区三区在线观看| 91久久久亚洲精品| 亚洲精品久久久久久久久久久| 欧美专区一区二区三区| 久久久99精品免费观看不卡| 国产精品高清在线| 亚洲婷婷在线| 欧美在线观看视频一区二区三区| 欧美日韩国产精品| 亚洲香蕉视频| 久久深夜福利免费观看| 在线观看久久av| 欧美深夜影院| 久久精品水蜜桃av综合天堂| 亚洲一区二区三区影院| 亚洲黄色av一区| 欧美日韩专区| 亚洲欧美日韩爽爽影院| 欧美大片免费| 新狼窝色av性久久久久久| 精品成人乱色一区二区| 欧美人妖在线观看| 久久高清福利视频| 亚洲精品免费看| 国产精品美女久久久免费| 久久久久久伊人| 一区二区三区欧美日韩| 欧美国产精品一区| 久久国产精品久久久久久久久久| 亚洲精品国产视频| 国产亚洲一本大道中文在线| 欧美日韩极品在线观看一区| 久久九九久精品国产免费直播| 亚洲精品一线二线三线无人区| 久久久久久97三级| 久久精品免费观看| 性一交一乱一区二区洋洋av| 国产精品影音先锋| 亚洲视频综合| 亚洲黄色精品| 亚洲第一色在线| 99国产精品视频免费观看| 欧美aaa级| 快she精品国产999| 国产精品欧美日韩一区二区| 亚洲精品乱码久久久久久黑人 | 欧美黄色小视频| 欧美日韩亚洲另类| 亚洲第一搞黄网站| 久久久久一本一区二区青青蜜月| 亚洲国产精品精华液2区45| 亚洲女人天堂成人av在线| 欧美久久久久久| 亚洲精品小视频| 久久免费的精品国产v∧| 亚洲国产精品悠悠久久琪琪| 午夜精品久久久久久久久| 欧美日韩一区二区在线观看| 在线免费观看视频一区| 久久亚洲一区二区三区四区| 国产日韩精品在线观看| 一区二区三区高清视频在线观看| 欧美在线资源| 亚洲一区三区电影在线观看| 欧美精品一区二区视频| 亚洲黄色免费电影| 小嫩嫩精品导航| 一区二区久久久久| 欧美黄污视频| 久久精品国产一区二区三区| 国产精品高潮视频| 欧美一区二区三区在线观看视频| 在线中文字幕日韩| 国产精品国内视频| 宅男精品导航| 99国产精品久久久久久久成人热| 老司机精品视频网站| 伊人天天综合| 亚洲久久在线| 日韩一区二区高清| 欧美国产综合| 欧美日韩伦理在线| 欧美一区二区三区视频在线观看| 午夜欧美大片免费观看| 在线看无码的免费网站| 亚洲精品一区二区三区不| 国产精品区免费视频| 久久婷婷av| 欧美人交a欧美精品| 久久成人免费网| 欧美国产日本| 麻豆精品精品国产自在97香蕉| 欧美日韩高清在线观看| 欧美一级精品大片| 欧美高清视频一区二区三区在线观看| 一本色道**综合亚洲精品蜜桃冫| 日韩网站免费观看| 黄网站色欧美视频| 你懂的视频一区二区| 久久久久久久97| 一区二区高清在线| 久久久久久久国产| 小嫩嫩精品导航| 欧美午夜激情在线| 日韩午夜一区| 免费看av成人| 国产精品xnxxcom| 亚洲福利视频专区| 国户精品久久久久久久久久久不卡| 亚洲国产网站| 樱桃视频在线观看一区| 午夜日韩激情| 欧美伊人久久久久久久久影院| 欧美午夜理伦三级在线观看| 亚洲一区区二区| 欧美www视频在线观看| 亚洲一区二区在| 亚洲电影免费观看高清完整版在线观看 | 欧美区在线观看| 欧美专区在线| 国产精品毛片一区二区三区 | 亚洲福利国产| 久久gogo国模裸体人体| 老司机午夜精品| 亚洲国产二区| 国产欧美精品日韩| 亚洲私人影吧| 激情一区二区三区| 欧美国产精品v| 99精品国产在热久久下载| 亚洲午夜精品久久| 影院欧美亚洲| 欧美午夜精彩| 男女视频一区二区| 亚洲香蕉网站| 91久久久亚洲精品| 久久成人av少妇免费| 亚洲国内精品| 欧美成人在线免费观看| 久久久久高清| 美国十次成人| 亚洲国产成人在线| 亚洲激情欧美激情| 欧美日本在线一区| 欧美一区二区三区另类| 亚洲性视频网站| 亚洲美女在线国产| 亚洲激情另类| 99精品热6080yy久久| 一区二区三区www| 亚洲一区二区视频在线| 亚洲欧美日韩精品| 久久高清免费观看| 美女在线一区二区| 亚洲国产精品福利| 在线亚洲高清视频| 久久国产精品亚洲77777| 久久亚洲免费| 欧美日韩你懂的|