haishi 发表于 2015-7-20 11:00:01

【redis源码】(一)Zmalloc

Zmalloc是redis的基础,redis源码的阅读从Zmalloc开始,相信这个一个愉快的旅程,读优秀的代码,就像听音乐~ 好了开始吧



头文件 Zmalloc.h,没什么好说的,声明了一些函数,具体的实现见Zmalloc.c






   1:#ifndef _ZMALLOC_H
   2:#define _ZMALLOC_H
   3:   
   4:void *zmalloc(size_t size);
   5:void *zcalloc(size_t size);
   6:void *zrealloc(void *ptr, size_t size);
   7:void zfree(void *ptr);
   8:char *zstrdup(const char *s);
   9:size_t zmalloc_used_memory(void);
10:void zmalloc_enable_thread_safeness(void);
11:float zmalloc_get_fragmentation_ratio(void);
12:size_t zmalloc_get_rss(void);
13:   
14:#endif /* _ZMALLOC_H */

Zmalloc.c


   1:#include
   2:#include
   3:#include
   4:#include
   5:#include "config.h"
   6:#include "zmalloc.h"
   7:   
   8:   
   9://PREFIX_SIZE用来记录malloc拿到的内存块的size,如果使用了google的tcmalloc库或者苹果的环境,可以使用系统函数获得内存块的大小,就不用这个区域来记录
10:#ifdef HAVE_MALLOC_SIZE
11:#define PREFIX_SIZE (0)
12:#else
13:#if defined(__sun)
14:#define PREFIX_SIZE (sizeof(long long))
15:#else
16:#define PREFIX_SIZE (sizeof(size_t))
17:#endif
18:#endif
19:   
20:/* Explicitly override malloc/free etc when using tcmalloc. */
21://使用google的tcmalloc库作为底层的malloc函数
22:#if defined(USE_TCMALLOC)
23:#define malloc(size) tc_malloc(size)
24:#define calloc(count,size) tc_calloc(count,size)
25:#define realloc(ptr,size) tc_realloc(ptr,size)
26:#define free(ptr) tc_free(ptr)
27:#endif
28:   
29://Zmalloc会在全局静态变量里记录已经申请的内存大小 static size_t used_memory = 0;
30:#define update_zmalloc_stat_alloc(__n,__size) do { \
31:      size_t _n = (__n); \
32:      //将记录的内存大小补齐sizeof(long)的倍数
33:      if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
34:      if (zmalloc_thread_safe) { \
35:          pthread_mutex_lock(&used_memory_mutex);\
36:          used_memory += _n; \
37:          pthread_mutex_unlock(&used_memory_mutex); \
38:      } else { \
39:          used_memory += _n; \
40:      } \
41:} while(0)
42:   
43:#define update_zmalloc_stat_free(__n) do { \
44:      size_t _n = (__n); \
45:      if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
46:      if (zmalloc_thread_safe) { \
47:          pthread_mutex_lock(&used_memory_mutex);\
48:          used_memory -= _n; \
49:          pthread_mutex_unlock(&used_memory_mutex); \
50:      } else { \
51:          used_memory -= _n; \
52:      } \
53:} while(0)
54:   
55:static size_t used_memory = 0;
56:static int zmalloc_thread_safe = 0;
57:pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
58:   
59://如果申请内存失败,发送SIGABRT信号通知程序
60:static void zmalloc_oom(size_t size) {
61:      fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
62:          size);
63:      fflush(stderr);
64:      abort();
65:}
66:   
67://申请size大bytes的内存区域
68:void *zmalloc(size_t size) {
69:      //实际申请size+PREFIX_SIZE大小的内存空间,其中,前PREFIX_SIZE的空间用来记录内存块大小
70:      void *ptr = malloc(size+PREFIX_SIZE);
71:   
72:      if (!ptr) zmalloc_oom(size);
73:#ifdef HAVE_MALLOC_SIZE
74:      update_zmalloc_stat_alloc(redis_malloc_size(ptr),size);
75:      return ptr;
76:#else
77:      //记录内存块大小
78:      *((size_t*)ptr) = size;
79:      update_zmalloc_stat_alloc(size+PREFIX_SIZE,size);
80:      return (char*)ptr+PREFIX_SIZE;
81:#endif
82:}
83:   
84://申请size个sizeof(byte)大的内存区域
85:void *zcalloc(size_t size) {
86:      void *ptr = calloc(1, size+PREFIX_SIZE);
87:   
88:      if (!ptr) zmalloc_oom(size);
89:#ifdef HAVE_MALLOC_SIZE
90:      update_zmalloc_stat_alloc(redis_malloc_size(ptr),size);
91:      return ptr;
92:#else
93:      *((size_t*)ptr) = size;
94:      update_zmalloc_stat_alloc(size+PREFIX_SIZE,size);
95:      return (char*)ptr+PREFIX_SIZE;
96:#endif
97:}
98:   
99://重新分配size大小的内存
100:void *zrealloc(void *ptr, size_t size) {
101:#ifndef HAVE_MALLOC_SIZE
102:      void *realptr;
103:#endif
104:      size_t oldsize;
105:      void *newptr;
106:   
107:      if (ptr == NULL) return zmalloc(size);
108:#ifdef HAVE_MALLOC_SIZE
109:      oldsize = redis_malloc_size(ptr);
110:      newptr = realloc(ptr,size);
111:      if (!newptr) zmalloc_oom(size);
112:   
113:      update_zmalloc_stat_free(oldsize);
114:      update_zmalloc_stat_alloc(redis_malloc_size(newptr),size);
115:      return newptr;
116:#else
117:      realptr = (char*)ptr-PREFIX_SIZE;
118:      oldsize = *((size_t*)realptr);
119:      newptr = realloc(realptr,size+PREFIX_SIZE);
120:      if (!newptr) zmalloc_oom(size);
121:   
122:      *((size_t*)newptr) = size;
123:      update_zmalloc_stat_free(oldsize);
124:      update_zmalloc_stat_alloc(size,size);
125:      return (char*)newptr+PREFIX_SIZE;
126:#endif
127:}
128:   
129://释放ptr开始内存块,与zmalloc,zcalloc,zrealloc配对
130:void zfree(void *ptr) {
131:#ifndef HAVE_MALLOC_SIZE
132:      void *realptr;
133:      size_t oldsize;
134:#endif
135:   
136:      if (ptr == NULL) return;
137:#ifdef HAVE_MALLOC_SIZE
138:      update_zmalloc_stat_free(redis_malloc_size(ptr));
139:      free(ptr);
140:#else
141:      realptr = (char*)ptr-PREFIX_SIZE;
142:      oldsize = *((size_t*)realptr);
143:      update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
144:      free(realptr);
145:#endif
146:}
147:   
148://复制字符串
149:char *zstrdup(const char *s) {
150:      size_t l = strlen(s)+1;
151:      char *p = zmalloc(l);
152:   
153:      memcpy(p,s,l);
154:      return p;
155:}
156:   
157://得到已申请内存块总大小
158:size_t zmalloc_used_memory(void) {
159:      size_t um;
160:   
161:      if (zmalloc_thread_safe) pthread_mutex_lock(&used_memory_mutex);
162:      um = used_memory;
163:      if (zmalloc_thread_safe) pthread_mutex_unlock(&used_memory_mutex);
164:      return um;
165:}
166:   
167://设置线程安全zmalloc开关,即操作前lock
168:void zmalloc_enable_thread_safeness(void) {
169:      zmalloc_thread_safe = 1;
170:}
171:   
172:/* Get the RSS information in an OS-specific way.
173:   *
174:   * WARNING: the function zmalloc_get_rss() is not designed to be fast
175:   * and may not be called in the busy loops where Redis tries to release
176:   * memory expiring or swapping out objects.
177:   *
178:   * For this kind of "fast RSS reporting" usages use instead the
179:   * function RedisEstimateRSS() that is a much faster (and less precise)
180:   * version of the funciton. */
181:   
182:#if defined(HAVE_PROCFS)
183:#include
184:#include
185:#include
186:#include
187:   
188:size_t zmalloc_get_rss(void) {
189:      //获取runtime的信息,获取byte为单位的page大小
190:      int page = sysconf(_SC_PAGESIZE);
191:      size_t rss;
192:      char buf;
193:      char filename;
194:      int fd, count;
195:      char *p, *x;
196:   
197:      snprintf(filename,256,"/proc/%d/stat",getpid());
198:      if ((fd = open(filename,O_RDONLY)) == -1) return 0;
199:      if (read(fd,buf,4096)
页: [1]
查看完整版本: 【redis源码】(一)Zmalloc