memlink按照天涯的人说是一个灰常牛的key-List系统,比Redis要快很多倍,下面就来一点点看它的代码。在内存中的Block也是通过一个池来管理的,用到的数据结构大致有三个DataBlock、MemItem、MemPool。MemPool的结构如下:
typedef struct _mempool
{
MemItem *freemem; // 数组
int size; // 数组的大小
int used; // 正在用的MemItem的大小
int blocks; // 内存池中的数目
}MemPool;
在一个内存池中管理的有各种大小的Block,而相同大小的Block就被放在统一个MemItem中来管理,该结构如下:
typedef struct _mem_item
{
int memsize; // 管理的块的大小
unsigned int block_count; // 块的数目
unsigned int total; // 用的空闲的块的总数
DataBlock *data; // 相当于一个链表头
}MemItem;
通过这个单位就把所有的大小相同的放在了统一个Item中管理,而数据块的表示如下:
typedef struct _data_block
{
unsigned short data_count; // 小块的数目
unsigned short visible_count; // visible item count
unsigned short tagdel_count; // tag delete item count, invisible
struct _data_block *prev;
struct _data_block *next;
char data[0];
}DataBlock;
该结构在内存中通过双向链表来保存,链表的头保存在MemItem中,
关于是否内存和申请内存的操作都很普通。这里用内存池显然是为了减少分配释放带来的开销,那为什在expend的时候不用改变内存大小的系统调用?这样的话可能减少一次分配和一次拷贝和一次释放,代码如下:
int mempool_expand(MemPool *mp)
{
int newnum = mp->size * 2;
MemItem *newitems = (MemItem*)zz_malloc(sizeof(MemItem) * newnum);
if (NULL == newitems) {
DERROR("malloc error!\n");
MEMLINK_EXIT;
return -1;
}
memcpy(newitems, mp->freemem, sizeof(MemItem) * mp->used);
zz_free(mp->freemem);
mp->freemem = newitems;
mp->size = newnum;
return 0;
}
-------------------------------------------
个人理解,欢迎拍砖。