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();


 

posted on 2019-07-23 10:13  长岛的雪  阅读(222)  评论(0编辑  收藏  举报