Files
ldb/mem_pool/mem_pool.c
2026-01-10 18:31:26 +08:00

165 lines
4.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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};
// >= 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;
}
#endif