十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
這篇“redis的zmalloc函數(shù)實(shí)例分析”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Redis的zmalloc函數(shù)實(shí)例分析”文章吧。
在萬(wàn)榮等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),網(wǎng)絡(luò)營(yíng)銷推廣,成都外貿(mào)網(wǎng)站建設(shè),萬(wàn)榮網(wǎng)站建設(shè)費(fèi)用合理。
我們直接來(lái)看 Redis 源碼(不是最新版本)中自定義的 zmalloc 函數(shù),該函數(shù)與 malloc 等常規(guī)函數(shù)的使用方式完全一致,不同的在于其內(nèi)部的具體實(shí)現(xiàn)細(xì)節(jié)。
void *zmalloc(size_t size) {
// 分配內(nèi)存;
void *ptr = malloc(size + PREFIX_SIZE);
// 分配失敗拋出異常;
if (!ptr) zmalloc_oom_handler(size);
// 系統(tǒng)是否可以使用”malloc_size“函數(shù)?
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(zmalloc_size(ptr));
return ptr;
#else
// 在數(shù)據(jù)域保存分配數(shù)據(jù)的實(shí)際大小;
*((size_t*)ptr) = size;
// 計(jì)算對(duì)齊后的內(nèi)存使用大小,并更新”used_memory“變量;
update_zmalloc_stat_alloc(size + PREFIX_SIZE);
// 返回?cái)?shù)據(jù)體的初始位置;
return (char*)ptr + PREFIX_SIZE;
#endif
}
其實(shí),標(biāo)準(zhǔn)庫(kù)中的 malloc 函數(shù)已經(jīng)能夠自動(dòng)為分配的內(nèi)存實(shí)現(xiàn)對(duì)齊,因此 zmalloc 方法在這里其主要目的是為了能夠精確地計(jì)算每一次數(shù)據(jù)存儲(chǔ)時(shí)所分配的內(nèi)存大小。在每一次分配內(nèi)存時(shí),zmalloc 都會(huì)在該次分配的數(shù)據(jù)內(nèi)存大小的基礎(chǔ)上再加上一個(gè) PREFIX_SIZE 大小的額外內(nèi)存空間,這個(gè) PREFIX_SIZE 宏代表了當(dāng)前系統(tǒng)的最大內(nèi)存尋址空間大小(size_t),其依賴于具體系統(tǒng)的類型不同而不同。這里我們可以簡(jiǎn)稱這個(gè) PREFIX_SIZE 大小的空間為一個(gè)存儲(chǔ)單元的“數(shù)據(jù)頭”部分。
初版 Redis 的存儲(chǔ)單元結(jié)構(gòu)
如上圖所示,通過(guò) *((size_t*)ptr) = size; 語(yǔ)句,Redis 在當(dāng)前分配內(nèi)存塊的前 PREFIX_SIZE 個(gè)字節(jié),即數(shù)據(jù)頭內(nèi)存儲(chǔ)了本次實(shí)際分配的數(shù)據(jù)塊大小,而在后面 ”size“ 大小的內(nèi)存空間中才真正存放了二進(jìn)制的數(shù)據(jù)實(shí)體。在這里名為 update_zmalloc_stat_alloc 的函數(shù)在其內(nèi)部會(huì)維護(hù)一個(gè)名為 used_memory 的全局變量,該變量累加了每次新分配的內(nèi)存大小。函數(shù)在最后返回了一個(gè)偏移的指針,指向了當(dāng)前分配內(nèi)存的數(shù)據(jù)體部分。update_zmalloc_stat_alloc 函數(shù)的具體實(shí)現(xiàn)細(xì)節(jié)如下。
#define update_zmalloc_stat_alloc(__n) do {
size_t _n = (__n);
// 手動(dòng)內(nèi)存補(bǔ)齊;
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1));
atomicIncr(used_memory, __n);
} while(0)
這里需要注意的重點(diǎn)是 _n += sizeof(long)-(_n&(sizeof(long)-1)); 這行語(yǔ)句。整個(gè)宏函數(shù)首先判斷本次分配的內(nèi)存大小是否為 sizeof(long) 大小的整數(shù)倍(64位機(jī)對(duì)應(yīng)著8字節(jié)的內(nèi)存對(duì)齊;32位機(jī)則對(duì)應(yīng)著4字節(jié)的內(nèi)存對(duì)齊),如果不是則通過(guò)我們之前給出的語(yǔ)句在該數(shù)據(jù)段后添加相應(yīng)的占位空間來(lái)補(bǔ)足位數(shù)以滿足內(nèi)存對(duì)齊(4/8字節(jié))的要求。最后的 atomicIncr 函數(shù)用來(lái)在保證線程安全的情況下更新全局的 used_memory 變量值。
而該版本 Redis 中內(nèi)存釋放與其內(nèi)存分配的過(guò)程則正好相反。如下所示代碼為對(duì)應(yīng) ”zfree“ 函數(shù)的實(shí)現(xiàn)細(xì)節(jié)。首先該函數(shù)通過(guò) (char*)ptr-PREFIX_SIZE 語(yǔ)句(向內(nèi)存低地址移動(dòng))指向了包含有該數(shù)據(jù)塊實(shí)際占用大小的數(shù)據(jù)域首地址,然后通過(guò) *((size_t*)realptr) 語(yǔ)句獲得到了該數(shù)據(jù)塊分配的真實(shí)內(nèi)存大?。ú话瑑?nèi)存對(duì)齊區(qū)域)。最后再通過(guò) update_zmalloc_stat_free 函數(shù)來(lái)更新全局變量 used_memory 的值,并釋放該段內(nèi)存。
void zfree(void *ptr) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
size_t oldsize;
#endif
if (ptr == NULL) return;
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_free(zmalloc_size(ptr));
free(ptr);
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
free(realptr);
#endif
}
如下所示,這里如果我們?cè)賮?lái)看 update_zmalloc_stat_free 函數(shù)的實(shí)現(xiàn)細(xì)節(jié),你會(huì)發(fā)現(xiàn)它與之前的 update_zmalloc_stat_alloc 函數(shù)其執(zhí)行過(guò)程類似。通過(guò)計(jì)算需要補(bǔ)足的內(nèi)存字節(jié)大小,并從 used_memory 變量中減去相應(yīng)大小的內(nèi)存空間,即可實(shí)現(xiàn)對(duì)內(nèi)存空間使用率的精確計(jì)算。
#define update_zmalloc_stat_free(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
atomicDecr(used_memory,__n); \
} while(0)
以上就是關(guān)于“Redis的zmalloc函數(shù)實(shí)例分析”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。