2単純な動的文字列
3126 ワード
Redis
は、単純動的文字列(simple dynamic string, SDS)
という抽象型を構築し、SDS
をredis
のデフォルト文字列表現として使用する.Redis
のC
文字列は、データベース内の文字列を保存するために使用されるほか、SDS
がバッファ(buffer)
として使用される文字列の字面量としてのみ使用されます.2.1
SDS
の定義sds.h/sdshdr
構造は、SDS
の値を表します.struct sdshdr{
// buf
// SDS
int len;
// buf
int free;
// ,
char buf[];
};
SDS
は、C
文字列が空白文字で終わる慣例に従うが、この動作はSDS
関数によって自動的に行われる.2.2
SDS
とC
文字列の違いC
言語は長さN+1
の文字配列を使用して長さNの文字列を表し、文字配列の最後の要素が常に空の文字列'\0'
C
言語で使用される文字列は、Redis
の文字列に対する安全性、効率、および機能の要件を満たすことができない.2.2.1定数複雑度取得文字列長
C
文字列は、自身の長さ情報を記録せず、C
文字列の長さを取得し、プログラムは文字列全体を遍歴しなければならない.この動作の時間的複雑さはO(N)
である.SDS
は、len
の属性にSDS
自体の長さを記録しているので、SDS
の長さを取得する複雑さはO(1)
にすぎない.SDS
の長さを設定および更新する作業は、SDS
のAPI
が実行時に自動的に完了し、SDS
を使用して長さを手動で変更する作業は必要ありません.2.2.2バッファオーバーフローの防止
C
文字列が自身の長さを記録しないことによるもう一つの問題は、バッファオーバーフロー(buffer overflow)
を生じやすいことである.C
文字列とは異なり、SDS
の空間割り当てポリシーはバッファオーバーフローの発生の可能性を完全に根絶している:SDS
API
がSDS
を修正する必要がある場合、API
はまずSDS
空間が修正に必要な要求を満たしているかどうかを検査し、満足していない場合、API
は、SDS
の空間を自動的に変更を実行するために必要なサイズに拡張してから、実際の変更操作を実行するので、SDS
を使用すると、SDS
の空間サイズを手動で変更する必要もなく、前述したバッファオーバーフローの問題も発生しません.2.2.3文字列の変更に伴うメモリの再割り当て回数を減らす
SDS
未使用空間により文字列長と下位データ長との関連が解除された:SDS
では、buf
配列の長さは必ずしも文字数に1を加えたものではなく、配列には未使用のバイトを含めることができ、これらのバイトの数はSDS
のfree
属性によって記録される.空間を使用しないことによって,SDS
は空間事前割り当てと不活性空間放出の2つの最適化戦略を実現した.1.空間の事前割り当て
空間事前割り当て
SDS
の文字列成長動作を最適化するために使用される:SDS
のAPI
が1つのSDS
を修正し、SDS
を空間拡張する必要がある場合、プログラムはSDS
が修正に必要な空間を割り当てるだけでなく、SDS
の割り当て額以外の未使用空間も割り当てる.空間事前割り当てポリシーにより、Redis
は、文字列成長操作を連続的に実行するために必要なメモリ再割り当て回数を低減することができる.SDS
スペースを拡張する前に、SDS API
は未使用スペースが十分かどうかを確認し、十分であれば、API
はメモリ再割り当てを実行することなく、未使用スペースを直接使用します.2.不活性空間解放
不活性空間解放
SDS
の文字列短縮動作を最適化するために使用される:SDS
のAPI
がSDS
保存した文字列を短縮する必要がある場合、プログラムは直ちにメモリ再割り当てを使用して短縮されたバイトを回収するのではなく、free
属性を使用してこれらのバイトの数を記録し、将来の使用を待つ.不活性空間解放ポリシーにより、SDS
は、文字列を短縮するために必要なメモリ再割り当て操作を回避し、将来可能な増加操作を最適化します.SDS
も対応するAPI
を提供し、必要に応じてSDS
の未使用空間を本当に解放する.2.2.4バイナリセキュリティ
SDS
のAPI
はすべてバイナリで安全であり、すべてのSDS
API
はSDS
がbuf
配列に格納されたデータをバイナリで処理する.Redis
のbuf
は、文字を保存するのではなく、一連のバイナリデータを保存するために使用される.これは,SDS
のbuf
属性をバイト配列と呼ぶ理由である.2.2.5互換部分C文字列関数