redis——內存概述

Redis通過自己的方法管理內存,,主要方法有zmalloc(),zrealloc(), zcalloc()和zfree(), 分別對應C中的malloc(), realloc()、
calloc()和free()。相關代碼在zmalloc.h和zmalloc.c中。
Redis自己管理內存的好處主要有兩個:可以利用內存池等手段提高內存分配的性能;可以掌握更多的內存信息,以便于Redis虛擬內存(VM)等功能中,決定何時將數據swap到磁盤。
先回憶各個系統中常見的內存分配函數:
malloc()分配一塊指定大小的內存區域,并返回指向區域開頭的指針,若分配失敗,則返回NULL。
calloc()與malloc()一樣,分配一塊指定大小的內存區域,成功時返回區域頭指針,失敗返回NULL。

區別在于, calloc()的輸入參數為count和size,即分配的項的數
目,及每一項的大小。

calloc()在成功分配內存空間后,會將空間內所有值置0。
realloc()修改已分配的內存塊的大小。若已分配的內存塊后沒有足夠的空間用于擴展內存塊,則重新申請一塊滿足需要的內存塊,并將舊的數據拷貝到新位置,釋放舊的內存塊,返回指向新的內存塊的指針;否則直接擴展原有的內存塊。若分配失敗,返回NULL。
free()釋放已分配的內存塊。
內存分配
在Redis中,如果系統中包含TCMALLOC,則會使用tc_malloc()等TCMALLOC中的方法代替malloc()等原有的分配內存方法。 TCmalloc是google perftools中的一個組件。

#if defined(USE_TCMALLOC)
#define malloc(size) tc_malloc(size)

首先看zmalloc()和zfree()兩個最常用的方法。 Redis在申請內存時,除了申請需要的size外,還會多申請一塊定長(PREFIX_SIZE)的區域用于記錄所申請的內存塊的長度。如果申請成功, Redis會使用宏函數(Redis中為性能考慮,大量使用宏函數)
update_zmalloc_stat_alloc(size+PREFIX_SIZE, size)記錄申請的內存塊的相關信息,以便監控內存使用狀況;當內存塊被zfree()釋放時,根據頭部的信息可以快速地獲知被釋放的內存區域的長度,然后通過宏函數update_zmalloc_stat_free()標記釋放。源代碼中,若系統支持malloc_size()方法,則會使用它返回指針所指向的內存塊的大小(Mac OS X 10.4以上支持該方法[3])。 有疑惑的是,在支持malloc_size()的系統中,為何還要多申請PREFIX_SIZE的內存?
?

void *zmalloc(size_t size) {void *ptr = malloc(size+PREFIX_SIZE);if (!ptr) zmalloc_oom(size);
#ifdef HAVE_MALLOC_SIZEupdate_zmalloc_stat_alloc(redis_malloc_size(ptr),size);return ptr;
#else*((size_t*)ptr) = size; // 在頭部記錄內存塊的長度update_zmalloc_stat_alloc(size+PREFIX_SIZE,size);return (char*)ptr+PREFIX_SIZE;
#endif
}

宏update_zmalloc_stat_alloc()中,首先將要分配的空間與內存對齊,然后會根據宏zmalloc_thread_safe判斷是否需要對內存信息記錄表的相關操作加鎖。雖然Redis在大部分場景中是單線程讀寫的,即thread_safe的,但啟用虛擬內存(VM),或持久化dump到磁盤等操作時會啟動多線程,因此在多線程模式中,需要對部分操作加鎖。內存監控
used_memory記錄了Redis使用的內存總數。而多線程下malloc()是線程安全的。
zmalloc_allocations[]記錄了各個size分配的內存塊的數目,大于256個字節的按256算。應用程序可以通過zmalloc_allocations_for_size(size)獲得對應size的
內存塊的分配數目;也可以通過zmalloc_used_memory()獲得Redis占用的總內存。這些監控類的方法在Redis的日志系統中被用到。
zcalloc(size)、 zrealloc()與zmalloc()的處理策略類似,不再詳述。
在部分操作系統中, Redis可以通過zmalloc_get_rss()方法獲得自己的進程占用
的內存信息。該信息通過操作系統提供,往往比Redis自己記錄的used_memory更準確,
但其獲取速度也較慢。這些信息也是用于虛擬內存功能。
除了內存相關的操作外, Redis在此還提供了一個復制字符串的方法zstrdup(char
*),該方法將申請一塊與源字符串長度相同的內存區域,并用memcpy()拷貝字符串的內
容。
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/445089.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445089.shtml
英文地址,請注明出處:http://en.pswp.cn/news/445089.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows下如何用C語言清空特定文件夾中的所有文件

#include "iostream.h" //由于該博客系統發布是不能顯示正常,代碼如需調試,只需將改成""即可 #include "string.h" #include "stdlib.h" #include "time.h" #include "math.h" #include…

MachineLearning(5)-去量綱:歸一化、標準化

去量綱:歸一化、標準化1.歸一化(Normalization)1.1 Min-Max Normalization1.2 非線性Normalization2.標準化(Standardlization)2.1 Z-score Normalization3.標準化在梯度下降算法中的重要性本博文為葫蘆書《百面機器學習》閱讀筆記。去量綱化 可以消除特征之間量綱的…

GDB調試技術(一)

啟動GDB的方法有以下幾種: 1、gdb <program> program也就是你的執行文件,一般在當然目錄下。 2、gdb <program> core 用gdb同時調試一個運行程序和core文件,core是程序非法執行后core dump后產生的文件。 3、

GDB調試技術(二)

1) 恢復程序運行和單步調試 當程序被停住了,你可以用continue命令恢復程序的運行直到程序結束,或下一個斷點到來。也可以使用step或next命令單步跟蹤程序。 continue [ignore-count] c [ignore-count] fg [ignore-count] 恢復程序運行,直到程序結束,或是下一個斷點到…

關于Java中String的問題

String 對象的兩種創建方式&#xff1a; String str1 "abcd";//先檢查字符串常量池中有沒有"abcd"&#xff0c;如果字符串常量池中沒有&#xff0c;則創建一個&#xff0c;然后 str1 指向字符串常量池中的對象&#xff0c;如果有&#xff0c;則直接將 st…

學點數學(3)-函數空間

函數空間1.距離&#xff1a;從具體到抽象2.范數3.內積4.拓撲本博文為觀看《上海交通大學公開課-數學之旅-函數空間 》所整理筆記&#xff0c;公開課視頻連接&#xff1a;http://open.163.com/newview/movie/free?pidM8PTB0GHI&midM8PTBUHT0數學中的空間 是 大家研究工作的…

Makefile編寫詳解--項目開發

預備知識&#xff1a; gcc 的3個參數&#xff1a; 1. -o 指定目標文件 gcc sources/main.c -o bin/main 2. -c 編譯的時候只生產目標文件不鏈接 gcc -c sources/main.c -o obj/main.o 3. -I 主要指定頭文件的搜索路徑 gcc -I headers -c main.c -o main.o 4. -l 指定靜…

如何判斷對象已經死亡

引用計數 給對象中添加一個引用計數器&#xff0c;每當有一個地方引用它&#xff0c;計數器就加 1&#xff1b;當引用失效&#xff0c;計數器就減 1&#xff1b;任何時候計數器為 0 的對象就是不可能再被使用的。 這個方法實現簡單&#xff0c;效率高&#xff0c;但是目前主流…

XML常見的操作

1. 創建XML文檔 &#xff08;1&#xff09;創建一個XML文檔非常簡單&#xff0c;其流程如下&#xff1a; ① 用xmlNewDoc函數創建一個文檔指針doc。 ② 用xmlNewNode函數創建一個節點指針root_node。 ③ 用xmlDocSetRootElement將root_node設置為doc的根結點。…

算法(2)-二叉樹的遍歷(遞歸/迭代)python實現

二叉樹的遍歷1.深度優先DFS1.1 DFS 遞歸解法1.1.1先序遍歷1.1.2中序遍歷1.1.3后序遍歷1.2 DFS迭代解法1.2.1先序遍歷1.2.2中序遍歷1.2.3后序遍歷2.廣度優先BFS3.二叉樹的最大深度3.1遞歸3.2迭代4.翻轉二叉樹4.1遞歸4.1迭代5.合并兩棵二叉樹5.1遞歸5.2迭代有兩種通用的遍歷樹的策…

libxml的安裝和相關數據結構詳解

1安裝 一般如果在安裝系統的時候選中了libxml開發庫的話&#xff0c;系統會默認安裝。如果沒有安裝&#xff0c;可以按如下步驟進行手工安裝。 ① 從xmlsoft站點或ftp(ftp.xmlsoft.org)站點下載libxml壓縮包 (libxml2-xxxx.tar.gz) ② 對壓縮包進行解壓縮 tar xvzf …

內核中的 likely() 與 unlikely()

在 2.6 內核中&#xff0c;隨處可以見到 likely() 和 unlikely() 的身影&#xff0c;那么為什么要用它們&#xff1f;它們之間有什么區別&#xff1f; 首先要明確&#xff1a; if(likely(value)) 等價于 if(value) if(unlikely(value)) 也等價于 if(value) 也就是說 likely()…

python外卷(12)-sort(),sorted(),ord(),chr()

Python內置函數1.sort()&#xff0c;sorted()2.ord(), chr()1.sort()&#xff0c;sorted() sort() 是list的方法&#xff0c;對已經存在的列表進行操作&#xff0c;無返回值 a[3,2,4,1] b["c","a","b"] print (a.sort(),b.sort()) # 輸出 (Non…

利用posix_fadvise清理系統中的文件緩存

利用posix_fadvise清理系統中的文件緩存leoncom c/c,unix2011-08-03當我們需要對某段讀寫文件并進行處理的程序進行性能測試時&#xff0c;文件會被系統cache住從而影響I/O的效率&#xff0c;必須清理cache中的對應文件的才能正確的進行性能測試。通常清理內存可以采用下面的這…

空間分配

目前主流的垃圾收集器都會采用分代回收算法&#xff0c;因此需要將堆內存分為新生代和老年代&#xff0c;這樣我們就可以根據各個年代的特點選擇合適的垃圾收集算法。 大多數情況下&#xff0c;對象在新生代中 eden 區分配。當 eden 區沒有足夠空間進行分配時&#xff0c;虛擬…

關于uint32_t uint8_t uint64_t 的問題

怎么又是u又是_t的?u代表的是unsigned相信大家都知道,那么_t又是什么呢?我認為它就是一個結構的標注,可以理解為type/typedef的縮寫,表示它是通過typedef定義的,而不是其它數據類型。 uint8_t,uint16_t,uint32_t等都不是什么新的數據類型,它們只是使用typedef給類型起…

學點數學(4)-協方差矩陣

協方差矩陣協方差矩陣&#xff08;從隨機變量講起&#xff09;隨機變量x&#xff1a;表示隨機試驗各種結果的 實值 單值函數&#xff0c;就是說隨機變量x是一個函數映射&#xff0c;其取值為標量。隨機變量有離散型和連續型&#xff0c;離散型&#xff1a;拋10次硬幣&#xff…

RedLock

概念 Redis 官方站這篇文章提出了一種權威的基于 Redis 實現分布式鎖的方式名叫 Redlock&#xff0c;此種方式比原先的單節點的方法更安全。它可以保證以下特性&#xff1a; 安全特性&#xff1a;互斥訪問&#xff0c;即永遠只有一個 client 能拿到鎖避免死鎖&#xff1a;最終…

GCC中常用的優化的參數

-pipe 的作用&#xff1a; 使用管道代替編譯中臨時文件&#xff0c; -pipe 加速編譯 gcc -pipe foo.c -o foo 加速 在將源代碼變成可執行文件的過程中,需要經過許多中間步驟,包含預處理、編譯、匯編和連接。這些過程實際上是由不同的程序負責完成的。大多數情況下 GCC 可以為 …

Linux與時間相關的結構體及相關用法

1. Linux下與時間有關的結構體 struct timeval { int tv_sec; int tv_usec; }; 其中tv_sec是由凌晨開始算起的秒數&#xff0c;tv_usec則是微秒(10E-6 second)。 struct timezone { …