Redis进行内存分配使用的是zmalloc,对应源文件为:zmalloc.h
,zmalloc.c
。
zmalloc - total amount of allocated memory aware version of malloc()
zmalloc的作用是对内存分配进行一些统计,使我们能清楚知道现在分配了多少总内存。
两个宏
- USE_TCMALLOC
- USE_JEMALLOC
如果定义了USE_TCMALLOC,那么zmalloc()底层使用的是tc_malloc();
如果定义了USE_JEMALLOC,那么zmalloc()底层使用的是je_malloc();
否则,zmalloc()使用glibc提供的malloc()。
what’re the differences between tcmalloc/jemalloc and memory pool
内存分配
zmalloc分配的内存由两部分组成:
- 实际大小部分
- 内容数据部分
zmalloc使用底层的malloc分配完内存之后,把内存大小存储在最开始的4个字节里面,返回的指针部分是指向的内容数据部分。我们使用通过zmalloc分配到的内存与直接用malloc分配的内存是一样的,实际大小部分是由zmalloc去处理的。
看下源代码:
统计功能
zmalloc在malloc的基础上做了一些内存使用的统计功能:
- 每一块分配内存的前4个字节记录这块内存的实际大小
- 定义全局变量:static size_t
used_memory
= 0
为了线程安全的修改全局变量used_memory,引入了两个变量:
- pthread_mutex_t
used_memory_mutex
:线程互斥锁 - int
zmalloc_thread_safe
:是否开启线程安全
这里如果编译器支持HAVE_ATOMIC
的话,直接使用__sync_add_and_fetch(),否则,使用互斥锁更新内存使用量。
OOM处理器
Redis提供了一个OOM处理器:zmalloc_oom_handler
当调用malloc()返回NULL,也即是内存不足时,输出错误日志并退出。