為什么要用內(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的問(wèn)題。
為了解決這兩個(gè)問(wèn)題,內(nèi)存池就應(yīng)運(yùn)而生了。內(nèi)存池預(yù)先分配一大塊內(nèi)存來(lái)做一個(gè)內(nèi)存池,業(yè)務(wù)中的內(nèi)存分配和釋放都由這個(gè)內(nèi)存池來(lái)管理,內(nèi)存池內(nèi)的內(nèi)存不足時(shí)其內(nèi)部會(huì)自己申請(qǐng)。所以內(nèi)存碎片的問(wèn)題就交由內(nèi)存池的算法來(lái)優(yōu)化,而內(nèi)存泄漏的問(wèn)題只需要遵守內(nèi)存池提供的api,就非常容易避免內(nèi)存泄漏了。
即使出現(xiàn)了內(nèi)存泄漏,排查的思路也很清晰。1.檢查是不是內(nèi)存池的問(wèn)題;2.如果不是內(nèi)存池的問(wèn)題,就檢查是不是第三方庫(kù)的內(nèi)存泄漏。
內(nèi)存池的使用場(chǎng)景
- 全局內(nèi)存池
- 一個(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)存塊組織管理起來(lá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,再?gòu)男碌腷lock中劃分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)存來(lái)說(shuō),回收就直接free掉即可。
上面理論講完了,下面來(lái)介紹如何管理小塊內(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)去,從last開(kāi)始一直到end都是空閑內(nèi)存,中間的區(qū)域就用來(lái)存儲(chǔ)小塊內(nèi)存。每一次mp_malloc,就將last指針后移,直到 e n d ? l a s t < s i z e end - last < size end?last
初始狀態(tài)
分配內(nèi)存
擴(kuò)容
大塊內(nèi)存的分配與管理
對(duì)于大塊內(nèi)存,前面已經(jīng)說(shuō)了,用戶申請(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:通過(guò)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ì)有疑問(wèn),有了head,為什么還有current,是因?yàn)槿绻粋€(gè)block剩余空間小于size超過(guò)一定次數(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ì)齊
訪問(wèn)速度是內(nèi)存對(duì)齊的原因之一,另外一個(gè)原因是某些平臺(tái)(arm)不支持未內(nèi)存對(duì)齊的訪問(wèn)
在4k里面劃分內(nèi)存,那么必然有很多地方是不對(duì)齊的,所以這里提供兩個(gè)內(nèi)存對(duì)齊的函數(shù)。那么為什么要內(nèi)存對(duì)齊呢?其一:提高訪問(wèn)速度;其二:某些平臺(tái)arm不支持未對(duì)其的內(nèi)存訪問(wèn),會(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 *mp_malloc(struct mp_pool_s *pool, size_t size) {
if (size <= 0) {
return NULL;
}
if (size > PAGE_SIZE - sizeof(struct mp_node_s)) {
//large
return mp_malloc_large(pool, size);
}
else {
//small
unsigned char *mem_addr = NULL;
struct mp_node_s *cur = NULL;
cur = pool- >current;
while (cur) {
mem_addr = mp_align_ptr(cur- >last, MP_ALIGNMENT);
if (cur- >end - mem_addr >= size) {
cur- >quote++;//引用+1
cur- >last = mem_addr + size;
return mem_addr;
}
else {
cur = cur- >next;
}
}
return mp_malloc_block(pool, size);// open new space
}
}
void *mp_calloc(struct mp_pool_s *pool, size_t size) {
void *mem_addr = mp_malloc(pool, size);
if (mem_addr) {
memset(mem_addr, 0, size);
}
return mem_addr;
}
小塊內(nèi)存block擴(kuò)容
所有的block都 e n d ? l a s t < s i z e end - last < size end?last
//new block 4k
void *mp_malloc_block(struct mp_pool_s *pool, size_t size) {
unsigned char *block;
int ret = posix_memalign((void **) &block, MP_ALIGNMENT, PAGE_SIZE); //4K
if (ret) {
return NULL;
}
struct mp_node_s *new_node = (struct mp_node_s *) block;
new_node- >end = block + PAGE_SIZE;
new_node- >next = NULL;
unsigned char *ret_addr = mp_align_ptr(block + sizeof(struct mp_node_s), MP_ALIGNMENT);
new_node- >last = ret_addr + size;
new_node- >quote++;
struct mp_node_s *current = pool- >current;
struct mp_node_s *cur = NULL;
for (cur = current; cur- >next; cur = cur- >next) {
if (cur- >failed++ > 4) {
current = cur- >next;
}
}
//now cur = last node
cur- >next = new_node;
pool- >current = current;
return ret_addr;
}
分配大塊內(nèi)存
//size >4k
void *mp_malloc_large(struct mp_pool_s *pool, size_t size) {
unsigned char *big_addr;
int ret = posix_memalign((void **) &big_addr, MP_ALIGNMENT, size); //size
if (ret) {
return NULL;
}
struct mp_large_s *large;
//released struct large resume
int n = 0;
for (large = pool- >large; large; large = large- >next) {
if (large- >alloc == NULL) {
large- >size = size;
large- >alloc = big_addr;
return big_addr;
}
if (n++ > 3) {
break;// 為了避免過(guò)多的遍歷,限制次數(shù)
}
}
large = mp_malloc(pool, sizeof(struct mp_large_s));
if (large == NULL) {
free(big_addr);
return NULL;
}
large- >size = size;
large- >alloc = big_addr;
large- >next = pool- >large;
pool- >large = large;
return big_addr;
}
釋放內(nèi)存
如果是大塊內(nèi)存,找到之后直接釋放;如果是小塊內(nèi)存,將引用計(jì)數(shù)減1,如果引用計(jì)數(shù)為0則重置last。
//釋放內(nèi)存
void mp_free(struct mp_pool_s *pool, void *p) {
struct mp_large_s *large;
for (large = pool- >large; large; large = large- >next) {//大塊
if (p == large- >alloc) {
free(large- >alloc);
large- >size = 0;
large- >alloc = NULL;
return;
}
}
//小塊 引用-1
struct mp_node_s *cur = NULL;
for (cur = pool- >head; cur; cur = cur- >next) {
// printf("cur:%p p:%p end:%pn", (unsigned char *) cur, (unsigned char *) p, (unsigned char *) cur- >end);
if ((unsigned char *) cur <= (unsigned char *) p && (unsigned char *) p <= (unsigned char *) cur- >end) {
cur- >quote--;
if (cur- >quote == 0) {
if (cur == pool- >head) {
pool- >head- >last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
}
else {
cur- >last = (unsigned char *) cur + sizeof(struct mp_node_s);
}
cur- >failed = 0;
pool- >current = pool- >head;
}
return;
}
}
}
內(nèi)存池測(cè)試
//
// Created by 68725 on 2022/7/26.
//
#include < stdlib.h >
#include < stdio.h >
#include < string.h >
#define PAGE_SIZE 4096
#define MP_ALIGNMENT 16
#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
//每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;
};
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);
void mp_reset_pool(struct mp_pool_s *pool) {
struct mp_node_s *cur;
struct mp_large_s *large;
for (large = pool- >large; large; large = large- >next) {
if (large- >alloc) {
free(large- >alloc);
}
}
pool- >large = NULL;
pool- >current = pool- >head;
for (cur = pool- >head; cur; cur = cur- >next) {
cur- >last = (unsigned char *) cur + sizeof(struct mp_node_s);
cur- >failed = 0;
cur- >quote = 0;
}
}
//創(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);
}
//size >4k
void *mp_malloc_large(struct mp_pool_s *pool, size_t size) {
unsigned char *big_addr;
int ret = posix_memalign((void **) &big_addr, MP_ALIGNMENT, size); //size
if (ret) {
return NULL;
}
struct mp_large_s *large;
//released struct large resume
int n = 0;
for (large = pool- >large; large; large = large- >next) {
if (large- >alloc == NULL) {
large- >size = size;
large- >alloc = big_addr;
return big_addr;
}
if (n++ > 3) {
break;// 為了避免過(guò)多的遍歷,限制次數(shù)
}
}
large = mp_malloc(pool, sizeof(struct mp_large_s));
if (large == NULL) {
free(big_addr);
return NULL;
}
large- >size = size;
large- >alloc = big_addr;
large- >next = pool- >large;
pool- >large = large;
return big_addr;
}
//new block 4k
void *mp_malloc_block(struct mp_pool_s *pool, size_t size) {
unsigned char *block;
int ret = posix_memalign((void **) &block, MP_ALIGNMENT, PAGE_SIZE); //4K
if (ret) {
return NULL;
}
struct mp_node_s *new_node = (struct mp_node_s *) block;
new_node- >end = block + PAGE_SIZE;
new_node- >next = NULL;
unsigned char *ret_addr = mp_align_ptr(block + sizeof(struct mp_node_s), MP_ALIGNMENT);
new_node- >last = ret_addr + size;
new_node- >quote++;
struct mp_node_s *current = pool- >current;
struct mp_node_s *cur = NULL;
for (cur = current; cur- >next; cur = cur- >next) {
if (cur- >failed++ > 4) {
current = cur- >next;
}
}
//now cur = last node
cur- >next = new_node;
pool- >current = current;
return ret_addr;
}
//分配內(nèi)存
void *mp_malloc(struct mp_pool_s *pool, size_t size) {
if (size <= 0) {
return NULL;
}
if (size > PAGE_SIZE - sizeof(struct mp_node_s)) {
//large
return mp_malloc_large(pool, size);
}
else {
//small
unsigned char *mem_addr = NULL;
struct mp_node_s *cur = NULL;
cur = pool- >current;
while (cur) {
mem_addr = mp_align_ptr(cur- >last, MP_ALIGNMENT);
if (cur- >end - mem_addr >= size) {
cur- >quote++;//引用+1
cur- >last = mem_addr + size;
return mem_addr;
}
else {
cur = cur- >next;
}
}
return mp_malloc_block(pool, size);// open new space
}
}
void *mp_calloc(struct mp_pool_s *pool, size_t size) {
void *mem_addr = mp_malloc(pool, size);
if (mem_addr) {
memset(mem_addr, 0, size);
}
return mem_addr;
}
//釋放內(nèi)存
void mp_free(struct mp_pool_s *pool, void *p) {
struct mp_large_s *large;
for (large = pool- >large; large; large = large- >next) {//大塊
if (p == large- >alloc) {
free(large- >alloc);
large- >size = 0;
large- >alloc = NULL;
return;
}
}
//小塊 引用-1
struct mp_node_s *cur = NULL;
for (cur = pool- >head; cur; cur = cur- >next) {
// printf("cur:%p p:%p end:%pn", (unsigned char *) cur, (unsigned char *) p, (unsigned char *) cur- >end);
if ((unsigned char *) cur <= (unsigned char *) p && (unsigned char *) p <= (unsigned char *) cur- >end) {
cur- >quote--;
if (cur- >quote == 0) {
if (cur == pool- >head) {
pool- >head- >last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
}
else {
cur- >last = (unsigned char *) cur + sizeof(struct mp_node_s);
}
cur- >failed = 0;
pool- >current = pool- >head;
}
return;
}
}
}
void monitor_mp_poll(struct mp_pool_s *pool, char *tk) {
printf("rnrn------start monitor poll------%srnrn", tk);
struct mp_node_s *head = NULL;
int i = 0;
for (head = pool- >head; head; head = head- >next) {
i++;
if (pool- >current == head) {
printf("current== >第%d塊n", i);
}
if (i == 1) {
printf("第%02d塊small block 已使用:%4ld 剩余空間:%4ld 引用:%4d failed:%4dn", i,
(unsigned char *) head- >last - (unsigned char *) pool,
head- >end - head- >last, head- >quote, head- >failed);
}
else {
printf("第%02d塊small block 已使用:%4ld 剩余空間:%4ld 引用:%4d failed:%4dn", i,
(unsigned char *) head- >last - (unsigned char *) head,
head- >end - head- >last, head- >quote, head- >failed);
}
}
struct mp_large_s *large;
i = 0;
for (large = pool- >large; large; large = large- >next) {
i++;
if (large- >alloc != NULL) {
printf("第%d塊large block size=%dn", i, large- >size);
}
}
printf("rnrn------stop monitor poll------rnrn");
}
int main() {
struct mp_pool_s *p = mp_create_pool(PAGE_SIZE);
monitor_mp_poll(p, "create memory pool");
#if 0
printf("mp_align(5, %d): %d, mp_align(17, %d): %dn", MP_ALIGNMENT, mp_align(5, MP_ALIGNMENT), MP_ALIGNMENT,
mp_align(17, MP_ALIGNMENT));
printf("mp_align_ptr(p- >current, %d): %p, p- >current: %pn", MP_ALIGNMENT, mp_align_ptr(p- >current, MP_ALIGNMENT),
p- >current);
#endif
void *mp[30];
int i;
for (i = 0; i < 30; i++) {
mp[i] = mp_malloc(p, 512);
}
monitor_mp_poll(p, "申請(qǐng)512字節(jié)30個(gè)");
for (i = 0; i < 30; i++) {
mp_free(p, mp[i]);
}
monitor_mp_poll(p, "銷毀512字節(jié)30個(gè)");
int j;
for (i = 0; i < 50; i++) {
char *pp = mp_calloc(p, 32);
for (j = 0; j < 32; j++) {
if (pp[j]) {
printf("calloc wrongn");
exit(-1);
}
}
}
monitor_mp_poll(p, "申請(qǐng)32字節(jié)50個(gè)");
for (i = 0; i < 50; i++) {
char *pp = mp_malloc(p, 3);
}
monitor_mp_poll(p, "申請(qǐng)3字節(jié)50個(gè)");
void *pp[10];
for (i = 0; i < 10; i++) {
pp[i] = mp_malloc(p, 5120);
}
monitor_mp_poll(p, "申請(qǐng)大內(nèi)存5120字節(jié)10個(gè)");
for (i = 0; i < 10; i++) {
mp_free(p, pp[i]);
}
monitor_mp_poll(p, "銷毀大內(nèi)存5120字節(jié)10個(gè)");
mp_reset_pool(p);
monitor_mp_poll(p, "reset pool");
for (i = 0; i < 100; i++) {
void *s = mp_malloc(p, 256);
}
monitor_mp_poll(p, "申請(qǐng)256字節(jié)100個(gè)");
mp_destroy_pool(p);
return 0;
}
nginx內(nèi)存池對(duì)比分析
相關(guān)結(jié)構(gòu)體定義對(duì)比
創(chuàng)建內(nèi)存池對(duì)比
內(nèi)存申請(qǐng)對(duì)比
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
8958瀏覽量
85084 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
2966瀏覽量
73812 -
API
+關(guān)注
關(guān)注
2文章
1472瀏覽量
61749 -
malloc
+關(guān)注
關(guān)注
0文章
52瀏覽量
63
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論