Redis zmalloc模块

2020-12-03  本文已影响0人  突击手平头哥

Redis zmalloc模块

zmalloc是处理redis内存的模块,主要涉及文件有:zmalloc、zmalloc.h、atomicvar.h, 本文从几个函数入手,简单说明该模块;同时这里面兼容了没有很多系统版本,目前仅分析普通Linux下的情况

HAVE_MALLOC_SIZE宏定义

#if defined(USE_TCMALLOC)
#define ZMALLOC_LIB ("tcmalloc-" __xstr(TC_VERSION_MAJOR) "." __xstr(TC_VERSION_MINOR))
#include <google/tcmalloc.h>
#if (TC_VERSION_MAJOR == 1 && TC_VERSION_MINOR >= 6) || (TC_VERSION_MAJOR > 1)
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) tc_malloc_size(p)
#else
#error "Newer version of tcmalloc required"
#endif

  这里截取了一部分,优先采用tmalloc、jmalloc最后才使用标准的malloc函数;对于tmalloc、jmalloc我们不做分析处理,这里就当作是普通系统的malloc来分析

zmalloc_size函数

Redis中有统计内存大小的需求, 而正常来说malloc会进行一定的4/8字节对齐,所以不能简单的计算;该函数是系统API计算堆上分配的内存

#define zmalloc_size(p) malloc_usable_size(p)

zmalloc函数

void *zmalloc(size_t size) {
    void *ptr = malloc(size+PREFIX_SIZE);               //单独内存分配并没有做非常特殊的封装

    if (!ptr) zmalloc_oom_handler(size);                //可以忽略,只是在错误时打印错误并退出
#ifdef HAVE_MALLOC_SIZE
    update_zmalloc_stat_alloc(zmalloc_size(ptr));       //累计已分配内存大小
    return ptr;
#else
    *((size_t*)ptr) = size;                             //兼容没有malloc_size的情况, 在头部加一个PREFIX_SIZE存储大小
    update_zmalloc_stat_alloc(size+PREFIX_SIZE);
    return (char*)ptr+PREFIX_SIZE;
#endif
}

//因为malloc对齐的缘故, 所以累计大小时需要向上扩展到4/8的倍数
#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)

\color{red}{内存分配还是简单的malloc, 但是进行了数量统计以及很多系统兼容问题}

zfree函数

void zfree(void *ptr) {
#ifndef HAVE_MALLOC_SIZE
    void *realptr;
    size_t oldsize;
#endif

    if (ptr == NULL) return;
#ifdef HAVE_MALLOC_SIZE
    update_zmalloc_stat_free(zmalloc_size(ptr));
    free(ptr);
#else
    realptr = (char*)ptr-PREFIX_SIZE;
    oldsize = *((size_t*)realptr);
    update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
    free(realptr);
#endif
}

#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); \
} while(0)

实现于zmalloc是类似的

atomicIncr函数

顾名思义, 很简单就可以猜出是进行原子性加减的函数

.....
#define atomicIncr(var,count) __atomic_add_fetch(&var,(count),__ATOMIC_RELAXED)

.....
#define atomicIncr(var,count) __sync_add_and_fetch(&var,(count))

.....
#define atomicIncr(var,count) do { \
    pthread_mutex_lock(&var ## _mutex); \
    var += (count); \
    pthread_mutex_unlock(&var ## _mutex); \
} while(0)

  __sync_add_and_fetch是gcc编译器提供的原子性操作,第一个没了解过;如果编译器或者系统未提供原子性操作,即使用锁来实现

上一篇下一篇

猜你喜欢

热点阅读