前言 Redis 沒有直接使用 C 語言傳統的字元串表示(以空字元結尾的字元數組,以下簡稱 C 字元串), 而是自己構建了一種名為簡單動態字元串(simple dynamic string,SDS)的抽象類型, 並將 SDS 用作 Redis 的預設字元串表示。 個人感覺SDS類似於Java的Arr ...
前言
Redis 沒有直接使用 C 語言傳統的字元串表示(以空字元結尾的字元數組,以下簡稱 C 字元串), 而是自己構建了一種名為簡單動態字元串(simple dynamic string,SDS)的抽象類型, 並將 SDS 用作 Redis 的預設字元串表示。
個人感覺SDS類似於Java的ArrayList,大家可以拿兩者對比一些,誰的效率更加高一點。
SDS定義
1 struct sdshdr { 2 3 // 記錄 buf 數組中已使用位元組的數量 4 // 等於 SDS 所保存字元串的長度 5 int len; 6 7 // 記錄 buf 數組中未使用位元組的數量 8 int free; 9 10 // 位元組數組,用於保存字元串 11 char buf[]; 12 13 };
這裡註意一下。C語言的char是占一個位元組的。不像Java的char占兩個位元組。也就是只有八位,-127 - 128。
SDS相比於C字元串的優勢
1. 常數複雜度獲取字元串長度
- 這個比較好理解,因為SDS裡面有一個欄位為len,可以直接獲取長度
2. 減少修改字元串時帶來的記憶體重分配次數
- 因為傳統的c字元串,不會自動擴容。而且其記憶體大小就等於字元串長度+1,因此,每修改一次字元串,都要重新分配一次記憶體,非常的耗費時間
- SDS會自動擴容,並且會進行空間預分配。比如現在有一個Hello的字元串。記憶體的大小可能是Hello的兩倍,也就是 5 * 2 = 10。當再次擴容字元串的時候,不一定需要再次分配記憶體了。並且可以自動擴容,假設10不夠了,加了一個字元串後大小為13,那麼記憶體就會分配為 13 * 2 = 26大小的記憶體。
3. 二進位安全,以及可以保存空字元
- C 字元串中的字元必須符合某種編碼(比如 ASCII), 並且除了字元串的末尾之外, 字元串裡面不能包含空字元, 否則最先被程式讀入的空字元將被誤認為是字元串結尾 —— 這些限制使得 C 字元串只能保存文本數據, 而不能保存像圖片、音頻、視頻、壓縮文件這樣的二進位數據。
- 因此,所有 SDS API 都會以處理二進位的方式來處理 SDS 存放在
buf
數組裡的數據 - 也就是保存在buf數組裡面的所有東西,不論英文中文,還是圖片音頻,都是二進位數據流。