redisソース分析の簡単な動的文字列sds
Sds(Simple Dynamic String.単純動的文字列)は、Redisの下位層で使用される文字列であり、ほとんどのredisモジュールで使用される.
SdsのRedisでの用途は主に2つあります.
1.stringObjectオブジェクトの作成
2.Redis内部でchar*の代替品として使用される.
1.文字列オブジェクトの実装
Redisはキー値対データベースであり、(key-value DataBase)、データベースの値は文字列、集合、リストなど多くのタイプのオブジェクトであってもよく、データベースのキーは常に文字列オブジェクトである.文字列値を含む文字列オブジェクトの場合、各文字列オブジェクトにはsds値が含まれます.
2.Cのデフォルトのchar*タイプにsdsを置き換える
Cデフォルトのcharタイプの文字列は、機能が単一で抽象階層が低く、追加操作や長さ計算操作などのRedis操作を効率的にサポートできないため、Redis内部ではchar*の代わりにsdsを使用して文字列を表すことがほとんどです.
Redisでは,クライアントからのプロトコルコンテンツ,aofキャッシュコンテンツ,クライアントへの返信など,これらの重要なコンテンツはsdsタイプで保存される.
Redisの文字列
C言語では文字列はすべて'0'で終わる.例えばhello worldはc言語で「hello wordl0」と表示されます
このような単純な文字列は多くの場合要求を満たすことができるが,計算長さや追加操作を効率的に行うことはできない.
1.長さの計算にはstrlen()関数を使用する必要があり、複雑度はO(n)である.
2.N回追加する場合はrealloc N回必要
Redisでは,この2つの操作は非常に頻繁であり,この2つの簡単な操作は性能のボトルネックにはならない.また、Redisは文字列のほかに、1バイトの配列やサーバプロトコルなども扱うので、Redisの文字列はバイナリで安全なはずです.したがって、Redisは、Cのデフォルトのchar*文字列の代わりにSdsを使用します.sdsは計算長さと追加操作を効率的に行うことができるか,それともバイナリが安全であるか.
sdsの実装:
sdsは2つの部分からなる
lenにより,文字列の長さ(O(1))を容易に算出できる.
一方,bufに空間を多く割り当て,freeを用いて未使用の空間の大きさを記録することで,sdshdrは直行追加操作に必要なメモリ再割り当て回数を大幅に減少させることができる.
もちろんsdsの操作はlen、free属性を正しく更新します.
追加操作の最適化
sdshdrにはfreeという属性があるので,空間を割り当てる際には,より多くの空間を割り当てることができ,次の追加操作の際には,必ずしも空間を再割り当てる必要がなく,空間を再割り当てる回数を減らすことができる.
たとえば、最初の文字列の「hello world0」sdshdrの値は次のようになります.
まとめ:
1.Redis文字列はsdsとして表され、Cデフォルトのchar*ではありません.
2.C文字列よりsdsの方が次のようなメリットがある
2.1.文字列の長さの計算を容易にする
2.2.追加操作の効率化
2.3.バイナリセキュリティ
3.sdsは追加操作を最適化するために、スペースを多く割り当てますが、マルチ割り当てメモリはアクティブに回収されず、スペースが浪費されます.
SdsのRedisでの用途は主に2つあります.
1.stringObjectオブジェクトの作成
2.Redis内部でchar*の代替品として使用される.
1.文字列オブジェクトの実装
Redisはキー値対データベースであり、(key-value DataBase)、データベースの値は文字列、集合、リストなど多くのタイプのオブジェクトであってもよく、データベースのキーは常に文字列オブジェクトである.文字列値を含む文字列オブジェクトの場合、各文字列オブジェクトにはsds値が含まれます.
2.Cのデフォルトのchar*タイプにsdsを置き換える
Cデフォルトのcharタイプの文字列は、機能が単一で抽象階層が低く、追加操作や長さ計算操作などのRedis操作を効率的にサポートできないため、Redis内部ではchar*の代わりにsdsを使用して文字列を表すことがほとんどです.
Redisでは,クライアントからのプロトコルコンテンツ,aofキャッシュコンテンツ,クライアントへの返信など,これらの重要なコンテンツはsdsタイプで保存される.
Redisの文字列
C言語では文字列はすべて'0'で終わる.例えばhello worldはc言語で「hello wordl0」と表示されます
このような単純な文字列は多くの場合要求を満たすことができるが,計算長さや追加操作を効率的に行うことはできない.
1.長さの計算にはstrlen()関数を使用する必要があり、複雑度はO(n)である.
2.N回追加する場合はrealloc N回必要
Redisでは,この2つの操作は非常に頻繁であり,この2つの簡単な操作は性能のボトルネックにはならない.また、Redisは文字列のほかに、1バイトの配列やサーバプロトコルなども扱うので、Redisの文字列はバイナリで安全なはずです.したがって、Redisは、Cのデフォルトのchar*文字列の代わりにSdsを使用します.sdsは計算長さと追加操作を効率的に行うことができるか,それともバイナリが安全であるか.
sdsの実装:
sdsは2つの部分からなる
typedef char *sds;
struct sdshdr {
// buf
int len;
// buf
int free;
//
char buf[];
};
sdsはchar*の別名であり、構造sdshdrはlen、free、bufの3つの属性を保存します.lenにより,文字列の長さ(O(1))を容易に算出できる.
一方,bufに空間を多く割り当て,freeを用いて未使用の空間の大きさを記録することで,sdshdrは直行追加操作に必要なメモリ再割り当て回数を大幅に減少させることができる.
もちろんsdsの操作はlen、free属性を正しく更新します.
追加操作の最適化
sdshdrにはfreeという属性があるので,空間を割り当てる際には,より多くの空間を割り当てることができ,次の追加操作の際には,必ずしも空間を再割り当てる必要がなく,空間を再割り当てる回数を減らすことができる.
たとえば、最初の文字列の「hello world0」sdshdrの値は次のようになります.
struct sdshdr {
len = 11;
free = 0;
buf = "hello world\0";
}
Appendの場合、Redisは空間を再割り当てます.例えば、appendの文字列againは7バイトしかかかりませんが、Redisは必要な空間の倍の空間を割り当てます.チャンスは37バイト分のスペースを割り当てて、これで18バイト余ったので、次のAppend操作の時、追加した文字列の長さが18バイト未満であれば、再びスペースを割り当てる必要はありません.追加するまで、余剰スペースが足りなくて、二次的にスペースを再割り当て、2倍のスペースを割り当てることができます.これにより、再割り当てされたスペースの回数は減少しますが、文字列全体が破棄されない限り、マルチ割り当てされたスペースは回収されません.まとめ:
1.Redis文字列はsdsとして表され、Cデフォルトのchar*ではありません.
2.C文字列よりsdsの方が次のようなメリットがある
2.1.文字列の長さの計算を容易にする
2.2.追加操作の効率化
2.3.バイナリセキュリティ
3.sdsは追加操作を最適化するために、スペースを多く割り当てますが、マルチ割り当てメモリはアクティブに回収されず、スペースが浪費されます.