设为首页 收藏本站
查看: 944|回复: 0

[经验分享] 【redis源码】(一)Zmalloc

[复制链接]
累计签到:2 天
连续签到:2 天
发表于 2015-7-20 11:00:01 | 显示全部楼层 |阅读模式
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[4096];
193:      char filename[256];
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、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-88640-1-1.html 上篇帖子: ServiceStack.Redis常用操作 下篇帖子: redis cluster 集群
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表