在c中,字符串的表示一般是以\0(空字符)結(jié)尾的字符數(shù)組,這種表示字符串的方法簡(jiǎn)單,但是使用起來(lái)卻有著許多繁瑣事項(xiàng),因此redis引入了自身的字符串形式->SDS。
那么c語(yǔ)言中的字符串?dāng)?shù)組具體來(lái)說(shuō)有著哪些不足呢?總體來(lái)說(shuō),就是四點(diǎn):
- 無(wú)法常數(shù)級(jí)獲取長(zhǎng)度,因?yàn)楦緵](méi)有記錄長(zhǎng)度的數(shù)據(jù),只能遍歷直到遇到空字符串,而在特定情境下,獲取長(zhǎng)度可能是高頻操作(很多使用者并不會(huì)認(rèn)為獲取長(zhǎng)度是復(fù)雜的)
- 需要程序員自己去保證內(nèi)存足夠(否則緩沖區(qū)溢出問(wèn)題就來(lái)了)
- 無(wú)論是空間的獲取還是空間的釋放都需要程序員考慮(而且因?yàn)樾枰筒僮飨到y(tǒng)打交道,效率很低)
- 由于依賴\0來(lái)判斷結(jié)束,所以在處理二進(jìn)制(大量\0)的時(shí)候會(huì)顯得力不從心
其實(shí)我們也可以看出來(lái),這四個(gè)問(wèn)題,其實(shí)涉及到的就是兩點(diǎn),第一個(gè)就是對(duì)于結(jié)束的判斷(依賴于\0),第二點(diǎn)就是內(nèi)存的分配。
因此SDS對(duì)此做出了兩點(diǎn)改進(jìn),針對(duì)第一個(gè)問(wèn)題,就是簡(jiǎn)單粗暴了,我直接維護(hù)一個(gè)長(zhǎng)度不就行了?(而且在所有設(shè)計(jì)的api中都維護(hù)這個(gè)長(zhǎng)度。第二點(diǎn)的話,SDS引入了一個(gè)free的概念來(lái)表達(dá)我還剩多少空間,通過(guò)這個(gè)參數(shù),redis可以快速的判斷是否會(huì)出現(xiàn)內(nèi)存不夠的問(wèn)題,于是就可以避免緩沖區(qū)溢出的問(wèn)題,而為了減少內(nèi)存的重分配,redis在獲取內(nèi)存的時(shí)候并不是需要多少拿多少,而是采取這樣的策略1.如果操作后的空間小于1MB,那么我就分配一樣的free空間(2倍原則,這在算法里面也曾經(jīng)出現(xiàn)過(guò),通過(guò)這種分配,可以讓數(shù)組延伸的時(shí)候的時(shí)間復(fù)雜度均攤為常數(shù)級(jí)),而如果大于1MB那么我就只分配1MB(否則太大了)
盡管SDS并不跟字符串?dāng)?shù)組相同,redis還是在實(shí)際存儲(chǔ)的時(shí)候遵循了相同原則(以\0結(jié)束),這樣就使得redis可以借用一部分使用字符數(shù)組的函數(shù).
struct sdshdr{
int len;
int free;
char buf[];
}