久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Redis在內存分配和使用統計的技巧有哪些

132次閱讀
沒有評論

共計 3471 個字符,預計需要花費 9 分鐘才能閱讀完成。

本篇內容主要講解“Redis 在內存分配和使用統計的技巧有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“Redis 在內存分配和使用統計的技巧有哪些”吧!

具體來說就是:

若系統中存在 Google 的 TC_MALLOC 庫,則使用 tc_malloc 一族函數代替原本的 malloc 一族函數。

若當前系統是 Mac 系統,則使用中的內存分配函數。

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

源代碼分別在 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

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

那么這個記錄有什么用呢? 答案是,為了統計當前進程到底占用了多少內存。在 zmalloc.c 中,有這樣一個靜態變量:

static size_t used_memory = 0;

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

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 在內存分配和使用統計方面有哪些技巧

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

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

}

先將指針向前移動 PREFIX_SIZE,然后取出分配空間時保存的空間長度。最后 free 整個空間。

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

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 變量外,還有幾個要關注的地方:
先對_n 的低位向上取整,最后_n 變為 sizeof(long)的倍數,比如對于 32 位系統,sizeof(long) == 100(二進制),_n 向上取整之后,低兩位都變為 0。
如果進程中有多個線程存在,則在更新變量的時候要加鎖。
在 zmalloc 函數中還有一個統計量要更新:zmalloc_allocations[]。
在 zmalloc.c 中,zmalloc_allocations 是這樣定義的:
size_t zmalloc_allocations[ZMALLOC_MAX_ALLOC_STAT+1];
其作用是統計程序分配內存時,對不同大小空間的請求次數。統計的空間范圍從 1 字節到 256 字節,大于 256 字節的算為 256。統計結果通過調用 zmalloc_allocations_for_size 函數返回:
size_t zmalloc_allocations_for_size(size_t size) {
if (size ZMALLOC_MAX_ALLOC_STAT) return 0;

return zmalloc_allocations[size];

}

另一個對內存使用量的統計通過調用 zmalloc_used_memory 函數返回:

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 中,還針對不同的系統實現了 zmalloc_get_rss 函數,在 linux 系統中是通過讀取 /proc/$pid/stat 文件獲得系統統計的內存占用量。

到此,相信大家對“Redis 在內存分配和使用統計的技巧有哪些”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-15發表,共計3471字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 静安区| 平山县| 济阳县| 南靖县| 永登县| 西宁市| 浦县| 辉南县| 麦盖提县| 岳普湖县| 海伦市| 个旧市| 嘉定区| 邵东县| 瓦房店市| 延长县| 大洼县| 泰顺县| 沙坪坝区| 香河县| 当阳市| 大悟县| 宁海县| 常熟市| 浮梁县| 惠安县| 黑河市| 彩票| 平谷区| 共和县| 汉中市| 普格县| 建始县| 西和县| 南江县| 灌云县| 麻江县| 淳安县| 洪雅县| 克山县| 汶上县|