实现内存池的测试用例、继承jemalloc和自实现内存池。

This commit is contained in:
2026-01-09 20:09:05 +08:00
parent 4b4e06b33d
commit 1adb24482b
16 changed files with 664 additions and 436 deletions

164
mem_pool/mem_pool.c Normal file
View File

@@ -0,0 +1,164 @@
#include "mem_pool.h"
#include <stddef.h>
#include <stdlib.h>
#define JEMALLOC_NO_DEMANGLE
#include <jemalloc/jemalloc.h>
void *kvs_malloc(size_t size) {
#if MEMORY_SELECT_MALLOC == MEMORY_USE_DEFAULT
return malloc(size);
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
return mp_alloc(size);
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_JEMALLOC
return je_malloc(size);
#endif
}
void kvs_free(void *ptr) {
#if MEMORY_SELECT_MALLOC == MEMORY_USE_DEFAULT
free(ptr);
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
mp_free(ptr);
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_JEMALLOC
je_free(ptr);
#endif
}
#if MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
mp_pool_t global_mempool = {0};
#endif
// >= x 的第一个2^n
uint32_t mp_ceil_pow2_u32(uint32_t x) {
if (x <= 1) return 1;
x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
// return cid
uint16_t mp_class_id_for(size_t size) {
if (size < 8) size = 8;
if (size > (1u << MP_MAX_SHIFT)) return MP_LARGE_CLASS;
uint32_t s = (uint32_t)size;
uint32_t p2 = mp_ceil_pow2_u32(s); /* 8/16/32... */
/* 计算 log2(p2) */
uint16_t shift = 0;
while ((1u << shift) < p2) shift++;
return (uint16_t)(shift - MP_MIN_SHIFT);
}
size_t mp_user_size_from_class(uint16_t cid) {
return (size_t)1u << (cid + MP_MIN_SHIFT);
}
int mp_add_page(mp_pool_t* p, void* mem) {
mp_page_t* pg = (mp_page_t*)malloc(sizeof(mp_page_t));
if (!pg) return -1;
pg->mem = mem;
pg->next = p->pages;
p->pages = pg;
return 0;
}
int mp_grow(mp_pool_t* p, uint16_t cid) {
void* page = malloc(MP_PAGE_SIZE);
if (!page) return -1;
if (mp_add_page(p, page) != 0) { free(page); return -1; }
// cid对应的空间大小
const size_t user_sz = mp_user_size_from_class(cid);
const size_t block_sz = sizeof(mp_blk_hdr_t) + user_sz;
const size_t n = MP_PAGE_SIZE / block_sz;
if (n == 0) return -1;
uint8_t* cur = (uint8_t*)page;
for (size_t i = 0; i < n; ++i) {
mp_blk_hdr_t* h = (mp_blk_hdr_t*)cur;
h->magic = MP_MAGIC;
h->class_id = cid;
mp_free_node_t* user = (mp_free_node_t*)(h + 1);
user->next = p->buckets[cid].free_list;
p->buckets[cid].free_list = user;
cur += block_sz;
}
return 0;
}
void mp_init(mp_pool_t* p){
if (!p) return;
for (int i = 0; i < MP_NBUCKETS; ++i) p->buckets[i].free_list = NULL;
p->pages = NULL;
}
void mp_destroy(mp_pool_t* p){
if (!p) return;
mp_page_t* pg = p->pages;
while (pg) {
mp_page_t* nxt = pg->next;
free(pg->mem);
free(pg);
pg = nxt;
}
p->pages = NULL;
for (int i = 0; i < MP_NBUCKETS; ++i) p->buckets[i].free_list = NULL;
}
void* mp_alloc(size_t size){
mp_pool_t* p = &global_mempool;
if (!p) return NULL;
if (size == 0) size = 1;
uint16_t cid = mp_class_id_for(size);
if (cid == MP_LARGE_CLASS) {
mp_blk_hdr_t* h = (mp_blk_hdr_t*)malloc(sizeof(mp_blk_hdr_t) + size);
if (!h) return NULL;
h->magic = MP_MAGIC;
h->class_id = MP_LARGE_CLASS;
return (void*)(h + 1);
}
mp_free_node_t* node = p->buckets[cid].free_list;
if (!node) {
if (mp_grow(p, cid) != 0) return NULL;
node = p->buckets[cid].free_list;
if (!node) return NULL;
}
p->buckets[cid].free_list = node->next;
return (void*)node;
}
void mp_free(void* ptr){
mp_pool_t* p = &global_mempool;
if (!p || !ptr) return;
mp_blk_hdr_t* h = ((mp_blk_hdr_t*)ptr) - 1;
if (h->magic != MP_MAGIC) {
/* 非法指针:极简处理(你也可以 assert/abort */
return;
}
if (h->class_id == MP_LARGE_CLASS) {
/* 大对象:直接 free 整块(从 header 起) */
free(h);
return;
}
if (!p) return;
uint16_t cid = h->class_id;
if (cid >= MP_NBUCKETS) return; /* 极简:不做更多校验 */
mp_free_node_t* node = (mp_free_node_t*)ptr;
node->next = p->buckets[cid].free_list;
p->buckets[cid].free_list = node;
}