redis zmalloc

zmalloc

Redis现在的版本可以支持使用tcmalloc或者是jemalloc或是applemalloc,或者是Redis自己的zmalloczmalloc对内存的分配管理是线程安全的(static size_t used_memory = 0;变量用来记录已经使用的内存空间的大小),而且分配的内存必须要求是以sizeof(long)对其的。

源码

zmalloc.hzmalloc.c

分析

宏变量说明:

  • PREFIX_SIZE:在实际分配的内存之前用于记录分配的内存的大小,和在实际的C中的malloc的内存数据结构类似,但是可能C是根据具体的环境不同的。
  • HAVE_MALLOC_SIZE:表明是否使用的是其他的malloc实现,这些malloc的实现中就可以有相关的函数可以直接获得所分配的内存的大小,如果没有的话则根据zmalloc的实现是实际分配的size+PREFIX_SIZE。
  • #ifndef HAVE_MALLOC_SIZE
  • size_t zmalloc_size(void *ptr);
  • #endif

其他

zmalloc除了提供标准的zamlloczcalloczrealloczfree功能之外还提供了dump内存数据到字符串的函数zstrdup,获得已经使用的内存总量的zmalloc_used_memory函数以及设置内存溢出处理函数的zmalloc_set_oom_handler。同时还提供了用于获得系统中的RSS,即程序所占用的实际的物理内存大小


-------------------------------------以上是转载。

/* Double expansion needed forstringification of macro values. */

#define __xstr(s) __str(s)

#define __str(s) #s

 在注释中出现了一个专有名词“ stringification ”,经查阅,网络上比较认可的翻译是“字符串化”。所以上面双重宏定义的用途为“用于宏值字符串化的双重宏展开 ”。

中也对双重宏定义的用法进行了举例说明。针对 xstr(foo) 展开的情况,由于 xstr() 本身是一个符合普通宏展开定义的东东,而 foo 同样是这样的一个东东 ,所以,在对  xstr(foo) 进行宏展开的时,会按照正常的展开顺序进行,即先展开 foo,再展开 xstr 。 

stringification :

Sometimes you may want to convert a macro argument into astring constant. Parameters are not replaced inside string constants, but youcan use the ‘#’ preprocessing operator instead. When a macro parameter isused with a leading ‘#’, the preprocessor replaces it with the literal text ofthe actual argument, converted to a string constant. Unlike normal parameterreplacement, the argument is not macro-expanded first. This is calledstringification.

 

至于采用二级定义的好处,当然就是可以更加灵活的对宏展开时的内容进行控制。

#define __xstr(s) __str(s)

#define __str(s) #s

#define foo 4

Str(foo) ==》“foo

Xstr(foo) èxstr(4)->str(4)->”4”

 

 

#definezmalloc_size(p) malloc_size(p)

 

void*zmalloc(size_t size);

 

void*zcalloc(size_t size);

 

void*zrealloc(void *ptr, size_t size);

 

void zfree(void*ptr);

调用相应的malloc realloc calloc并对used_memory进行处理

另外还加上对溢出(分配失败或释放失败)进行判断,并进行处理。

 

 

char*zstrdup(const char *s);

char*类型的s的字符串,在堆空间上进行分配空间(strlen(s)+1),并复制s的内容到空间上。

 

size_tzmalloc_used_memory(void);

获取used_memory,这里used_memory是共享资源,必须先获取线程的互斥量锁。

 

 

voidzmalloc_enable_thread_safeness(void);

 

voidzmalloc_set_oom_handler(void (*oom_handler)(size_t));//内存溢出处理函数

         默认的处理函数为打印出出错信息,之后abort()终止

 

 

floatzmalloc_get_fragmentation_ratio(size_t rss);

 

Fragmentation =RSS / allocated-bytes

 

 

size_tzmalloc_get_rss(void);

这个函数效率比较慢,RedisEstimateRSS()函数,这是一个快得多(不太准确)

HAVE_PROC_STAT:读取/proc/pid/stat文件的内容。

HAVE_TASKINFOtask_for_pid()  task_basic_info

其他:zmalloc_used_memory

 

 

size_tzmalloc_get_private_dirty(void);

HAVE_PROC_SMAPS/proc/self/smaps

voidzlibc_free(void *ptr);

访问original libc free() libc运行库里的free()

我们需要定义这个函数在包含zmalloc.h之前,这样可以隐藏free实现,if we use jemalloc or another nonstandard allocator.

 

 

 

当使用tcmalloc重写malloc/free函数,

使用#define malloc(size) tc_malloc(size)

 

 

 

 

size_t _n =(__n); \

if (_n&(sizeof(long)-1)) _n +=sizeof(long)-(_n&(sizeof(long)-1)); \

这里需要_nlong的整数倍(如果不满足,则扩大_n的大小为long的整数倍)

static size_tused_memory = 0;

static intzmalloc_thread_safe = 0;

pthread_mutex_tused_memory_mutex = PTHREAD_MUTEX_INITIALIZER;//只对静态分配的互斥量进行初始化。

rss =strtoll(p,NULL,10);

你可能感兴趣的:(redis zmalloc)