溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Redis在內(nèi)存分配和使用統(tǒng)計(jì)的技巧有哪些

發(fā)布時(shí)間:2022-01-15 17:19:54 來源:億速云 閱讀:174 作者:iii 欄目:數(shù)據(jù)庫

本篇內(nèi)容主要講解“Redis在內(nèi)存分配和使用統(tǒng)計(jì)的技巧有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Redis在內(nèi)存分配和使用統(tǒng)計(jì)的技巧有哪些”吧!

  具體來說就是:

  若系統(tǒng)中存在Google的TC_MALLOC庫,則使用tc_malloc一族函數(shù)代替原本的malloc一族函數(shù)。

  若當(dāng)前系統(tǒng)是Mac系統(tǒng),則使用中的內(nèi)存分配函數(shù)。

  其他情況,在每一段分配好的空間前頭,同時(shí)多分配一個(gè)定長的字段,用來記錄分配的空間大小。

  源代碼分別在 config.h 和 zmalloc.c 中:

  /* config.h */

  #if defined(USE_TCMALLOC)

  #include

  #if TC_VERSION_MAJOR >= 1 && TC_VERSION_MINOR >= 6

  #define HAVE_MALLOC_SIZE 1

  #define redis_malloc_size(p) tc_malloc_size(p)

  #endif

  #elif defined(__APPLE__)

  #include

  #define HAVE_MALLOC_SIZE 1

  #define redis_malloc_size(p) malloc_size(p)

  #endif

  /* zmalloc.c */

  #ifdef HAVE_MALLOC_SIZE

  #define PREFIX_SIZE (0)

  #else

  #if defined(__sun)

  #define PREFIX_SIZE (sizeof(long long))

  #else

  #define PREFIX_SIZE (sizeof(size_t))

  #endif

  #endif

  因?yàn)?tc_malloc 和 Mac平臺(tái)下的 malloc 函數(shù)族提供了計(jì)算已分配空間大小的函數(shù)(分別是tc_malloc_size和malloc_size),所以就不需要單獨(dú)分配一段空間記錄大小了。而針對(duì)linux和sun平臺(tái)則要記錄分配空間大小。對(duì)于linux,使用sizeof(size_t)定長字段記錄;對(duì)于sun os,使用sizeof(long long)定長字段記錄。也就是上邊源碼中的 PREFIX_SIZE 宏。

  那么這個(gè)記錄有什么用呢?答案是,為了統(tǒng)計(jì)當(dāng)前進(jìn)程到底占用了多少內(nèi)存。在 zmalloc.c 中,有這樣一個(gè)靜態(tài)變量:

  static size_t used_memory = 0;

  它記錄了進(jìn)程當(dāng)前占用的內(nèi)存總數(shù)。每當(dāng)要分配內(nèi)存或是釋放內(nèi)存的時(shí)候,都要更新這個(gè)變量。因?yàn)榉峙鋬?nèi)存的時(shí)候,可以明確知道要分配多少內(nèi)存。但是釋放內(nèi)存的時(shí)候,(對(duì)于未提供malloc_size函數(shù)的平臺(tái))僅通過指向要釋放內(nèi)存的指針是不能知道釋放的空間到底有多大的。這個(gè)時(shí)候,上邊提到的PREFIX_SIZE定長字段就起作用了,可以通過其中記錄的內(nèi)容得到空間的大小。zmalloc函數(shù)如下(去掉無關(guān)代碼):

  void *zmalloc(size_t size) {

  void *ptr = malloc(size+PREFIX_SIZE);

  if (!ptr) zmalloc_oom(size);

  *((size_t*)ptr) = size;

  update_zmalloc_stat_alloc(size+PREFIX_SIZE,size);

  return (char*)ptr+PREFIX_SIZE;

  #endif

  }

  Redis在內(nèi)存分配和使用統(tǒng)計(jì)方面有哪些技巧

  看到在分配空間的時(shí)候,空間大小是size+PREFIX_SIZE。對(duì)于mac系統(tǒng)或是使用tc_malloc的情況,PREFIX_SIZE 為0。之后將ptr指針指向的空間前size_t中記錄分配空間的大小。最后返回的是越過記錄區(qū)的指針。zfree函數(shù)類似(去掉無關(guān)代碼):

  void zfree(void *ptr) {

  void *realptr;

  size_t oldsize;

  if (ptr == NULL) return;

  realptr = (char*)ptr-PREFIX_SIZE;

  oldsize = *((size_t*)realptr);

  update_zmalloc_stat_free(oldsize+PREFIX_SIZE);

  free(realptr);

  #endif

  }

  先將指針向前移動(dòng)PREFIX_SIZE,然后取出分配空間時(shí)保存的空間長度。最后free整個(gè)空間。

  update_zmalloc_stat_alloc(__n,__size) 和 update_zmalloc_stat_free(__n) 這兩個(gè)宏負(fù)責(zé)在分配內(nèi)存或是釋放內(nèi)存的時(shí)候更新used_memory變量。定義成宏主要是出于效率上的考慮。將其還原為函數(shù),就是下邊這個(gè)樣子:

  void update_zmalloc_stat_alloc(__n,__size)

  {

  do {

  size_t _n = (__n);

  size_t _stat_slot = (__size < ZMALLOC_MAX_ALLOC_STAT) ? __size : ZMALLOC_MAX_ALLOC_STAT;   if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1));   if (zmalloc_thread_safe) {   pthread_mutex_lock(&used_memory_mutex);   used_memory += _n;   zmalloc_allocations[_stat_slot]++;   pthread_mutex_unlock(&used_memory_mutex);   } else {   used_memory += _n;   zmalloc_allocations[_stat_slot]++;   }   } while(0)   }   void update_zmalloc_stat_free(__n)   {   do {   size_t _n = (__n);   if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1));   if (zmalloc_thread_safe) {   pthread_mutex_lock(&used_memory_mutex);   used_memory -= _n;   pthread_mutex_unlock(&used_memory_mutex);   } else {   used_memory -= _n;   }   } while(0)   }   代碼中除了更新used_memory變量外,還有幾個(gè)要關(guān)注的地方:   先對(duì)_n的低位向上取整,最后_n變?yōu)閟izeof(long)的倍數(shù),比如對(duì)于32位系統(tǒng),sizeof(long) == 100(二進(jìn)制),_n向上取整之后,低兩位都變?yōu)?。   如果進(jìn)程中有多個(gè)線程存在,則在更新變量的時(shí)候要加鎖。   在zmalloc函數(shù)中還有一個(gè)統(tǒng)計(jì)量要更新:zmalloc_allocations[]。   在 zmalloc.c 中,zmalloc_allocations是這樣定義的:   size_t zmalloc_allocations[ZMALLOC_MAX_ALLOC_STAT+1];   其作用是統(tǒng)計(jì)程序分配內(nèi)存時(shí),對(duì)不同大小空間的請(qǐng)求次數(shù)。統(tǒng)計(jì)的空間范圍從1字節(jié)到256字節(jié),大于256字節(jié)的算為256。統(tǒng)計(jì)結(jié)果通過調(diào)用 zmalloc_allocations_for_size 函數(shù)返回:   size_t zmalloc_allocations_for_size(size_t size) {   if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;

  return zmalloc_allocations[size];

  }

  另一個(gè)對(duì)內(nèi)存使用量的統(tǒng)計(jì)通過調(diào)用 zmalloc_used_memory 函數(shù)返回:

  size_t zmalloc_used_memory(void) {

  size_t um;

  if (zmalloc_thread_safe) pthread_mutex_lock(&used_memory_mutex);

  um = used_memory;

  if (zmalloc_thread_safe) pthread_mutex_unlock(&used_memory_mutex);

  return um;

  }

  另外 zmalloc.c 中,還針對(duì)不同的系統(tǒng)實(shí)現(xiàn)了 zmalloc_get_rss 函數(shù),在linux系統(tǒng)中是通過讀取/proc/$pid/stat文件獲得系統(tǒng)統(tǒng)計(jì)的內(nèi)存占用量。

到此,相信大家對(duì)“Redis在內(nèi)存分配和使用統(tǒng)計(jì)的技巧有哪些”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI