redis源码分析 -- 内存管理

redis源码分析 – 内存管理

zmalloc.h 这个头文件中,有 USE_TCMALLOCUSE_JEMALLOC 这两个宏,分别控制 redis 使用的是 tcmalloc 还是 jemalloc 这两个内存管理器。 tcmalloc 是Google gperftools里的组件之一。全名是 thread cache malloc(线程缓存分配器),其内存管理分为线程内存中央堆两部分。而 jemalloc 是由 FreeBSD 的开发人员 Jason Evans 开发的,在 FreeBSD、NetBSD和 FireFox 中是默认的 malloc,目前是 Maridab 、Tengine、Redis 中默认推荐的内存优化工具。在没有这两个内存管理器的情况下,redis 使用的是 glibc 的 malloc。下面讲解的都是使用 libc 库的源码分析。

#ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc"
#endif

redis 对 tcmalloc 和 jemalloc 的函数都进行了封装

#if defined(USE_TCMALLOC)
#define malloc(size) tc_malloc(size)
#define calloc(count,size) tc_calloc(count,size)
#define realloc(ptr,size) tc_realloc(ptr,size)
#define free(ptr) tc_free(ptr)
#elif defined(USE_JEMALLOC)
#define malloc(size) je_malloc(size)
#define calloc(count,size) je_calloc(count,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#endif

在 redis 中定义了下面这三个变量

static size_t used_memory = 0;
static int zmalloc_thread_safe = 0;
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;

used_memory 表示系统使用的内存大小,全局维护这么一个变量,说明作者希望通过这个变量来反映内存的使用情况。zmalloc_thread_safe通过变量名也能看出,这个是控制线程安全模式的变量,后面的 mutex 变量 used_memory_mutex 就是用在线程安全条件下的互斥信号量。

HAVE_ATOMIC定义了原子操作

#define update_zmalloc_stat_add(__n) __sync_add_and_fetch(&used_memory, (__n))
#define update_zmalloc_stat_sub(__n) __sync_sub_and_fetch(&used_memory, (__n))

gcc 从 4.1.2 提供了 __sync_* 系列的 built-in 函数,用于提供加减和逻辑运算的原子操作。

// 返回更新前的值
type __sync_fetch_and_add (type *ptr, type value, ...)
type __sync_fetch_and_sub (type *ptr, type value, ...)
type __sync_fetch_and_or (type *ptr, type value, ...)
type __sync_fetch_and_and (type *ptr, type value, ...)
type __sync_fetch_and_xor (type *ptr, type value, ...)
type __sync_fetch_and_nand (type *ptr, type value, ...)

// 返回更新后的值
type __sync_add_and_fetch (type *ptr, type value, ...)
type __sync_sub_and_fetch (type *ptr, type value, ...)
type __sync_or_and_fetch (type *ptr, type value, ...)
type __sync_and_and_fetch (type *ptr, type value, ...)
type __sync_xor_and_fetch (type *ptr, type value, ...)
type __sync_nand_and_fetch (type *ptr, type value, ...)

如果没有定义 HAVE_ATOMIC这个宏,使用 mutex 实现对 used_memory 的安全操作

#define update_zmalloc_stat_add(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory += (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

#define update_zmalloc_stat_sub(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory -= (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

申请

内存申请 zmalloc 函数,调用的仍然是 glibc 的 malloc 函数。

void *zmalloc(size_t size) {
    void *ptr = malloc(size+PREFIX_SIZE);

    // 当申请的 ptr 为 NULL 时,调用 oom 函数处理方法
    if (!ptr) zmalloc_oom_handler(size);
#ifdef HAVE_MALLOC_SIZE
    update_zmalloc_stat_alloc(zmalloc_size(ptr));
    ret
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫步旅人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值