redis源码分析(1)内存管理zmalloc
总体来说,zmalloc根据平台不同加了一层封装,可以维护已申请的总共堆内存的大小。
PREFIX_SIZE是一个预留量,用于存储当前分配内存的大小。
在linux下,PREFIX_SIZE大小为8
1.分配时会多分配PREFIX_SIZE。
2.将多分配出来的地方写入大小,但是这个大小不包括PREFIX_SIZE本身。
3.返回malloc分配的内存地址往右偏移PREFIX_SIZE的大小。
tcmalloc 和 Mac平台下的 malloc 函数族提供了计算已分配空间大小的函数(分别是tcmallocsize和mallocsize),但是linux平台下并没有。
在free的时候没有办法通过函数获得内存大小,所以需要维护这个变量以计算总共分配的堆内存的大小。
sizeof(long)-1=7
假设内存地址 ...........000后三位为000,&上000000111的结果为0,说明内存8字节对齐了。
if(_n&7)如果为真的话,说明内存没有8字节对齐。如果内存大小不是8的倍数,就加上相应的偏移量使之变成8的倍数。
刚开始没注意,这个函数的参数__n是地址大小而非地址,因为malloc保证分配的内存是8的倍数,如果你要分配的内存不是8的倍数,那么malloc就会多分配一点,来凑成8的倍数。所以这个函数判断分配内存的大小是否为8的倍数,来精确地统计已分配的内存。
这个函数也是功能类似。
size_t zmalloc_get_rss(void) { int page = sysconf(_SC_PAGESIZE); size_t rss; char buf[4096]; char filename[256]; int fd, count; char *p, *x; snprintf(filename,256,"/proc/%d/stat",getpid()); if ((fd = open(filename,O_RDONLY)) == -1) return 0; if (read(fd,buf,4096) <= 0) { close(fd); return 0; } close(fd); p = buf; count = 23; /* RSS is the 24th field in /proc/<pid>/stat */ while(p && count--) { p = strchr(p,' '); if (p) p++; } if (!p) return 0; x = strchr(p,' '); if (!x) return 0; *x = '\0'; rss = strtoll(p,NULL,10); 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 0; 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
rss全称为Resident Set Size,指实际使用物理内存(包含共享库占用的内存),centos下测试 直接是 什么都没定义,所以return zmalloc_used_memory();暂时先不去管
以上测试程序输出为空,所以linux下zmalloc_get_rss返回的是zmalloc_used_memory();