Redisのは、複数のデータ型をサポートし、SDS(簡単な動的な文字列)で最も基本的な一種で、主に動的な拡張と圧縮をサポートする、保存、および多くのユーティリティ機能を提供していますRedisのSDSを使用する文字列を入力します。この記事では、それが達成する方法であるRedisの中にSDSを分析します。
1. SDSタイプ
実際にはRedisの中のSDSは、以下の文、のchar *型の別名であります:
typedefでのchar * SDS;
しかし、SDSポイント記憶フォーマットストリング定数ルールを有する、すなわち、データ列の前に対応するヘッダ情報を格納し、ヘッダ情報は、長さを割り当てられたメモリ空間alloc- :. 1を含みます。2. len-効果的な文字列の長さ。3. flags-ヘッドタイプ。
そこRedisのsdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64次のように宣言されているこのカテゴリ5タイプのヘッド、:
構造体__attribute __((__packed__))sdshdr8 { uint8_t LEN。/ *使用* / uint8_tのアロケーション; / *ヘッダとヌルターミネータ* /除い unsigned char型フラグ。/ * 3 LSBタイプの、5未使用ビット* / チャー[] BUF。 }。
いくつかの他の同様のタイプが、異なるヘッド・タイプ、sdshdr16使用uint16_t、sdshdr32使用のuint32_t、sdshdr64使用uint64_tをに従って使用するALLOC lenのフィールドタイプを有します。また、ヘッドの異なる種類がないALLOCのLENフィールド、及び高い5ビットフラグフィールドに格納されている文字列の実際の長さと、他のsdshdr5。
uint8_t sdshdr8のALLOC型のため、従って、それは255バイトまでの文字列で表すことができる。起因uint16_t sdshdr16列型にALLOC、最大65536バイトで表すことができ、同様に、Redisのが最適ヘッドを選択スペースを節約sdshdr8使用して文字列、小さなスペースの節約を保存するためのユニット(私は時に短い文字列と信じている、が、文字列が長くsdshdr16とsdshdr32を使用してuint8_t表現範囲、使用ヘッドスペースの長さの割合よりもありますほとんど差)。どのような次のことを達成するために使用されるヘッド選択機能:
静的インラインチャーsdsReqType(size_tのstring_size){ 場合(string_size < 1 << 5 ) リターンSDS_TYPE_5。 もし(string_size < 1 << 8 ) 戻りSDS_TYPE_8。 もし(string_size < 1 << 16 ) 戻りSDS_TYPE_16。 #if(LONG_MAX == LLONG_MAX) 場合(string_size <1LL << 32 ) 戻りSDS_TYPE_32と、 返すSDS_TYPE_64を。 #else 返すSDS_TYPE_32を。 #endifの }
2. SDS操作
実際のメモリ割り当てタイプとの間の2.1 SDS変換
有効な文字列初期位置にSDS型ポイントを、ヘッダ情報の有効な記憶空間が一様分布列である、連続した、頭部の前方への移動の長さは、それらのメモリ空間を、SDS、実際の分布を得ることができますメモリはアドレスを始めます。SDSヘッダ長は次のように実装されているタイプのヘッドによって決定されます。
静的インラインINT sdsHdrSize(チャータイプ){ スイッチ(タイプ&SDS_TYPE_MASK){ ケースSDS_TYPE_5: リターン はsizeof(構造体sdshdr5)。 ケースSDS_TYPE_8: リターン はsizeof(構造体sdshdr8)。 ケースSDS_TYPE_16: リターン はsizeof(構造体sdshdr16)。 ケースSDS_TYPE_32: リターン はsizeof(構造体sdshdr32)。 場合SDS_TYPE_64: リターン はsizeof(構造体sdshdr64)。 } 戻り 0 。 }
下部ヘッド内に格納されたSDSヘッド型3ビットフラグは、ヘッド型は、以下のようにして求めることができます
S = oldtype [ - 1 ]&SDS_TYPE_MASK; // S型である、SDS
次のようにメモリアドレスから得られた実際の分布
SH =(チャー *)S-sdsHdrSize(oldtype)。
これには、以下を達成するためにsdsfree操作です。
ボイドsdsfree(SDS S){ もし、(S == NULL)のリターン; s_free((チャー *)S-sdsHdrSize(S [ - 1 ]))。 }
2.2分布SDS型c_str
機能のSDS新しいタイプは、次のように宣言されます。
SDS sdsnewlen(constの ボイド * initを、size_tのinitlen)
手順を以下のように一般的に記載されてもよいです。
- 適切な長さの選択c_str SDSヘッドタイプ、この工程()関数はsdsReqTypeにより実現されます
- 有効なヘッダ文字列を格納するための十分なスペースを割り当て(SDS端バイト列メモリが「\ 0」を必要とする)、このステップは()関数s_mallocによって実現されます。
- 中c_str SDSにヘッダ情報、コンテンツのコピーを設定します。
具体的な以下の機能を実現します:
SDS sdsnewlen(CONST ボイド *のINIT、size_tのinitlen){ ボイド *のSH。 SDS秒。 チャータイプ= sdsReqType(initlen)。 / * 空の文字列は、通常、追加するために作成されます。使用タイプ8 *タイプ5本が得意ではないので。* / 場合(タイプ== SDS_TYPE_5 && initlen == 0)=入力SDS_TYPE_8と、 INT hdrlen = sdsHdrSize(タイプ)。 符号なしのchar * fpは、/ * フラグは、ポインタ。* / SH = s_malloc(hdrlen + initlen + 1 )。 もし(INIT == SDS_NOINIT) INIT = NULL; それ以外の 場合(!INIT) のmemset(SH、0、hdrlen + initlen + 1 ); もし(SH == NULL)戻りNULL; S =(CHAR *)SH + hdrlen。 FP =((符号なしのchar *)S) - 1 。 スイッチ(タイプ){ ケースSDS_TYPE_5:{ * FP =タイプ| (initlen << SDS_TYPE_BITS)。 破ります; } ケース SDS_TYPE_8:{ SDS_HDR_VAR(8 、S)。 SH - > LEN = initlen。 SH - >のalloc = initlen。 * FP = タイプ。 破ります; } ケースSDS_TYPE_16:{ SDS_HDR_VAR(16 、S)。 SH - > LEN = initlen。 SH - >のalloc = initlen。 * FP = タイプ。 破ります; } ケースSDS_TYPE_32:{ SDS_HDR_VAR(32 、S)。 SH- > LEN = initlen。 SH - >のalloc = initlen。 * FP = タイプ。 破ります; } ケースSDS_TYPE_64:{ SDS_HDR_VAR(64 、S)。 SH - > LEN = initlen。 SH - >のalloc = initlen。 * FP = タイプ。 破ります; } } もし(initlen && INIT) のmemcpy(S、INIT、initlen)。 S [initlen] = ' \ 0 ' 。 リターンS; }
ストレージ容量を増やすために2.3 SDS
すでにSDS操作機能のように宣言されて存在するタイプのストレージ容量を増やします。
SDS sdsMakeRoomFor(SDS秒、size_tのaddlen)
これは次のように手順:
- 文字列の長さのaddlenを保持するのに十分な空き容量がある、そこに返され、他の操作は、ビューSDS継続されていません。
- addlen元の長さのSDSを含む、所望の長さREALLOCATE記憶空間を算出し、残りのスペースの追加の予備的な部分。
- 新しい長さ、オリジナルの新しいタイプと同じタイプのヘッドは、より多くのスペースのs_reallocを割り当てるために使用される場合、新しいタイプのSDSヘッドを取得し、新しいヘッドタイプは、元と同じタイプでない場合、再割り当てs_allocを使用してメモリ、および元のコピーは、新しく割り当てられたスペースにコンテンツをSDS。
具体的な以下の機能を実現します:
SDS sdsMakeRoomFor(SDS S、size_tのaddlen){ ボイド * SHを、* newsh。 size_tの無駄 = sdsavail(S)。 size_tのLEN、NEWLEN。 CHAR型、oldtype = sの[ - 1 ]&SDS_TYPE_MASK。 int型hdrlen; / * 左の十分なスペースがある場合はできるだけ早く返します。* / 場合(無駄> = addlen)リターンS。 LEN = sdslen(S)。 SH =(チャー *)S- sdsHdrSize(oldtype)。 NEWLEN =(LEN + addlen)。 もし(NEWLEN < SDS_MAX_PREALLOC) NEWLEN* = 2 ; 他 NEWLEN + = SDS_MAX_PREALLOC。 タイプ = sdsReqType(NEWLEN)。 / * タイプ5は使用しないでください:ユーザーが文字列に追加され、タイプ5がある *空きスペースを思い出すことができないので、sdsMakeRoomFor()を呼び出さなければなりません すべての追加操作で*。* / 場合(タイプ== SDS_TYPE_5)=入力SDS_TYPE_8と、 hdrlen = sdsHdrSize(タイプ)。 もし(oldtype == タイプ){ newsh = s_realloc(SH、hdrlen + NEWLEN + 1 )。 もし(newsh == NULL)リターンNULL; S =(チャー *)newsh + hdrlen。 } 他{ / * ヘッダサイズの変化するので、前方の文字列を移動する必要がある *とのreallocを使用することはできません* / newsh = s_malloc(hdrlen + NEWLEN + 1 )。 もし(newsh == NULL)戻りNULL; memcpy((CHAR *)newsh + hdrlen、S、lenの+ 1 )。 s_free(SH)。 S =(チャー *)newsh + hdrlen。 S [ - 1 ] =タイプ; sdssetlen(S、LEN)。 } sdssetalloc(S、NEWLEN)。 リターン秒; }
2.4リリースの未使用のストレージ容量のSDS
未使用メモリ空間を解放するために必要なときLEN記録に従って、ヘッドALLOC割り当てられたメモリ空間、記録された実際の使用をlenのメモリ空間を記録SDSを用いてもよいし、圧縮空間s_reallocのs_allocの使用は、より小さなスペースを再配布、レリーズ古いメモリ。対応する機能は次のように宣言されています。
SDS sdsRemoveFreeSpace(SDS秒)
実質的に以下のステップを実行します。
- LENに従って新しい所望のSDS型メモリを算出します。
- 元の型と同じ新しいタイプのSDS、元のメモリ空間s_realloc圧縮を使用している場合。
- 新しい型が元の型をSDS場合は、新たに割り当てられたオリジナルコンテンツSDSをコピーするためのスペース、および元のメモリの解放を再割り当てs_alloc使用していません。
sdsRemoveFreeSpaceがsdsMakeRoomForが実質的に同じで達成SDS、ここに記載されていません。
さらにSDSツールは、猫操作、コピー操作、ll2str(整数文字列)、また、vprintf、操作(フォーマット操作)など、多くの機能を提供します。特定の実装のソースコードファイルを参照してくださいsds.c.