日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

本文從零到一,手把手實(shí)現(xiàn)一個(gè)內(nèi)存池。

比較出名的內(nèi)存池有jemalloc和tcmalloc,這兩個(gè)都是全局內(nèi)存池,比較推薦使用tcmalloc。

本專欄知識(shí)點(diǎn)是通過零聲教育的線上課學(xué)習(xí),進(jìn)行梳理總結(jié)寫下文章

為什么要用內(nèi)存池

為什么要用內(nèi)存池?首先,在7 * 24h的服務(wù)器中如果不使用內(nèi)存池,而使用malloc和free,那么就非常容易產(chǎn)生內(nèi)存碎片,早晚都會(huì)申請(qǐng)內(nèi)存失敗;并且在比較復(fù)雜的代碼或者繼承的屎山中,非常容易出現(xiàn)內(nèi)存泄漏導(dǎo)致mmo的問題。

為了解決這兩個(gè)問題,內(nèi)存池就應(yīng)運(yùn)而生了。內(nèi)存池預(yù)先分配一大塊內(nèi)存來做一個(gè)內(nèi)存池,業(yè)務(wù)中的內(nèi)存分配和釋放都由這個(gè)內(nèi)存池來管理,內(nèi)存池內(nèi)的內(nèi)存不足時(shí)其內(nèi)部會(huì)自己申請(qǐng)。所以內(nèi)存碎片的問題就交由內(nèi)存池的算法來優(yōu)化,而內(nèi)存泄漏的問題只需要遵守內(nèi)存池提供的api,就非常容易避免內(nèi)存泄漏了。

即使出現(xiàn)了內(nèi)存泄漏,排查的思路也很清晰。1.檢查是不是內(nèi)存池的問題;2.如果不是內(nèi)存池的問題,就檢查是不是第三方庫的內(nèi)存泄漏。

內(nèi)存池的使用場(chǎng)景

  1. 全局內(nèi)存池
  2. 一個(gè)連接一個(gè)內(nèi)存池(本文實(shí)現(xiàn)這個(gè)場(chǎng)景的內(nèi)存池)

設(shè)計(jì)一個(gè)內(nèi)存池

總體介紹

由于本文是一個(gè)連接一個(gè)內(nèi)存池,所以后續(xù)介紹和代碼都是以4k為分界線,大于4k的我們認(rèn)為是大塊內(nèi)存;小于4k的我們認(rèn)為是小塊內(nèi)存。并且注意這里的4k,并不是嚴(yán)格遵照4096,而是在描述上,用4k比較好描述。

在真正使用內(nèi)存之前,內(nèi)存池提前分配一定數(shù)量且大小相等的內(nèi)存塊以作備用,當(dāng)真正被用戶調(diào)用api分配內(nèi)存的時(shí)候,直接從內(nèi)存塊中獲取內(nèi)存(指小塊內(nèi)存),當(dāng)內(nèi)存塊不夠用了,再有內(nèi)存池取申請(qǐng)新的內(nèi)存塊。而如果是需要大塊內(nèi)存,則內(nèi)存池直接申請(qǐng)大塊內(nèi)存再返回給用戶。

內(nèi)存池:就是將這些提前申請(qǐng)的內(nèi)存塊組織管理起來的數(shù)據(jù)結(jié)構(gòu),內(nèi)存池實(shí)現(xiàn)原理主要分為分配,回收,擴(kuò)容三部分。

內(nèi)存池原理之小塊內(nèi)存:分配=> 內(nèi)存池預(yù)申請(qǐng)一塊4k的內(nèi)存塊,這里稱為block,即block=4k內(nèi)存塊。當(dāng)用戶向內(nèi)存池申請(qǐng)內(nèi)存size小于4k時(shí),內(nèi)存池從block的空間中劃分出去size空間,當(dāng)再有新申請(qǐng)時(shí),再劃分出去。擴(kuò)容=> 直到block中的剩余空間不足以分配size大小,那么此時(shí)內(nèi)存池會(huì)再次申請(qǐng)一塊block,再從新的block中劃分size空間給用戶。回收=> 每一次申請(qǐng)小內(nèi)存,都會(huì)在對(duì)應(yīng)的block中引用計(jì)數(shù)加1,每一次釋放小內(nèi)存時(shí),都會(huì)在block中引用計(jì)數(shù)減1,只有當(dāng)引用計(jì)數(shù)為零的時(shí)候,才會(huì)回收block使他重新成為空閑空間,以便重復(fù)利用空間。這樣,內(nèi)存池避免頻繁向內(nèi)核申請(qǐng)/釋放內(nèi)存,從而提高系統(tǒng)性能。

內(nèi)存池原理之大塊內(nèi)存:分配=> 因?yàn)榇髩K內(nèi)存是大于4k的,所以內(nèi)存池不預(yù)先申請(qǐng)內(nèi)存,也就是用戶申請(qǐng)的時(shí)候,內(nèi)存池再申請(qǐng)內(nèi)存,然后返回給用戶。擴(kuò)容=> 大塊內(nèi)存不存在擴(kuò)容。回收=> 對(duì)于大塊內(nèi)存來說,回收就直接free掉即可。

上面理論講完了,下面來介紹如何管理小塊內(nèi)存和大塊內(nèi)存。

 

小塊內(nèi)存的分配與管理

在創(chuàng)建內(nèi)存池的時(shí)候,會(huì)預(yù)先申請(qǐng)一塊4k的內(nèi)存,并且在起始處將pool的結(jié)構(gòu)體和node的結(jié)構(gòu)體放進(jìn)去,

在創(chuàng)建內(nèi)存池的時(shí)候,會(huì)預(yù)先申請(qǐng)一塊4k的內(nèi)存,并且在起始處將pool的結(jié)構(gòu)體和node的結(jié)構(gòu)體放進(jìn)去,從last開始一直到end都是空閑內(nèi)存,<last , end >中間的區(qū)域就用來存儲(chǔ)小塊內(nèi)存。每一次mp_malloc,就將last指針后移,直到 e n d − l a s t < s i z e end - last < sizeend−last<size 時(shí),進(jìn)行擴(kuò)容,將新block的last后移即可。

初始狀態(tài)

分配內(nèi)存

擴(kuò)容

大塊內(nèi)存的分配與管理

對(duì)于大塊內(nèi)存,前面已經(jīng)說了,用戶申請(qǐng)的時(shí)候,內(nèi)存池才申請(qǐng)

  • 申請(qǐng)一塊大內(nèi)存

再申請(qǐng)一塊大內(nèi)存

內(nèi)存池代碼實(shí)現(xiàn)

向外提供的api

  • mp_create_pool:創(chuàng)建一個(gè)線程池,其核心是創(chuàng)建struct mp_pool_s這個(gè)結(jié)構(gòu)體,并申請(qǐng)4k內(nèi)存,將各個(gè)指針指向上文初始狀態(tài)的圖一樣。
  • mp_destroy_pool:銷毀內(nèi)存池,遍歷小塊結(jié)構(gòu)體和大塊結(jié)構(gòu)體,進(jìn)行free釋放內(nèi)存
  • mp_malloc:提供給用戶申請(qǐng)內(nèi)存的api
  • mp_calloc:通過mp_malloc申請(qǐng)內(nèi)存后置零,相當(dāng)于calloc
  • mp_free:釋放由mp_malloc返回的內(nèi)存
  • mp_reset_pool:將block的last置為初始狀態(tài),銷毀所有大塊內(nèi)存
  • monitor_mp_poll:監(jiān)控內(nèi)存池狀態(tài)
struct mp_pool_s *mp_create_pool(size_t size);

void mp_destroy_pool(struct mp_pool_s *pool);

void *mp_malloc(struct mp_pool_s *pool, size_t size);

void *mp_calloc(struct mp_pool_s *pool, size_t size);

void mp_free(struct mp_pool_s *pool, void *p);

void mp_reset_pool(struct mp_pool_s *pool);

void monitor_mp_poll(struct mp_pool_s *pool, char *tk);

相關(guān)結(jié)構(gòu)體的定義

mp_pool_s 就是整個(gè)內(nèi)存池的管理結(jié)構(gòu),我們做的內(nèi)存池是一個(gè)連接一個(gè)內(nèi)存池,所以對(duì)于整個(gè)程序而言,內(nèi)存池對(duì)象是有很多個(gè)的。

可能讀者會(huì)有疑問,有了head,為什么還有current,是因?yàn)槿绻粋€(gè)block剩余空間小于size超過一定次數(shù)后,將current指向下一個(gè)block,這樣就加快內(nèi)存分配效率,減少遍歷次數(shù)。

//每4k一block結(jié)點(diǎn)
struct mp_node_s {
    unsigned char *end;//塊的結(jié)尾
    unsigned char *last;//使用到哪了
    struct mp_node_s *next;//鏈表
    int quote;//引用計(jì)數(shù)
    int failed;//失效次數(shù)
};

struct mp_large_s {
    struct mp_large_s *next;//鏈表
    int size;//alloc的大小
    void *alloc;//大塊內(nèi)存的起始地址
};

struct mp_pool_s {
    struct mp_large_s *large;
    struct mp_node_s *head;
    struct mp_node_s *current;
};

內(nèi)存對(duì)齊

訪問速度是內(nèi)存對(duì)齊的原因之一,另外一個(gè)原因是某些平臺(tái)(arm)不支持未內(nèi)存對(duì)齊的訪問

在4k里面劃分內(nèi)存,那么必然有很多地方是不對(duì)齊的,所以這里提供兩個(gè)內(nèi)存對(duì)齊的函數(shù)。那么為什么要內(nèi)存對(duì)齊呢?其一:提高訪問速度;其二:某些平臺(tái)arm不支持未對(duì)其的內(nèi)存訪問,會(huì)出錯(cuò)。

#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))

創(chuàng)建與銷毀內(nèi)存池

創(chuàng)建一個(gè)線程池,其核心是創(chuàng)建struct mp_pool_s這個(gè)結(jié)構(gòu)體,并申請(qǐng)4k內(nèi)存,將各個(gè)指針指向上文初始狀態(tài)的圖一樣。
銷毀內(nèi)存池,遍歷小塊結(jié)構(gòu)體和大塊結(jié)構(gòu)體,進(jìn)行free釋放內(nèi)存。

//創(chuàng)建內(nèi)存池
struct mp_pool_s *mp_create_pool(size_t size) {
    struct mp_pool_s *pool;
    if (size < PAGE_SIZE || size % PAGE_SIZE != 0) {
        size = PAGE_SIZE;
    }
    //分配4k以上不用malloc,用posix_memalign
    /*
        int posix_memalign (void **memptr, size_t alignment, size_t size);
     */

    int ret = posix_memalign((void **) &pool, MP_ALIGNMENT, size); //4K + mp_pool_s
    if (ret) {
        return NULL;
    }
    pool->large = NULL;
    pool->current = pool->head = (unsigned char *) pool + sizeof(struct mp_pool_s);
    pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    pool->head->end = (unsigned char *) pool + PAGE_SIZE;
    pool->head->failed = 0;

    return pool;
}

//銷毀內(nèi)存池
void mp_destroy_pool(struct mp_pool_s *pool) {
    struct mp_large_s *large;
    for (large = pool->large; large; large = large->next) {
        if (large->alloc) {
            free(large->alloc);
        }
    }

    struct mp_node_s *cur, *next;
    cur = pool->head->next;

    while (cur) {
        next = cur->next;
        free(cur);
        cur = next;
    }
    free(pool);
}

提供給用戶的內(nèi)存申請(qǐng)api

申請(qǐng)的內(nèi)存以size做區(qū)分,如果大于4k就分配大塊內(nèi)存,小于4k就去block里面劃分。

 

//分配內(nèi)存
void%20*mp_malloc(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20if%20(size%20<=%200)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20if%20(size%20>%20PAGE_SIZE%20-%20sizeof(struct%20mp_node_s))%20{
%20%20%20%20%20%20%20%20//large
%20%20%20%20%20%20%20%20return%20mp_malloc_large(pool,%20size);
%20%20%20%20}
%20%20%20%20else%20{
%20%20%20%20%20%20%20%20//small
%20%20%20%20%20%20%20%20unsigned%20char%20*mem_addr%20=%20NULL;
%20%20%20%20%20%20%20%20struct%20mp_node_s%20*cur%20=%20NULL;
%20%20%20%20%20%20%20%20cur%20=%20pool->current;
%20%20%20%20%20%20%20%20while%20(cur)%20{
%20%20%20%20%20%20%20%20%20%20%20%20mem_addr%20=%20mp_align_ptr(cur->last,%20MP_ALIGNMENT);
%20%20%20%20%20%20%20%20%20%20%20%20if%20(cur->end%20-%20mem_addr%20>=%20size)%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->quote++;//引用+1
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->last%20=%20mem_addr%20+%20size;
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20mem_addr;
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20else%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur%20=%20cur->next;
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20return%20mp_malloc_block(pool,%20size);//%20open%20new%20space
%20%20%20%20}
}
void%20*mp_calloc(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20void%20*mem_addr%20=%20mp_malloc(pool,%20size);
%20%20%20%20if%20(mem_addr)%20{
%20%20%20%20%20%20%20%20memset(mem_addr,%200,%20size);
%20%20%20%20}
%20%20%20%20return%20mem_addr;
}
小塊內(nèi)存block擴(kuò)容

 

所有的block都%20e%20n%20d%20−%20l%20a%20s%20t%20<%20s%20i%20z%20e%20end%20-%20last%20<%20sizeend−last<size%20時(shí),進(jìn)行擴(kuò)容,將新block的last后移即可。

 

//new%20block%204k
void%20*mp_malloc_block(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20unsigned%20char%20*block;
%20%20%20%20int%20ret%20=%20posix_memalign((void%20**)%20&block,%20MP_ALIGNMENT,%20PAGE_SIZE);%20//4K
%20%20%20%20if%20(ret)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20struct%20mp_node_s%20*new_node%20=%20(struct%20mp_node_s%20*)%20block;
%20%20%20%20new_node->end%20=%20block%20+%20PAGE_SIZE;
%20%20%20%20new_node->next%20=%20NULL;

%20%20%20%20unsigned%20char%20*ret_addr%20=%20mp_align_ptr(block%20+%20sizeof(struct%20mp_node_s),%20MP_ALIGNMENT);

%20%20%20%20new_node->last%20=%20ret_addr%20+%20size;
%20%20%20%20new_node->quote++;

%20%20%20%20struct%20mp_node_s%20*current%20=%20pool->current;
%20%20%20%20struct%20mp_node_s%20*cur%20=%20NULL;

%20%20%20%20for%20(cur%20=%20current;%20cur->next;%20cur%20=%20cur->next)%20{
%20%20%20%20%20%20%20%20if%20(cur->failed++%20>%204)%20{
%20%20%20%20%20%20%20%20%20%20%20%20current%20=%20cur->next;
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20//now%20cur%20=%20last%20node
%20%20%20%20cur->next%20=%20new_node;
%20%20%20%20pool->current%20=%20current;
%20%20%20%20return%20ret_addr;
}
分配大塊內(nèi)存

 

//size>4k
void%20*mp_malloc_large(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20unsigned%20char%20*big_addr;
%20%20%20%20int%20ret%20=%20posix_memalign((void%20**)%20&big_addr,%20MP_ALIGNMENT,%20size);%20//size
%20%20%20%20if%20(ret)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}

%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20//released%20struct%20large%20resume
%20%20%20%20int%20n%20=%200;
%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{
%20%20%20%20%20%20%20%20if%20(large->alloc%20==%20NULL)%20{
%20%20%20%20%20%20%20%20%20%20%20%20large->size%20=%20size;
%20%20%20%20%20%20%20%20%20%20%20%20large->alloc%20=%20big_addr;
%20%20%20%20%20%20%20%20%20%20%20%20return%20big_addr;
%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20if%20(n++%20>%203)%20{
%20%20%20%20%20%20%20%20%20%20%20%20break;//%20為了避免過多的遍歷,限制次數(shù)
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20large%20=%20mp_malloc(pool,%20sizeof(struct%20mp_large_s));
%20%20%20%20if%20(large%20==%20NULL)%20{
%20%20%20%20%20%20%20%20free(big_addr);
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20large->size%20=%20size;
%20%20%20%20large->alloc%20=%20big_addr;
%20%20%20%20large->next%20=%20pool->large;
%20%20%20%20pool->large%20=%20large;
%20%20%20%20return%20big_addr;
}

釋放內(nèi)存

如果是大塊內(nèi)存,找到之后直接釋放;如果是小塊內(nèi)存,將引用計(jì)數(shù)減1,如果引用計(jì)數(shù)為0則重置last。

 

//釋放內(nèi)存
void%20mp_free(struct%20mp_pool_s%20*pool,%20void%20*p)%20{
%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{//大塊
%20%20%20%20%20%20%20%20if%20(p%20==%20large->alloc)%20{
%20%20%20%20%20%20%20%20%20%20%20%20free(large->alloc);
%20%20%20%20%20%20%20%20%20%20%20%20large->size%20=%200;
%20%20%20%20%20%20%20%20%20%20%20%20large->alloc%20=%20NULL;
%20%20%20%20%20%20%20%20%20%20%20%20return;
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20//小塊%20引用-1
%20%20%20%20struct%20mp_node_s%20*cur%20=%20NULL;
%20%20%20%20for%20(cur%20=%20pool->head;%20cur;%20cur%20=%20cur->next)%20{
//%20%20%20%20%20%20%20%20printf("cur:%p%20%20%20p:%p%20%20%20end:%pn",%20(unsigned%20char%20*)%20cur,%20(unsigned%20char%20*)%20p,%20(unsigned%20char%20*)%20cur->end);
%20%20%20%20%20%20%20%20if%20((unsigned%20char%20*)%20cur%20<=%20(unsigned%20char%20*)%20p%20&&%20(unsigned%20char%20*)%20p%20<=%20(unsigned%20char%20*)%20cur->end)%20{
%20%20%20%20%20%20%20%20%20%20%20%20cur->quote--;
%20%20%20%20%20%20%20%20%20%20%20%20if%20(cur->quote%20==%200)%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cur%20==%20pool->head)%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pool->head->last%20=%20(unsigned%20char%20*)%20pool%20+%20sizeof(struct%20mp_pool_s)%20+%20sizeof(struct%20mp_node_s);
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->last%20=%20(unsigned%20char%20*)%20cur%20+%20sizeof(struct%20mp_node_s);
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->failed%20=%200;
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pool->current%20=%20pool->head;
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20return;
%20%20%20%20%20%20%20%20}
%20%20%20%20}
}
內(nèi)存池測(cè)試

 

//
//%20Created%20by%2068725%20on%202022/7/26.
//
#include%20<stdlib.h>
#include%20<stdio.h>
#include%20<string.h>

#define%20PAGE_SIZE%204096
#define%20MP_ALIGNMENT%2016
#define%20mp_align(n,%20alignment)%20(((n)+(alignment-1))%20&%20~(alignment-1))
#define%20mp_align_ptr(p,%20alignment)%20(void%20*)((((size_t)p)+(alignment-1))%20&%20~(alignment-1))

//每4k一block結(jié)點(diǎn)
struct%20mp_node_s%20{
%20%20%20%20unsigned%20char%20*end;//塊的結(jié)尾
%20%20%20%20unsigned%20char%20*last;//使用到哪了
%20%20%20%20struct%20mp_node_s%20*next;//鏈表
%20%20%20%20int%20quote;//引用計(jì)數(shù)
%20%20%20%20int%20failed;//失效次數(shù)
};

struct%20mp_large_s%20{
%20%20%20%20struct%20mp_large_s%20*next;//鏈表
%20%20%20%20int%20size;//alloc的大小
%20%20%20%20void%20*alloc;//大塊內(nèi)存的起始地址
};

struct%20mp_pool_s%20{
%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20struct%20mp_node_s%20*head;
%20%20%20%20struct%20mp_node_s%20*current;
};

struct%20mp_pool_s%20*mp_create_pool(size_t%20size);

void%20mp_destroy_pool(struct%20mp_pool_s%20*pool);

void%20*mp_malloc(struct%20mp_pool_s%20*pool,%20size_t%20size);

void%20*mp_calloc(struct%20mp_pool_s%20*pool,%20size_t%20size);

void%20mp_free(struct%20mp_pool_s%20*pool,%20void%20*p);

void%20mp_reset_pool(struct%20mp_pool_s%20*pool);

void%20monitor_mp_poll(struct%20mp_pool_s%20*pool,%20char%20*tk);


void%20mp_reset_pool(struct%20mp_pool_s%20*pool)%20{
%20%20%20%20struct%20mp_node_s%20*cur;
%20%20%20%20struct%20mp_large_s%20*large;

%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{
%20%20%20%20%20%20%20%20if%20(large->alloc)%20{
%20%20%20%20%20%20%20%20%20%20%20%20free(large->alloc);
%20%20%20%20%20%20%20%20}
%20%20%20%20}

%20%20%20%20pool->large%20=%20NULL;
%20%20%20%20pool->current%20=%20pool->head;
%20%20%20%20for%20(cur%20=%20pool->head;%20cur;%20cur%20=%20cur->next)%20{
%20%20%20%20%20%20%20%20cur->last%20=%20(unsigned%20char%20*)%20cur%20+%20sizeof(struct%20mp_node_s);
%20%20%20%20%20%20%20%20cur->failed%20=%200;
%20%20%20%20%20%20%20%20cur->quote%20=%200;
%20%20%20%20}
}

//創(chuàng)建內(nèi)存池
struct%20mp_pool_s%20*mp_create_pool(size_t%20size)%20{
%20%20%20%20struct%20mp_pool_s%20*pool;
%20%20%20%20if%20(size%20<%20PAGE_SIZE%20||%20size%20%%20PAGE_SIZE%20!=%200)%20{
%20%20%20%20%20%20%20%20size%20=%20PAGE_SIZE;
%20%20%20%20}
%20%20%20%20//分配4k以上不用malloc,用posix_memalign
%20%20%20%20/*
%20%20%20%20%20%20%20%20int%20posix_memalign%20(void%20**memptr,%20size_t%20alignment,%20size_t%20size);
%20%20%20%20%20*/

%20%20%20%20int%20ret%20=%20posix_memalign((void%20**)%20&pool,%20MP_ALIGNMENT,%20size);%20//4K%20+%20mp_pool_s
%20%20%20%20if%20(ret)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20pool->large%20=%20NULL;
%20%20%20%20pool->current%20=%20pool->head%20=%20(unsigned%20char%20*)%20pool%20+%20sizeof(struct%20mp_pool_s);
%20%20%20%20pool->head->last%20=%20(unsigned%20char%20*)%20pool%20+%20sizeof(struct%20mp_pool_s)%20+%20sizeof(struct%20mp_node_s);
%20%20%20%20pool->head->end%20=%20(unsigned%20char%20*)%20pool%20+%20PAGE_SIZE;
%20%20%20%20pool->head->failed%20=%200;

%20%20%20%20return%20pool;
}

//銷毀內(nèi)存池
void%20mp_destroy_pool(struct%20mp_pool_s%20*pool)%20{
%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{
%20%20%20%20%20%20%20%20if%20(large->alloc)%20{
%20%20%20%20%20%20%20%20%20%20%20%20free(large->alloc);
%20%20%20%20%20%20%20%20}
%20%20%20%20}

%20%20%20%20struct%20mp_node_s%20*cur,%20*next;
%20%20%20%20cur%20=%20pool->head->next;

%20%20%20%20while%20(cur)%20{
%20%20%20%20%20%20%20%20next%20=%20cur->next;
%20%20%20%20%20%20%20%20free(cur);
%20%20%20%20%20%20%20%20cur%20=%20next;
%20%20%20%20}
%20%20%20%20free(pool);
}

//size>4k
void%20*mp_malloc_large(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20unsigned%20char%20*big_addr;
%20%20%20%20int%20ret%20=%20posix_memalign((void%20**)%20&big_addr,%20MP_ALIGNMENT,%20size);%20//size
%20%20%20%20if%20(ret)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}

%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20//released%20struct%20large%20resume
%20%20%20%20int%20n%20=%200;
%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{
%20%20%20%20%20%20%20%20if%20(large->alloc%20==%20NULL)%20{
%20%20%20%20%20%20%20%20%20%20%20%20large->size%20=%20size;
%20%20%20%20%20%20%20%20%20%20%20%20large->alloc%20=%20big_addr;
%20%20%20%20%20%20%20%20%20%20%20%20return%20big_addr;
%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20if%20(n++%20>%203)%20{
%20%20%20%20%20%20%20%20%20%20%20%20break;//%20為了避免過多的遍歷,限制次數(shù)
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20large%20=%20mp_malloc(pool,%20sizeof(struct%20mp_large_s));
%20%20%20%20if%20(large%20==%20NULL)%20{
%20%20%20%20%20%20%20%20free(big_addr);
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20large->size%20=%20size;
%20%20%20%20large->alloc%20=%20big_addr;
%20%20%20%20large->next%20=%20pool->large;
%20%20%20%20pool->large%20=%20large;
%20%20%20%20return%20big_addr;
}

//new%20block%204k
void%20*mp_malloc_block(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20unsigned%20char%20*block;
%20%20%20%20int%20ret%20=%20posix_memalign((void%20**)%20&block,%20MP_ALIGNMENT,%20PAGE_SIZE);%20//4K
%20%20%20%20if%20(ret)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20struct%20mp_node_s%20*new_node%20=%20(struct%20mp_node_s%20*)%20block;
%20%20%20%20new_node->end%20=%20block%20+%20PAGE_SIZE;
%20%20%20%20new_node->next%20=%20NULL;

%20%20%20%20unsigned%20char%20*ret_addr%20=%20mp_align_ptr(block%20+%20sizeof(struct%20mp_node_s),%20MP_ALIGNMENT);

%20%20%20%20new_node->last%20=%20ret_addr%20+%20size;
%20%20%20%20new_node->quote++;

%20%20%20%20struct%20mp_node_s%20*current%20=%20pool->current;
%20%20%20%20struct%20mp_node_s%20*cur%20=%20NULL;

%20%20%20%20for%20(cur%20=%20current;%20cur->next;%20cur%20=%20cur->next)%20{
%20%20%20%20%20%20%20%20if%20(cur->failed++%20>%204)%20{
%20%20%20%20%20%20%20%20%20%20%20%20current%20=%20cur->next;
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20//now%20cur%20=%20last%20node
%20%20%20%20cur->next%20=%20new_node;
%20%20%20%20pool->current%20=%20current;
%20%20%20%20return%20ret_addr;
}

//分配內(nèi)存
void%20*mp_malloc(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20if%20(size%20<=%200)%20{
%20%20%20%20%20%20%20%20return%20NULL;
%20%20%20%20}
%20%20%20%20if%20(size%20>%20PAGE_SIZE%20-%20sizeof(struct%20mp_node_s))%20{
%20%20%20%20%20%20%20%20//large
%20%20%20%20%20%20%20%20return%20mp_malloc_large(pool,%20size);
%20%20%20%20}
%20%20%20%20else%20{
%20%20%20%20%20%20%20%20//small
%20%20%20%20%20%20%20%20unsigned%20char%20*mem_addr%20=%20NULL;
%20%20%20%20%20%20%20%20struct%20mp_node_s%20*cur%20=%20NULL;
%20%20%20%20%20%20%20%20cur%20=%20pool->current;
%20%20%20%20%20%20%20%20while%20(cur)%20{
%20%20%20%20%20%20%20%20%20%20%20%20mem_addr%20=%20mp_align_ptr(cur->last,%20MP_ALIGNMENT);
%20%20%20%20%20%20%20%20%20%20%20%20if%20(cur->end%20-%20mem_addr%20>=%20size)%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->quote++;//引用+1
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->last%20=%20mem_addr%20+%20size;
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20mem_addr;
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20else%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur%20=%20cur->next;
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20return%20mp_malloc_block(pool,%20size);//%20open%20new%20space
%20%20%20%20}
}

void%20*mp_calloc(struct%20mp_pool_s%20*pool,%20size_t%20size)%20{
%20%20%20%20void%20*mem_addr%20=%20mp_malloc(pool,%20size);
%20%20%20%20if%20(mem_addr)%20{
%20%20%20%20%20%20%20%20memset(mem_addr,%200,%20size);
%20%20%20%20}
%20%20%20%20return%20mem_addr;
}

//釋放內(nèi)存
void%20mp_free(struct%20mp_pool_s%20*pool,%20void%20*p)%20{
%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{//大塊
%20%20%20%20%20%20%20%20if%20(p%20==%20large->alloc)%20{
%20%20%20%20%20%20%20%20%20%20%20%20free(large->alloc);
%20%20%20%20%20%20%20%20%20%20%20%20large->size%20=%200;
%20%20%20%20%20%20%20%20%20%20%20%20large->alloc%20=%20NULL;
%20%20%20%20%20%20%20%20%20%20%20%20return;
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20//小塊%20引用-1
%20%20%20%20struct%20mp_node_s%20*cur%20=%20NULL;
%20%20%20%20for%20(cur%20=%20pool->head;%20cur;%20cur%20=%20cur->next)%20{
//%20%20%20%20%20%20%20%20printf("cur:%p%20%20%20p:%p%20%20%20end:%pn",%20(unsigned%20char%20*)%20cur,%20(unsigned%20char%20*)%20p,%20(unsigned%20char%20*)%20cur->end);
%20%20%20%20%20%20%20%20if%20((unsigned%20char%20*)%20cur%20<=%20(unsigned%20char%20*)%20p%20&&%20(unsigned%20char%20*)%20p%20<=%20(unsigned%20char%20*)%20cur->end)%20{
%20%20%20%20%20%20%20%20%20%20%20%20cur->quote--;
%20%20%20%20%20%20%20%20%20%20%20%20if%20(cur->quote%20==%200)%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cur%20==%20pool->head)%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pool->head->last%20=%20(unsigned%20char%20*)%20pool%20+%20sizeof(struct%20mp_pool_s)%20+%20sizeof(struct%20mp_node_s);
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->last%20=%20(unsigned%20char%20*)%20cur%20+%20sizeof(struct%20mp_node_s);
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cur->failed%20=%200;
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pool->current%20=%20pool->head;
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20%20%20%20%20return;
%20%20%20%20%20%20%20%20}
%20%20%20%20}
}

void%20monitor_mp_poll(struct%20mp_pool_s%20*pool,%20char%20*tk)%20{
%20%20%20%20printf("rnrn------start%20monitor%20poll------%srnrn",%20tk);
%20%20%20%20struct%20mp_node_s%20*head%20=%20NULL;
%20%20%20%20int%20i%20=%200;
%20%20%20%20for%20(head%20=%20pool->head;%20head;%20head%20=%20head->next)%20{
%20%20%20%20%20%20%20%20i++;
%20%20%20%20%20%20%20%20if%20(pool->current%20==%20head)%20{
%20%20%20%20%20%20%20%20%20%20%20%20printf("current==>第%d塊n",%20i);
%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20if%20(i%20==%201)%20{
%20%20%20%20%20%20%20%20%20%20%20%20printf("第%02d塊small%20block%20%20已使用:%4ld%20%20剩余空間:%4ld%20%20引用:%4d%20%20failed:%4dn",%20i,
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(unsigned%20char%20*)%20head->last%20-%20(unsigned%20char%20*)%20pool,
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20head->end%20-%20head->last,%20head->quote,%20head->failed);
%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20else%20{
%20%20%20%20%20%20%20%20%20%20%20%20printf("第%02d塊small%20block%20%20已使用:%4ld%20%20剩余空間:%4ld%20%20引用:%4d%20%20failed:%4dn",%20i,
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(unsigned%20char%20*)%20head->last%20-%20(unsigned%20char%20*)%20head,
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20head->end%20-%20head->last,%20head->quote,%20head->failed);
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20struct%20mp_large_s%20*large;
%20%20%20%20i%20=%200;
%20%20%20%20for%20(large%20=%20pool->large;%20large;%20large%20=%20large->next)%20{
%20%20%20%20%20%20%20%20i++;
%20%20%20%20%20%20%20%20if%20(large->alloc%20!=%20NULL)%20{
%20%20%20%20%20%20%20%20%20%20%20%20printf("第%d塊large%20block%20%20size=%dn",%20i,%20large->size);
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20printf("rnrn------stop%20monitor%20poll------rnrn");
}



int%20main()%20{
%20%20%20%20struct%20mp_pool_s%20*p%20=%20mp_create_pool(PAGE_SIZE);
%20%20%20%20monitor_mp_poll(p,%20"create%20memory%20pool");
#if%200
%20%20%20%20printf("mp_align(5,%20%d):%20%d,%20mp_align(17,%20%d):%20%dn",%20MP_ALIGNMENT,%20mp_align(5,%20MP_ALIGNMENT),%20MP_ALIGNMENT,
%20%20%20%20%20%20%20%20%20%20%20mp_align(17,%20MP_ALIGNMENT));
%20%20%20%20printf("mp_align_ptr(p->current,%20%d):%20%p,%20p->current:%20%pn",%20MP_ALIGNMENT,%20mp_align_ptr(p->current,%20MP_ALIGNMENT),
%20%20%20%20%20%20%20%20%20%20%20p->current);
#endif
%20%20%20%20void%20*mp[30];
%20%20%20%20int%20i;
%20%20%20%20for%20(i%20=%200;%20i%20<%2030;%20i++)%20{
%20%20%20%20%20%20%20%20mp[i]%20=%20mp_malloc(p,%20512);
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"申請(qǐng)512字節(jié)30個(gè)");

%20%20%20%20for%20(i%20=%200;%20i%20<%2030;%20i++)%20{
%20%20%20%20%20%20%20%20mp_free(p,%20mp[i]);
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"銷毀512字節(jié)30個(gè)");

%20%20%20%20int%20j;
%20%20%20%20for%20(i%20=%200;%20i%20<%2050;%20i++)%20{
%20%20%20%20%20%20%20%20char%20*pp%20=%20mp_calloc(p,%2032);
%20%20%20%20%20%20%20%20for%20(j%20=%200;%20j%20<%2032;%20j++)%20{
%20%20%20%20%20%20%20%20%20%20%20%20if%20(pp[j])%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20printf("calloc%20wrongn");
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exit(-1);
%20%20%20%20%20%20%20%20%20%20%20%20}
%20%20%20%20%20%20%20%20}
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"申請(qǐng)32字節(jié)50個(gè)");

%20%20%20%20for%20(i%20=%200;%20i%20<%2050;%20i++)%20{
%20%20%20%20%20%20%20%20char%20*pp%20=%20mp_malloc(p,%203);
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"申請(qǐng)3字節(jié)50個(gè)");


%20%20%20%20void%20*pp[10];
%20%20%20%20for%20(i%20=%200;%20i%20<%2010;%20i++)%20{
%20%20%20%20%20%20%20%20pp[i]%20=%20mp_malloc(p,%205120);
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"申請(qǐng)大內(nèi)存5120字節(jié)10個(gè)");

%20%20%20%20for%20(i%20=%200;%20i%20<%2010;%20i++)%20{
%20%20%20%20%20%20%20%20mp_free(p,%20pp[i]);
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"銷毀大內(nèi)存5120字節(jié)10個(gè)");

%20%20%20%20mp_reset_pool(p);
%20%20%20%20monitor_mp_poll(p,%20"reset%20pool");

%20%20%20%20for%20(i%20=%200;%20i%20<%20100;%20i++)%20{
%20%20%20%20%20%20%20%20void%20*s%20=%20mp_malloc(p,%20256);
%20%20%20%20}
%20%20%20%20monitor_mp_poll(p,%20"申請(qǐng)256字節(jié)100個(gè)");

%20%20%20%20mp_destroy_pool(p);
%20%20%20%20return%200;
}

Nginx內(nèi)存池對(duì)比分析

相關(guān)結(jié)構(gòu)體定義對(duì)比

創(chuàng)建內(nèi)存池對(duì)比

內(nèi)存申請(qǐng)對(duì)比

 

分享到:
標(biāo)簽:內(nèi)存
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定