源碼版本:redis 2.4.4
redis記憶體相關函數都放在zmalloc.h zmalloc.c中
redis中可以使用tcmalloc、jemalloc
Makefile:
ifeq ($(USE_TCMALLOC),yes) ALLOC_DEP= ALLOC_LINK=-ltcmalloc ALLOC_FLAGS=-DUSE_TCMALLOCendififeq ($(USE_JEMALLOC),yes) ALLOC_DEP=../deps/jemalloc/lib/libjemalloc.a ALLOC_LINK=$(ALLOC_DEP) -ldl ALLOC_FLAGS=-DUSE_JEMALLOC -I../deps/jemalloc/includeendif
zmalloc.c中
#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
簡單封裝
void *zmalloc(size_t size);
void *zcalloc(size_t size);
void *zrealloc(void *ptr, size_t size);
void zfree(void *ptr);
分別對malloc、calloc、realloc、free做了簡單封裝
對zmalloc和zfree做分析
void *zmalloc(size_t size) { void *ptr = malloc(size+PREFIX_SIZE); if (!ptr) zmalloc_oom(size);#ifdef HAVE_MALLOC_SIZE update_zmalloc_stat_alloc(zmalloc_size(ptr),size); return ptr;#else *((size_t*)ptr) = size; update_zmalloc_stat_alloc(size+PREFIX_SIZE,size); return (char*)ptr+PREFIX_SIZE;#endif}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}
除了分配給指定大小的記憶體之外,還分配了PREFIX_SIZE
記憶體格局如下:
申請記憶體返回Real_ptr
#define update_zmalloc_stat_alloc(__n,__size) do { \ size_t _n = (__n); \ if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \ if (zmalloc_thread_safe) { \ pthread_mutex_lock(&used_memory_mutex); \ used_memory += _n; \ pthread_mutex_unlock(&used_memory_mutex); \ } else { \ 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)); \ if (zmalloc_thread_safe) { \ pthread_mutex_lock(&used_memory_mutex); \ used_memory -= _n; \ pthread_mutex_unlock(&used_memory_mutex); \ } else { \ used_memory -= _n; \ } \} while(0)
used_memory記錄當前分配的總記憶體
在定義了 int vm_max_threads; /* Max number of I/O threads running at the same time */
if (server.vm_max_threads != 0)
zmalloc_enable_thread_safeness(); /* we need thread safe zmalloc() */
在使用Threaded Virtual Memory I/O的時候,需要安全的zmalloc
size_t zmalloc_used_memory(void) { size_t um; if (zmalloc_thread_safe) pthread_mutex_lock(&used_memory_mutex); um = used_memory; if (zmalloc_thread_safe) pthread_mutex_unlock(&used_memory_mutex); return um;}
zmalloc_used_memory返回進程當前使用的記憶體,用以做相應的清記憶體操作,eg:
zmalloc_used_memory() > server.maxmemory //和配置的最大記憶體比較....
zmalloc_get_rss()用來計算進程實際使用實體記憶體