要想了解redis底层的内存管理是如何进行的,直接看源码绝对是一个很好的选择

下面是我添加了详细注释的源码,需要注意的是,为了便于源码分析,我把redis为了弥补平台差异的那部分代码删了,只需要知道有这个东西便好

下面我会贴上两份源码:一份是我自己的,有删减添加了注释的,一部分是原生的,可以做个参考对照

redis内存管理部分的源码在zmalloc.h文件和zmalloc.c文件

推荐文章:

https://www.cnblogs.com/likui360/p/5272443.html

https://www.cnblogs.com/likui360/p/5272975.html

http://wiki.jikexueyuan.com/project/redis/memory-data-management.html

我的源码

zmalloc.h:

#ifndef __ZMALLOC_H
#define __ZMALLOC_H #define __xstr(s) __str(s)
#define __str(s) #s #ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc"
#endif /*
CPU一次性能读取数据的二进制位数称为字长,也就是我们通常所说的32位系统(字长4个字节)、64位系统(字长8个字节)的由来。 所谓的8字节对齐,就是指变量的起始地址是8的倍数。 比如程序运行时(CPU)在读取long型数据的时候,只需要一个总线周期,时间更短, 如果不是8字节对齐的则需要两个总线周期才能读完数据。 本文中我提到的8字节对齐是针对64位系统而言的,如果是32位系统那么就是4字节对齐。 实际上Redis源码中的字节对齐是软编码,而非硬编码。 里面多用sizeof(long)或sizeof(size_t)来表示。 size_t(gcc中其值为long unsigned int)和long的长度是一样的, long的长度就是计算机的字长。 这样在未来的系统中如果字长(long的大小)不是8个字节了,该段代码依然能保证相应代码可用。 */ /**
Redis内存模型: |--------|:代表8个字节大小 | 头部 | 实际内存 |
|--------|--------|--------|--------|--------|
^
|
ptr:实际返回的地址 上面的内存模型说明了两个问题: 1.内存对齐,都是8个字节的,可以提高cpu响应速度 2.返回的实际地址不包括头部 ps:从左到右内存地址是增加的,默认大端模式 */
//============ API ==================// //封装malloc,申请内存
void *zmalloc(size_t size); //封装calloc,不再支持按块成倍申请
void *zcalloc(size_t size); //封装realloc,内存扩展
void *zrealloc(void *ptr, size_t size); //封装free,内存释放,释放时会更新已经使用的内存值,如果在多线程下没有开启安全模式,可能会出现并发错误
void zfree(void *ptr); //复制一个字符串,为字符串在堆分配内存
char *zstrdup(const char *s); //获取已经使用的内存大小
size_t zmalloc_used_memory(void); //设置内存管理为多线程安全模式,设置之后在更新使用内存大小时会使用mutex进行互斥操作
void zmalloc_enable_thread_safeness(void); //设置内存异常时的回调函数
void zmalloc_set_oom_handler(void (*oom_handler)(size_t)); //内存碎片率,驻留在物理内存中的内存/总分配的物理内存
float zmalloc_get_fragmentation_ratio(size_t rss); //获取进程可使用的所有内存大小
size_t zmalloc_get_rss(void); //获得private_dirty字段
size_t zmalloc_get_private_dirty(void); //用这个释放内存时,不会更新使用内存变量的值。
void zlibc_free(void *ptr); //获取内内存块总体大小
size_t zmalloc_size(void *ptr); #endif /* __ZMALLOC_H */ /*
1.malloc函数和calloc函数的区别 void *malloc(unsigned int size) 在内存中分配一个大小为size的连续空间 void* calloc(unsigned int num,unsigned int size)在内存中分配num个size大小的内存空间 调用malloc后内存中的数据是随机的垃圾数据 调用calloc后内存中的数据是0,因为calloc会自动清零 2.redis为了方便管理内存,在分配一块内存之后,会将内存大小size插入内存头部,size所占内存大小固定 3.Redis允许使用四种内存管理策略:jemalloc,tcmalloc,苹果系统自带的malloc,其他系统自带的malloc 当存在前面三种策略的时候,就选择前面三种,第四种是没有选择的选择 jemalloc是freebsd操作系统自带的内存分配策略,具有速度快,多线程优化的特点 tcmalloc是谷歌开发的,里面集成了很多内存分配的测试工具 这二者的性能不分伯仲 4.Redis很多对象都是共享的,可以节约内存 5.memory aware【内存感知】 Redis能随时高性能的感知所使用的内存总量,实时的获取Redis所使用的内存的大小,从而随时感知内存 实现方式:
每次分配/释放内存时都更新一个全局的内存使用值 6.内存对齐,比如5位补齐为8位,CPU访问对齐内存仅仅需要一次,访问非对齐内存需要2次,内存对齐可以提高cpu的访问速率 */

 

zmalloc.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "zmalloc.h" //记录已经使用的内存大小
static size_t used_memory = ; //线程安全开关
static int zmalloc_thread_safe = ; //互斥锁,如果开启了线程安全,而编译器又不支持原子操作函数,则需要互斥锁来完成代码互斥操作
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER; //头部长度
#define PREFIX_SIZE (sizeof(size_t)) //以线程安全的方式 增加 内存已使用 变量
#define update_zmalloc_stat_add(__n) do { \
pthread_mutex_lock(&used_memory_mutex); \
used_memory += (__n); \
pthread_mutex_unlock(&used_memory_mutex); \
} while() //以线程安全的方式 减小 内存已使用 变量 #define update_zmalloc_stat_sub(__n) do { \
pthread_mutex_lock(&used_memory_mutex); \
used_memory -= (__n); \
pthread_mutex_unlock(&used_memory_mutex); \
} while() //增加 已经使用的内存大小,函数内确定是否以线程安全的模式运行
#define update_zmalloc_stat_alloc(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-)) _n += sizeof(long)-(_n&(sizeof(long)-));/*手动内存补齐*/ \
if (zmalloc_thread_safe) { \
update_zmalloc_stat_add(_n); \
} else { \
used_memory += _n; \
} \
} while() //减小 已经使用的内存大小,函数内确定是否以线程安全的模式运行
#define update_zmalloc_stat_free(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-)) _n += sizeof(long)-(_n&(sizeof(long)-)); /*手动内存补齐*/ \
if (zmalloc_thread_safe) { \
update_zmalloc_stat_sub(_n); \
} else { \
used_memory -= _n; \
} \
} while() //释放内存,不会更改 已使用内存变量
void zlibc_free(void *ptr)
{
free(ptr);
} //打印错误信息并且终止程序 OOM:out of memory
static void zmalloc_default_oom(size_t size)
{
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
size);
fflush(stderr);
abort();
} //设置OMM时的回调函数
static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom; //申请size大小的连续内存空间,返回一个指向该空间的指针
void *zmalloc(size_t size)
{
//申请内存空间,预留了PREFIX_SIZE这样一小段空间
void *ptr = malloc(size+PREFIX_SIZE); //oom out of memory
if (!ptr) zmalloc_oom_handler(size); // 如果分配不成功,那么说明内存用尽 //把内存大小存储在头部
*((size_t*)ptr) = size; //更新已经使用的内存大小
update_zmalloc_stat_alloc(size+PREFIX_SIZE); //返回指向该内存空间实际地址的指针,该指针不指向存放内存大小的内存头部
return (char*)ptr+PREFIX_SIZE;
} //内存申请
void *zcalloc(size_t size)
{
//不再支持按倍数分配内存
void *ptr = calloc(, size+PREFIX_SIZE); //内存分配失败,调用回调函数
if (!ptr) zmalloc_oom_handler(size); *((size_t*)ptr) = size; //更改已经使用的内存大小
update_zmalloc_stat_alloc(size+PREFIX_SIZE); //返回指向该内存块的指针
return (char*)ptr+PREFIX_SIZE;
} //指定的内存扩展为size大小,返回扩展后的内存块指针
void *zrealloc(void *ptr, size_t size)
{
void *realptr;
size_t oldsize;
void *newptr; //原内存为空,则直接申请
if (ptr == NULL) return zmalloc(size); //实际内存地址指针(包含头部)
realptr = (char*)ptr-PREFIX_SIZE; //实际内存大小(包含头部)
oldsize = *((size_t*)realptr); //其实zrealloc底层还是封装了realloc,将原内存扩展为size+PREFIX_SIZE大小
newptr = realloc(realptr,size+PREFIX_SIZE); //内存扩展失败,进行回调
if (!newptr) zmalloc_oom_handler(size); //新内存块大小记录在内存头部
*((size_t*)newptr) = size; //修改已使用的内存大小
update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(size); //返回指针指向扩展后的内存块(不包含头部)
return (char*)newptr+PREFIX_SIZE;
} //返回指定内存块的大小(不包括头部)
size_t zmalloc_size(void *ptr)
{
//指向实际内存块(包含头部)
void *realptr = (char*)ptr-PREFIX_SIZE; //实际内存块大小
size_t size = *((size_t*)realptr); //内存对齐,比如5位补齐为8位,CPU访问对齐内存仅仅需要一次,访问非对齐内存需要2次,内存对齐可以提高cpu的访问速率
if (size&(sizeof(long)-)) size += sizeof(long)-(size&(sizeof(long)-)); //返回内存大小(不包括头部)
return size+PREFIX_SIZE;
} //释放内存,会更改 已使用的内存变量
void zfree(void *ptr)
{
/*释放内存之前要先获得包含头部内存的实际内存地址,才能避免头部内存的内存泄漏*/
void *realptr;
size_t oldsize; //空内存 直接返回
if (ptr == NULL) return; //指向实际内存(包含内存头部)
realptr = (char*)ptr-PREFIX_SIZE; //实际内存大小
oldsize = *((size_t*)realptr); //更改已使用的内存变量
update_zmalloc_stat_free(oldsize+PREFIX_SIZE); //释放
free(realptr); } //复制字符串
char *zstrdup(const char *s)
{
size_t l = strlen(s)+;
char *p = zmalloc(l);
memcpy(p,s,l);
return p;
} //获得已使用的内存空间
size_t zmalloc_used_memory(void)
{
size_t um; //线程不安全的情况 加锁
if (zmalloc_thread_safe)
{
pthread_mutex_lock(&used_memory_mutex);
um = used_memory;
pthread_mutex_unlock(&used_memory_mutex); }
else
{
um = used_memory;
} return um;
} //启动线程安全的开关,保证线程安全
void zmalloc_enable_thread_safeness(void)
{
zmalloc_thread_safe = ;
} //设置OMM的回调函数
void zmalloc_set_oom_handler(void (*oom_handler)(size_t))
{
zmalloc_oom_handler = oom_handler;
} //下面几个函数深究起来意义不大 //获取进程可使用的所有内存大小
size_t zmalloc_get_rss(void)
{
//很多东西我注释掉了.....
return zmalloc_used_memory();
} //内存碎片率
float zmalloc_get_fragmentation_ratio(size_t rss)
{
return (float)rss/zmalloc_used_memory();
} //获得private_dirty字段
size_t zmalloc_get_private_dirty(void)
{
return ;
}

原生源码:

zmalloc.h:

/* zmalloc - total amount of allocated memory aware version of malloc()
*
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/ #ifndef __ZMALLOC_H
#define __ZMALLOC_H /* Double expansion needed for stringification of macro values. */
#define __xstr(s) __str(s)
#define __str(s) #s #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 #elif defined(USE_JEMALLOC)
#define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX))
#include <jemalloc/jemalloc.h>
#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) je_malloc_usable_size(p)
#else
#error "Newer version of jemalloc required"
#endif #elif defined(__APPLE__)
#include <malloc/malloc.h>
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_size(p)
#endif #ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc"
#endif void *zmalloc(size_t size);
void *zcalloc(size_t size);
void *zrealloc(void *ptr, size_t size);
void zfree(void *ptr);
char *zstrdup(const char *s);
size_t zmalloc_used_memory(void);
void zmalloc_enable_thread_safeness(void);
void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
float zmalloc_get_fragmentation_ratio(size_t rss);
size_t zmalloc_get_rss(void);
size_t zmalloc_get_private_dirty(void);
void zlibc_free(void *ptr); #ifndef HAVE_MALLOC_SIZE
size_t zmalloc_size(void *ptr);
#endif #endif /* __ZMALLOC_H */

zmalloc.c:

/* zmalloc - total amount of allocated memory aware version of malloc()
*
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/ #include <stdio.h>
#include <stdlib.h> /* This function provide us access to the original libc free(). This is useful
* for instance to free results obtained by backtrace_symbols(). We need
* to define this function before including zmalloc.h that may shadow the
* free implementation if we use jemalloc or another non standard allocator. */
void zlibc_free(void *ptr) {
free(ptr);
} #include <string.h>
#include <pthread.h>
#include "config.h"
#include "zmalloc.h" #ifdef HAVE_MALLOC_SIZE
#define PREFIX_SIZE (0)
#else
#if defined(__sun) || defined(__sparc) || defined(__sparc__)
#define PREFIX_SIZE (sizeof(long long))
#else
#define PREFIX_SIZE (sizeof(size_t))
#endif
#endif /* Explicitly override malloc/free etc when using tcmalloc. */
#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 #ifdef 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))
#else
#define update_zmalloc_stat_add(__n) do { \
pthread_mutex_lock(&used_memory_mutex); \
used_memory += (__n); \
pthread_mutex_unlock(&used_memory_mutex); \
} while() #define update_zmalloc_stat_sub(__n) do { \
pthread_mutex_lock(&used_memory_mutex); \
used_memory -= (__n); \
pthread_mutex_unlock(&used_memory_mutex); \
} while() #endif #define update_zmalloc_stat_alloc(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-)) _n += sizeof(long)-(_n&(sizeof(long)-)); \
if (zmalloc_thread_safe) { \
update_zmalloc_stat_add(_n); \
} else { \
used_memory += _n; \
} \
} while() #define update_zmalloc_stat_free(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-)) _n += sizeof(long)-(_n&(sizeof(long)-)); \
if (zmalloc_thread_safe) { \
update_zmalloc_stat_sub(_n); \
} else { \
used_memory -= _n; \
} \
} while() static size_t used_memory = ;
static int zmalloc_thread_safe = ;
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER; static void zmalloc_default_oom(size_t size) {
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
size);
fflush(stderr);
abort();
} static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom; 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;
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)ptr+PREFIX_SIZE;
#endif
} void *zcalloc(size_t size) {
void *ptr = calloc(, 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;
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)ptr+PREFIX_SIZE;
#endif
} void *zrealloc(void *ptr, size_t size) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
#endif
size_t oldsize;
void *newptr; if (ptr == NULL) return zmalloc(size);
#ifdef HAVE_MALLOC_SIZE
oldsize = zmalloc_size(ptr);
newptr = realloc(ptr,size);
if (!newptr) zmalloc_oom_handler(size); update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(zmalloc_size(newptr));
return newptr;
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
newptr = realloc(realptr,size+PREFIX_SIZE);
if (!newptr) zmalloc_oom_handler(size); *((size_t*)newptr) = size;
update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(size);
return (char*)newptr+PREFIX_SIZE;
#endif
} /* Provide zmalloc_size() for systems where this function is not provided by
* malloc itself, given that in that case we store a header with this
* information as the first bytes of every allocation. */
#ifndef HAVE_MALLOC_SIZE
size_t zmalloc_size(void *ptr) {
void *realptr = (char*)ptr-PREFIX_SIZE;
size_t size = *((size_t*)realptr);
/* Assume at least that all the allocations are padded at sizeof(long) by
* the underlying allocator. */
if (size&(sizeof(long)-)) size += sizeof(long)-(size&(sizeof(long)-));
return size+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
} char *zstrdup(const char *s) {
size_t l = strlen(s)+;
char *p = zmalloc(l); memcpy(p,s,l);
return p;
} size_t zmalloc_used_memory(void) {
size_t um; if (zmalloc_thread_safe) {
#ifdef HAVE_ATOMIC
um = __sync_add_and_fetch(&used_memory, );
#else
pthread_mutex_lock(&used_memory_mutex);
um = used_memory;
pthread_mutex_unlock(&used_memory_mutex);
#endif
}
else {
um = used_memory;
} return um;
} void zmalloc_enable_thread_safeness(void) {
zmalloc_thread_safe = ;
} void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {
zmalloc_oom_handler = oom_handler;
} /* Get the RSS information in an OS-specific way.
*
* WARNING: the function zmalloc_get_rss() is not designed to be fast
* and may not be called in the busy loops where Redis tries to release
* memory expiring or swapping out objects.
*
* For this kind of "fast RSS reporting" usages use instead the
* function RedisEstimateRSS() that is a much faster (and less precise)
* version of the function. */ #if defined(HAVE_PROC_STAT)
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> size_t zmalloc_get_rss(void) {
int page = sysconf(_SC_PAGESIZE);
size_t rss;
char buf[];
char filename[];
int fd, count;
char *p, *x; snprintf(filename,,"/proc/%d/stat",getpid());
if ((fd = open(filename,O_RDONLY)) == -) return ;
if (read(fd,buf,) <= ) {
close(fd);
return ;
}
close(fd); p = buf;
count = ; /* RSS is the 24th field in /proc/<pid>/stat */
while(p && count--) {
p = strchr(p,' ');
if (p) p++;
}
if (!p) return ;
x = strchr(p,' ');
if (!x) return ;
*x = '\0'; rss = strtoll(p,NULL,);
rss *= page;
return rss;
}
#elif defined(HAVE_TASKINFO)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/task.h>
#include <mach/mach_init.h> size_t zmalloc_get_rss(void) {
task_t task = MACH_PORT_NULL;
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; if (task_for_pid(current_task(), getpid(), &task) != KERN_SUCCESS)
return ;
task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count); return t_info.resident_size;
}
#else
size_t zmalloc_get_rss(void) {
/* If we can't get the RSS in an OS-specific way for this system just
* return the memory usage we estimated in zmalloc()..
*
* Fragmentation will appear to be always 1 (no fragmentation)
* of course... */
return zmalloc_used_memory();
}
#endif /* Fragmentation = RSS / allocated-bytes */
float zmalloc_get_fragmentation_ratio(size_t rss) {
return (float)rss/zmalloc_used_memory();
} #if defined(HAVE_PROC_SMAPS)
size_t zmalloc_get_private_dirty(void) {
char line[];
size_t pd = ;
FILE *fp = fopen("/proc/self/smaps","r"); if (!fp) return ;
while(fgets(line,sizeof(line),fp) != NULL) {
if (strncmp(line,"Private_Dirty:",) == ) {
char *p = strchr(line,'k');
if (p) {
*p = '\0';
pd += strtol(line+,NULL,) * ;
}
}
}
fclose(fp);
return pd;
}
#else
size_t zmalloc_get_private_dirty(void) {
return ;
}
#endif

 

Redis 内存管理 源码分析的更多相关文章

  1. Redis网络模型的源码分析

    Redis的网络模型是基于I/O多路复用程序来实现的.源码中包含四种多路复用函数库epoll.select.evport.kqueue.在程序编译时会根据系统自动选择这四种库其中之一.下面以epoll ...

  2. Redis之ziplist源码分析

    一.ziplist简介 从上一篇分析我们知道quicklist的底层存储使用了ziplist(压缩列表),由于压缩列表本身也有不少内容,所以重新开了一篇,在正式源码之前,还是先看下ziplist的特点 ...

  3. Redis网络库源码分析(1)之介绍篇

    一.前言 Redis网络库是一个单线程EPOLL模型的网络库,和Memcached使用的libevent相比,它没有那么庞大,代码一共2000多行,因此比较容易分析.其实网上已经有非常多有关这个网络库 ...

  4. Redis 数据结构-字符串源码分析

    相关文章 Redis 初探-安装与使用 Redis常用指令 本文将从以下几个部分进行介绍 1.前言 2.常用命令 3.字符串结构 4.字符串实现 5.命令是如果操作字符串的 前言 平时在使用 Redi ...

  5. Redis之quicklist源码分析

    一.quicklist简介 Redis列表是简单的字符串列表,按照插入顺序排序.你可以添加一个元素到列表的头部(左边)或者尾部(右边). 一个列表最多可以包含 232 - 1 个元素 (4294967 ...

  6. Redis事件库源码分析

    由于老大在新项目中使用redis的事件库代替了libevent,我也趁着机会读了一遍redis的事件库代码,第一次读到“优美,让人愉快”的代码,加之用xmind制作的类图非常帅,所以留文纪念. Red ...

  7. Redis网络库源码分析(3)之ae.c

    一.aeCreateEventLoop & aeCreateFileEvent 上一篇文章中,我们已经将服务器启动,只是其中有些细节我们跳过了,比如aeCreateEventLoop函数到底做 ...

  8. Redis学习——链表源码分析

    0. 前言 Redis 中的链表是以通用链表的形式实现的,而对于链表的用途来说,主要的功能就是增删改查,所以对于查找来说,redis其提供了一个match函数指针,用户负责实现其具体的匹配操作,从而实 ...

  9. 第10课:[实战] Redis 网络通信模块源码分析(3)

    redis-server 接收到客户端的第一条命令 redis-cli 给 redis-server 发送的第一条数据是 *1\r\n\$7\r\nCOMMAND\r\n .我们来看下对于这条数据如何 ...

随机推荐

  1. C# 实现敏感词过滤

    实现 该 敏感词过滤 采用的是 DFA算法,参考文章:https://blog.csdn.net/chenssy/article/details/26961957 具体 实现 步骤 如下: 第一步,构 ...

  2. NopCommerce源代码分析之用户验证和权限管理

    目录 1.  介绍 2.  UML 2.1  实体类UML图 2.2  业务相关UML图 3.  核心代码分析 3.1  实体类源代码 3.2  业务相关源代码 3.3  相关控制器源代码 3.4  ...

  3. 钉钉企业内部H5微应用开发

    企业内部H5微应用开发 分为 服务端API和前端API的开发,主要涉及到进入应用免登流程和JSAPI鉴权. JSAPI鉴权开发步骤: 1.创建H5微应用 登入钉钉开放平台(https://open-d ...

  4. ASP.NET Core系列:JWT身份认证

    1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...

  5. spring cloud 框架源码 activiti工作流 vue.js html 跨域 前后分离 springboot

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

  6. Outlook API

    1.Outlook简介 若要从Outlook 外控制Outlook对象,必须在编写代码的工程中建立对Outlook对象库的引用. 1.1  Outlook Application说明: 代表整个Mic ...

  7. vue全家桶项目应用断断续续的记录

    一.引用axios插件报错 axios使用文档 Cannot read property 'protocol' of undefined 解决方法:在mainjs文件中把axios引入vue的原型函数 ...

  8. 【餐厅】 What kind of food would you like to eat tonight?

    核心句型 What kind of food would you like to eat tonight? 你今晚想吃哪种菜? What would you like to eat ? 你想吃什么? ...

  9. robotframework-post request请求携带上一个请求返回的cookie

    公司的接口服务需要先登录,获取服务端的cookie后,在后续的请求中携带这个cookie才能够访问 在尝试用RF工具进行自动化接口测试时,发现先访问登录接口之后,接着请求其他接口时没有自动携带上次请求 ...

  10. docker 持久化存储

    1.data Volume  mysql5.7:dockerfile FROM debian:stretch-slim # add our user and group first to make s ...