学习redis源码(1):redis的内存管理

2019-08-11  本文已影响0人  三分钟热度的陈恤猿

       内存分配的代码写在zmalloc.c和zmalloc.h中。原理是对底层内存分配方式的再封装。除此之外,redis没有对内存进行额外的操作,因此,内存分配器的性能和碎片化率会对redis造成一些性能上的影响。其底层内存分配会根据宏的选择不同而有所不同。如果定义了USE_TCMALLOC,则使用tcmalloc;如果定义了USE_JEMALLOC,则使用jemalloc;否则如果系统自带c运行库,将会使用系统自带的malloc进行内存分配;最后才会使用redis自己的内存分配函数。
redis会通过定义宏 HAVE_MALLOC_SIZE为1 来表示使用的是其他库的内存分配函数。
       封装的底层函数:

malloc_usable_size(p)//返回p对应内存的大小
malloc(size)//分配堆内存,内容没有初始化
calloc(count,size)//在malloc基础上,将内存初始化为0
realloc(ptr,size)
free(ptr)

       对于特定版本的JEMALLOC,redis实现了内存的碎片化处理。

       zmalloc里主要的两个宏

#define update_zmalloc_stat_alloc(__n) do { \
    size_t _n = (__n); \
    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
    atomicIncr(used_memory,__n); \
} while(0)

#define update_zmalloc_stat_free(__n) do { \
    size_t _n = (__n); \
    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
    atomicDecr(used_memory,__n); \

       上面两个都进行了原子操作,保证线程安全;同时if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)) 确保了64位机上8字节对齐(这个技巧运用了位操作,效率很高;同时字节对齐的单位取决于系统,即所谓的软编码)。
       zmalloc里的重要变量:

static size_t used_memory = 0;
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;

       zmalloc主要函数如下:

size_t zmalloc_usable(void *ptr)//返回内存大小(不包含prefix的大小)
size_t zmalloc_size(void *ptr)//返回内存大小(包含prefix的大小)
void *zmalloc(size_t size);
void *zcalloc(size_t size);
void *zrealloc(void *ptr, size_t size);
void zfree(void *ptr);
char *zstrdup(const char *s);
size_t zmalloc_used_memory(void);
void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
//获得系统的配置信息
size_t zmalloc_get_rss(void);//实际使用的物理内存
size_t zmalloc_get_smap_bytes_by_field(char *field, long pid);//得到指定pid指定field对应的值
size_t zmalloc_get_private_dirty(long pid);//上一个函数的filed为”Private_Dirty"
int zmalloc_get_allocator_info(size_t *allocated, size_t *active, size_t *resident);//得到已经申请了内存数,活跃的,长期存在的内存数
size_t zmalloc_get_memory_size(void);//获得RAM的大小

       redis的内存分配方式如下:



       prefix存储buf的大小。这种管理方式类似redis中的sds管理方式。如果使用了外部库的内存分配函数,PREFIX_SIZE为0。

上一篇下一篇

猜你喜欢

热点阅读