redis内存管理代码注释

来源:互联网 发布:知鱼之乐 编辑:程序博客网 时间:2024/06/04 20:01

zmalloc.h

[cpp] view plaincopy
  1. /* zmalloc - total amount of allocated memory aware version of malloc() 
  2.  * 
  3.  * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com> 
  4.  * All rights reserved. 
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without 
  7.  * modification, are permitted provided that the following conditions are met: 
  8.  * 
  9.  *   * Redistributions of source code must retain the above copyright notice, 
  10.  *     this list of conditions and the following disclaimer. 
  11.  *   * Redistributions in binary form must reproduce the above copyright 
  12.  *     notice, this list of conditions and the following disclaimer in the 
  13.  *     documentation and/or other materials provided with the distribution. 
  14.  *   * Neither the name of Redis nor the names of its contributors may be used 
  15.  *     to endorse or promote products derived from this software without 
  16.  *     specific prior written permission. 
  17.  * 
  18.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
  19.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  20.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  21.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  22.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  23.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  24.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  25.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  26.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  27.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  28.  * POSSIBILITY OF SUCH DAMAGE. 
  29.  */  
  30.   
  31. #ifndef __ZMALLOC_H  
  32. #define __ZMALLOC_H  
  33.   
  34. /* Double expansion needed for stringification of macro values. */  
  35. #define __xstr(s) __str(s)  
  36. #define __str(s) #s  
  37.   
  38. //TCMALLOC内存分配器  
  39. #if defined(USE_TCMALLOC)  
  40. #define ZMALLOC_LIB ("tcmalloc-" __xstr(TC_VERSION_MAJOR) "." __xstr(TC_VERSION_MINOR))  
  41. #include <google/tcmalloc.h>  
  42. #if (TC_VERSION_MAJOR == 1 && TC_VERSION_MINOR >= 6) || (TC_VERSION_MAJOR > 1)//版本要求  
  43. #define HAVE_MALLOC_SIZE 1          //TCMALLOC内置获取分配内存空间大小的函数  
  44. #define zmalloc_size(p) tc_malloc_size(p)  
  45. #else                               //编译出错处理  
  46. #error "Newer version of tcmalloc required"   
  47. #endif  
  48.   
  49. #elif defined(USE_JEMALLOC)  
  50. #define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX))  
  51. #include <jemalloc/jemalloc.h>  
  52. #if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)  
  53. #define HAVE_MALLOC_SIZE 1  
  54. #define zmalloc_size(p) je_malloc_usable_size(p)  
  55. #else  
  56. #error "Newer version of jemalloc required"  
  57. #endif  
  58.   
  59. #elif defined(__APPLE__)  
  60. #include <malloc/malloc.h>  
  61. #define HAVE_MALLOC_SIZE 1  
  62. #define zmalloc_size(p) malloc_size(p)  
  63. #endif  
  64.   
  65. //使用默认libc分配器  
  66. #ifndef ZMALLOC_LIB  
  67. #define ZMALLOC_LIB "libc"  
  68. #endif  
  69.   
  70. void *zmalloc(size_t size);  
  71. void *zcalloc(size_t size);  
  72. void *zrealloc(void *ptr, size_t size);  
  73. void zfree(void *ptr);  
  74. char *zstrdup(const char *s);  
  75. size_t zmalloc_used_memory(void);  
  76. void zmalloc_enable_thread_safeness(void);  
  77. void zmalloc_set_oom_handler(void (*oom_handler)(size_t));  
  78. float zmalloc_get_fragmentation_ratio(size_t rss);  
  79. size_t zmalloc_get_rss(void);  
  80. size_t zmalloc_get_private_dirty(void);  
  81. size_t zmalloc_get_smap_bytes_by_field(char *field);  
  82. void zlibc_free(void *ptr);  
  83.   
  84. #ifndef HAVE_MALLOC_SIZE  
  85. size_t zmalloc_size(void *ptr);  
  86. #endif  
  87.   
  88. #endif /* __ZMALLOC_H */  

zmalloc.c

[cpp] view plaincopy
  1. /* zmalloc - total amount of allocated memory aware version of malloc() 
  2.  * 
  3.  * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com> 
  4.  * All rights reserved. 
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without 
  7.  * modification, are permitted provided that the following conditions are met: 
  8.  * 
  9.  *   * Redistributions of source code must retain the above copyright notice, 
  10.  *     this list of conditions and the following disclaimer. 
  11.  *   * Redistributions in binary form must reproduce the above copyright 
  12.  *     notice, this list of conditions and the following disclaimer in the 
  13.  *     documentation and/or other materials provided with the distribution. 
  14.  *   * Neither the name of Redis nor the names of its contributors may be used 
  15.  *     to endorse or promote products derived from this software without 
  16.  *     specific prior written permission. 
  17.  * 
  18.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
  19.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  20.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  21.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  22.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  23.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  24.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  25.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  26.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  27.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  28.  * POSSIBILITY OF SUCH DAMAGE. 
  29.  */  
  30.   
  31. #include <stdio.h>  
  32. #include <stdlib.h>  
  33.   
  34. /* This function provide us access to the original libc free(). This is useful 
  35.  * for instance to free results obtained by backtrace_symbols(). We need 
  36.  * to define this function before including zmalloc.h that may shadow the 
  37.  * free implementation if we use jemalloc or another non standard allocator. */  
  38.   
  39.  //保留了libc的free()接口,用于释放backtrace_symbols()获取的结果  
  40. void zlibc_free(void *ptr) {  
  41.     free(ptr);  
  42. }  
  43.   
  44. #include <string.h>  
  45. #include <pthread.h>  
  46. #include "config.h"  
  47. #include "zmalloc.h"  
  48.   
  49. #ifdef HAVE_MALLOC_SIZE //tc_malloc,je_malloc,Mac平台  
  50. #define PREFIX_SIZE (0)  
  51. #else  
  52. /*其他平台内存分配 
  53. **内存模型:data_size(PREFIX_SIZE)+data 
  54. **前面PREFIX_SIZE字节存储申请空间大小,后面空间为申请的内存 
  55. */  
  56. #if defined(__sun) || defined(__sparc) || defined(__sparc__)  
  57. #define PREFIX_SIZE (sizeof(long long))  
  58. #else                   //linux  
  59. #define PREFIX_SIZE (sizeof(size_t))  
  60. #endif  
  61. #endif  
  62.   
  63. /* Explicitly override malloc/free etc when using tcmalloc. */  
  64. #if defined(USE_TCMALLOC)  
  65. #define malloc(size) tc_malloc(size)  
  66. #define calloc(count,size) tc_calloc(count,size)  
  67. #define realloc(ptr,size) tc_realloc(ptr,size)  
  68. #define free(ptr) tc_free(ptr)  
  69. #elif defined(USE_JEMALLOC)  
  70. #define malloc(size) je_malloc(size)  
  71. #define calloc(count,size) je_calloc(count,size)  
  72. #define realloc(ptr,size) je_realloc(ptr,size)  
  73. #define free(ptr) je_free(ptr)  
  74. #endif  
  75.   
  76. //原子操作修改总共使用内存  
  77. #if defined(__ATOMIC_RELAXED)  
  78. #define update_zmalloc_stat_add(__n) __atomic_add_fetch(&used_memory, (__n), __ATOMIC_RELAXED)  
  79. #define update_zmalloc_stat_sub(__n) __atomic_sub_fetch(&used_memory, (__n), __ATOMIC_RELAXED)  
  80. #elif defined(HAVE_ATOMIC)  
  81. #define update_zmalloc_stat_add(__n) __sync_add_and_fetch(&used_memory, (__n))  
  82. #define update_zmalloc_stat_sub(__n) __sync_sub_and_fetch(&used_memory, (__n))  
  83. #else  
  84. #define update_zmalloc_stat_add(__n) do { \  
  85.     pthread_mutex_lock(&used_memory_mutex); \  
  86.     used_memory += (__n); \  
  87.     pthread_mutex_unlock(&used_memory_mutex); \  
  88. while(0)  
  89.   
  90. #define update_zmalloc_stat_sub(__n) do { \  
  91.     pthread_mutex_lock(&used_memory_mutex); \  
  92.     used_memory -= (__n); \  
  93.     pthread_mutex_unlock(&used_memory_mutex); \  
  94. while(0)  
  95.   
  96. #endif  
  97.   
  98. //__n是分配的内存字节,更新used_memory的值,注意long型对齐  
  99. #define update_zmalloc_stat_alloc(__n) do { \  
  100.     size_t _n = (__n); \  
  101.     if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \    //分配字节不到long型的整数倍增加至整数倍  
  102.     if (zmalloc_thread_safe) { \    //线程安全模式  
  103.         update_zmalloc_stat_add(_n); \  
  104.     } else { \                      //非线程安全模式  
  105.         used_memory += _n; \  
  106.     } \  
  107. while(0)  
  108.   
  109. //__n是释放的内存字节,更新used_memory的值,注意long型对齐  
  110. #define update_zmalloc_stat_free(__n) do { \  
  111.     size_t _n = (__n); \  
  112.     if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \  
  113.     if (zmalloc_thread_safe) { \  
  114.         update_zmalloc_stat_sub(_n); \  
  115.     } else { \  
  116.         used_memory -= _n; \  
  117.     } \  
  118. while(0)  
  119.   
  120.   
  121. static size_t used_memory = 0;          //初始时总共使用内存空间为0  
  122. static int zmalloc_thread_safe = 0;     //默认不启动线程安全模式  
  123. pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;  //定义并初始化一个互斥量  
  124.   
  125. //内存不足默认处理函数  
  126. static void zmalloc_default_oom(size_t size) {  
  127.     fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",  
  128.         size);  
  129.     fflush(stderr);  
  130.     abort();  
  131. }  
  132.   
  133. //内存不足处理函数指针,初始为默认函数  
  134. static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;  
  135.   
  136. //malloc实现内存申请函数  
  137. void *zmalloc(size_t size) {  
  138.     void *ptr = malloc(size+PREFIX_SIZE);  
  139.   
  140.     if (!ptr) zmalloc_oom_handler(size);    //申请失败调用内存不足处理函数,终止程序  
  141. #ifdef HAVE_MALLOC_SIZE                     //tc_malloc,je_malloc,Mac平台  
  142.     update_zmalloc_stat_alloc(zmalloc_size(ptr));  
  143.     return ptr;  
  144. #else                                       //其他平台  
  145.     *((size_t*)ptr) = size;  
  146.     update_zmalloc_stat_alloc(size+PREFIX_SIZE);  
  147.     return (char*)ptr+PREFIX_SIZE;  
  148. #endif  
  149. }  
  150.   
  151. //calloc实现内存释放函数  
  152. void *zcalloc(size_t size) {  
  153.     void *ptr = calloc(1, size+PREFIX_SIZE);  
  154.   
  155.     if (!ptr) zmalloc_oom_handler(size);  
  156. #ifdef HAVE_MALLOC_SIZE  
  157.     update_zmalloc_stat_alloc(zmalloc_size(ptr));  
  158.     return ptr;  
  159. #else  
  160.     *((size_t*)ptr) = size;  
  161.     update_zmalloc_stat_alloc(size+PREFIX_SIZE);  
  162.     return (char*)ptr+PREFIX_SIZE;  
  163. #endif  
  164. }  
  165.   
  166. void *zrealloc(void *ptr, size_t size) {  
  167. #ifndef HAVE_MALLOC_SIZE  
  168.     void *realptr;  
  169. #endif  
  170.     size_t oldsize;  
  171.     void *newptr;  
  172.   
  173.     if (ptr == NULL) return zmalloc(size);  
  174. #ifdef HAVE_MALLOC_SIZE  
  175.     oldsize = zmalloc_size(ptr);  
  176.     newptr = realloc(ptr,size);  
  177.     if (!newptr) zmalloc_oom_handler(size);  
  178.   
  179.     update_zmalloc_stat_free(oldsize);  
  180.     update_zmalloc_stat_alloc(zmalloc_size(newptr));  
  181.     return newptr;  
  182. #else  
  183.     realptr = (char*)ptr-PREFIX_SIZE;  
  184.     oldsize = *((size_t*)realptr);  
  185.     newptr = realloc(realptr,size+PREFIX_SIZE);  
  186.     if (!newptr) zmalloc_oom_handler(size);  
  187.   
  188.     *((size_t*)newptr) = size;  
  189.     update_zmalloc_stat_free(oldsize);  
  190.     update_zmalloc_stat_alloc(size);  
  191.     return (char*)newptr+PREFIX_SIZE;  
  192. #endif  
  193. }  
  194.   
  195. /* Provide zmalloc_size() for systems where this function is not provided by 
  196.  * malloc itself, given that in that case we store a header with this 
  197.  * information as the first bytes of every allocation. */  
  198. #ifndef HAVE_MALLOC_SIZE  
  199. size_t zmalloc_size(void *ptr) {  
  200.     void *realptr = (char*)ptr-PREFIX_SIZE;  
  201.     size_t size = *((size_t*)realptr);  
  202.     /* Assume at least that all the allocations are padded at sizeof(long) by 
  203.      * the underlying allocator. */  
  204.     //假设所有分配器分配时均使用long型对齐  
  205.     if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));  
  206.     return size+PREFIX_SIZE;  
  207. }  
  208. #endif  
  209.   
  210. //释放ptr指向的内存空间  
  211. void zfree(void *ptr) {  
  212. #ifndef HAVE_MALLOC_SIZE  
  213.     void *realptr;  
  214.     size_t oldsize;  
  215. #endif  
  216.   
  217.     if (ptr == NULL) return;  
  218. #ifdef HAVE_MALLOC_SIZE  
  219.     update_zmalloc_stat_free(zmalloc_size(ptr));  
  220.     free(ptr);  
  221. #else  
  222.     realptr = (char*)ptr-PREFIX_SIZE;  
  223.     oldsize = *((size_t*)realptr);  
  224.     update_zmalloc_stat_free(oldsize+PREFIX_SIZE);  
  225.     free(realptr);  
  226. #endif  
  227. }  
  228.   
  229. char *zstrdup(const char *s) {  
  230.     size_t l = strlen(s)+1;  
  231.     char *p = zmalloc(l);  
  232.   
  233.     memcpy(p,s,l);  
  234.     return p;  
  235. }  
  236.   
  237. //返回总共的使用内存  
  238. size_t zmalloc_used_memory(void) {  
  239.     size_t um;  
  240.   
  241.     if (zmalloc_thread_safe) {  
  242. #if defined(__ATOMIC_RELAXED) || defined(HAVE_ATOMIC)  
  243.         um = update_zmalloc_stat_add(0);  
  244. #else  
  245.         pthread_mutex_lock(&used_memory_mutex);  
  246.         um = used_memory;  
  247.         pthread_mutex_unlock(&used_memory_mutex);  
  248. #endif  
  249.     }  
  250.     else {  
  251.         um = used_memory;  
  252.     }  
  253.   
  254.     return um;  
  255. }  
  256.   
  257. //设置安全线程模式  
  258. void zmalloc_enable_thread_safeness(void) {  
  259.     zmalloc_thread_safe = 1;  
  260. }  
  261. //设置内存不足处理函数  
  262. void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {  
  263.     zmalloc_oom_handler = oom_handler;  
  264. }  
  265.   
  266. /* Get the RSS information in an OS-specific way. 
  267.  * 
  268.  * WARNING: the function zmalloc_get_rss() is not designed to be fast 
  269.  * and may not be called in the busy loops where Redis tries to release 
  270.  * memory expiring or swapping out objects. 
  271.  * 
  272.  * For this kind of "fast RSS reporting" usages use instead the 
  273.  * function RedisEstimateRSS() that is a much faster (and less precise) 
  274.  * version of the function. */  
  275.   
  276. #if defined(HAVE_PROC_STAT)  
  277. #include <unistd.h>  
  278. #include <sys/types.h>  
  279. #include <sys/stat.h>  
  280. #include <fcntl.h>  
  281. //获取当前进程的驻留集大小  
  282. size_t zmalloc_get_rss(void) {  
  283.     int page = sysconf(_SC_PAGESIZE);   //获取page大小  
  284.     size_t rss;  
  285.     char buf[4096];  
  286.     char filename[256];  
  287.     int fd, count;  
  288.     char *p, *x;  
  289.   
  290.     snprintf(filename,256,"/proc/%d/stat",getpid());  
  291.     if ((fd = open(filename,O_RDONLY)) == -1) return 0;  
  292.     if (read(fd,buf,4096) <= 0) {  
  293.         close(fd);  
  294.         return 0;  
  295.     }  
  296.     close(fd);  
  297.   
  298.     p = buf;  
  299.     count = 23; /* RSS is the 24th field in /proc/<pid>/stat */  
  300.     while(p && count--) {  
  301.         p = strchr(p,' ');  
  302.         if (p) p++;  
  303.     }  
  304.     if (!p) return 0;  
  305.     x = strchr(p,' ');  
  306.     if (!x) return 0;  
  307.     *x = '\0';  
  308.   
  309.     rss = strtoll(p,NULL,10);  
  310.     rss *= page;  
  311.     return rss;  
  312. }  
  313. #elif defined(HAVE_TASKINFO)  
  314. #include <unistd.h>  
  315. #include <stdio.h>  
  316. #include <stdlib.h>  
  317. #include <sys/types.h>  
  318. #include <sys/sysctl.h>  
  319. #include <mach/task.h>  
  320. #include <mach/mach_init.h>  
  321.   
  322. size_t zmalloc_get_rss(void) {  
  323.     task_t task = MACH_PORT_NULL;  
  324.     struct task_basic_info t_info;  
  325.     mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;  
  326.   
  327.     if (task_for_pid(current_task(), getpid(), &task) != KERN_SUCCESS)  
  328.         return 0;  
  329.     task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);  
  330.   
  331.     return t_info.resident_size;  
  332. }  
  333. #else  
  334. size_t zmalloc_get_rss(void) {  
  335.     /* If we can't get the RSS in an OS-specific way for this system just 
  336.      * return the memory usage we estimated in zmalloc().. 
  337.      * 
  338.      * Fragmentation will appear to be always 1 (no fragmentation) 
  339.      * of course... */  
  340.     return zmalloc_used_memory();  
  341. }  
  342. #endif  
  343.   
  344. /* Fragmentation = RSS / allocated-bytes */  
  345. //计算碎片率  
  346. float zmalloc_get_fragmentation_ratio(size_t rss) {  
  347.     return (float)rss/zmalloc_used_memory();  
  348. }  
  349.   
  350. /* Get the sum of the specified field (converted form kb to bytes) in 
  351.  * /proc/self/smaps. The field must be specified with trailing ":" as it 
  352.  * apperas in the smaps output. 
  353.  * 
  354.  * Example: zmalloc_get_smap_bytes_by_field("Rss:"); 
  355.  */  
  356.   
  357. #if defined(HAVE_PROC_SMAPS)  
  358. size_t zmalloc_get_smap_bytes_by_field(char *field) {  
  359.     char line[1024];  
  360.     size_t bytes = 0;  
  361.     FILE *fp = fopen("/proc/self/smaps","r");  
  362.     int flen = strlen(field);  
  363.   
  364.     if (!fp) return 0;  
  365.     while(fgets(line,sizeof(line),fp) != NULL) {  
  366.         if (strncmp(line,field,flen) == 0) {  
  367.             char *p = strchr(line,'k');  
  368.             if (p) {  
  369.                 *p = '\0';  
  370.                 bytes += strtol(line+flen,NULL,10) * 1024;  
  371.             }  
  372.         }  
  373.     }  
  374.     fclose(fp);  
  375.     return bytes;  
  376. }  
  377. #else  
  378. size_t zmalloc_get_smap_bytes_by_field(char *field) {  
  379.     ((void) field);  
  380.     return 0;  
  381. }  
  382. #endif  
  383.   
  384. //获取Private_Dirty大小,RSS=Shared_Clean+Shared_Dirty+Private_Clean+Private_Dirty  
  385. //Shared_Clean:引用大于1,未被修改  
  386. //Shared_Dirty:引用大于1,被修改  
  387. //Private_Clean:引用等于1,未被修改  
  388. //Private_Dirty:引用等于1,被修改  
  389. size_t zmalloc_get_private_dirty(void) {  
  390.     return zmalloc_get_smap_bytes_by_field("Private_Dirty:");  
  391. }  
0 0