redis原始碼分析二 sds實現

2021-10-03 15:38:34 字數 2384 閱讀 3506

1、sds頭部的結構

struct __attribute__ ((__packed__)) sdshdr8 ;
2、redis中sds的優勢

1.快速獲取字串長度

這個在於sds的首部中記錄了len表示當前buf的長度,這樣獲取乙個字串的長度的複雜度變成了o(1),這也是用空間換效率的有效方法,因為暫用的空間非常小且現在我們電腦上的記憶體越來越大,所以這個方法是可行的

2.避免緩衝區溢位

在redis中sds中,在新增資料前會呼叫sdsmakeroomfor函式,這個函式會判斷當前的alloc空間是否能夠容納len+新增加的空間,如果原來的alloc空間容納不下,會先去申請空間,其中也會維護type的引數,例如當新增加的空間大於8位時,會擴容成16位。這樣在每一次確保空間足夠大的情況下新增資料可以有效防止緩衝區溢位

3.降低空間分配次數提公升記憶體使用效率

在redis的sds中會先申請比所需要的大的空間,例如我們原來sds的有len,申請了alloc的空間,現在需要加上addlen的長度,如果len+addlen>alloc,就會進行擴容,這時候對len+addlen的大小進行判斷,如果len+addlen<10241024,那重新申請的空間大小為(len+addlen)2,如果len+addlen>=10241024,那重新申請的空間大小為(len+addlen)+10241024,通過申請較大一塊區域,可以只在空間不夠時進行申請,如果新增的資料alloc的空間還容納的下,那就不需要進行申請了,減少了空間分配的次數

3、sds函式釋義

函式引數

釋義sdsnewlen

const void *init, size_t initlen

申請乙個長為len的sds物件。首先根據initlen的長度選擇合適的type,比如說8位,還是16位的,然後再設定頭部的alloc,len,flag引數,接著將init指標指向的資料複製到buf中,最後加上\0

sdsmakeroomfor

sds s, size_t addlen

檢查當前sds的物件是否能夠容納addlen的資料,如果能夠容納,則直接返回,如果不能容納,則需要進行擴容,擴容是如果len+addlen沒有改變type的型別,例如都是8位,則使用remalloc可以申請,如果改變了type型別,則需要重新malloc(因為這時候頭部大小擴大,頭部需要向前移動,用remalloc無法支援向前擴充套件),同時這時候需要填寫頭部的引數。在操作sds新增資料時首先會呼叫這個函式來進行判斷,因為如果原來的足夠容納新加的資料會直接返回,所以這個函式可以有效的防止指標越界這個問題

sdsallocptr

sds s

返回指向sds頭部的指標,注意這裡sds的物件s指向的是buf的部分

sdsallocsize

sds s

返回sds中頭部儲存的alloc引數(注意alloc的表示的是當前buf已經申請的長度),而乙個sds的總長度表示的是頭部長度+alloc+1,這個1表示最後的\0

sdscatlen

sds s, const void *t, size_t len

往原來的s後面新增len長度的t指向的資料,然後返回新增後的sds物件,注意,在新增前會先呼叫sdsmakeroomfor來判斷是否原來的長度能夠容納len的資料,如果不能容納,並且新增後的長度導致增大了type,則這時候會新申請乙個位址,這時候返回的sds物件就和原來的那個不相同了

sdscpylen

sds s, const char *t, size_t len

和sdscatlen相似,就是講乙個sds的內容拷貝到另乙個sds物件中

sdscatprintf

sds s, const char *fmt, va_list ap

將資料用fmt的格式新增到s後面,例如s = sdsnew(「sum is: 「);s = sdscatprintf(s,」%d+%d = %d」,a,b,a+b).需要注意返回的sds物件也有可能與之前的不相同

sdscatfmt

sds s, char const *fmt, …

此函式和sdscatprintf函式相似,是sdscatprintf的加快版,其中fmt支援的型別有1、%s - c string 2、%s - sds string 3、%i - signed int 4、%i - 64 bit signed integer (long long, int64_t) 5、%u - unsigned int 6、%u - 64 bit unsigned integer (unsigned long long, uint64_t) 7、%% - verbatim 「%」 character.

sdsincrlen

sds s, ssize_t incr

我們在sds的物件新增完資料後用這個函式來更新sds頭部的len資料,同時會在buf的s[len]處新增\0,所以這個函式在我們新增完資料後必須要呼叫

SDS字串原始碼分析

0.前言 這裡對redis底層字串的實現分析,但是看完其實現還沒有完整的乙個概念,即不太清楚作者為什麼要這樣子設計,只能窺知一點,需要看完redis如何使用再回頭來體會,有不足之處還望告知。涉及檔案 sds.h sds.c 1.資料結構 1 typedef char sds 23 struct sd...

Redis原始碼分析二 Redis簡單動態字串

redis簡單動態字串 redis沒有直接使用c語言傳統的字串表示 以空字元結尾的字元陣列,以下簡稱c字串 而是自己構建了一種名為簡單動態字串 dynamic string,sds 的抽象型別,並將sds用作redis的預設字串表示。在redis裡面,c字串只會作為字串字面量 string lite...

Redis原始碼閱讀 sds字串實現

從開始工作就開始使用redis,也有一段時間了,但都只是停留在使用階段,沒有往更深的角度探索,每次想讀原始碼都止步在閱讀書籍上,因為看完書很快又忘了,這次逼自己先讀 因為個人覺得寫作需要閱讀文本來增強靈感,那麼寫 的,就閱讀更多 來增強靈感吧。redis的實現原理,在 redis設計與實現 一書中講...