NSStringストレージ管理-NSTaggedPointerString



Nsstring Storage Management Nstaggedpointerstring



NSString *strS = @'123456789' NSLog(@'%@ : %p',strS.class,strS) strS = [NSString stringWithFormat:@'1'] NSLog(@'%@ : %p',strS.class,strS) strS = [NSString stringWithUTF8String:'1234567'] strS = [NSString stringWithUTF8String:'abcdabc']//7 NSLog(@'%@ : %p',strS.class,strS) strS = [NSString stringWithUTF8String:'abcdabcd']//8 strS = [NSString stringWithUTF8String:'teeeeeeet']//9 NSLog(@'%@ : %p',strS.class,strS) strS = [NSString stringWithUTF8String:'eeeeeeeeee']//10 strS = [NSString stringWithUTF8String:'eeeeeeeeeee']//11 NSLog(@'%@ : %p',strS.class,strS) strS = [NSString stringWithUTF8String:'eeeeeeeeeeee']//12 NSLog(@'%@ : %p',strS.class,strS)

上記のコード出力は次のとおりです。

__NSCFConstantString : 0x10c843820 NSTaggedPointerString : 0xa000000000000311 NSTaggedPointerString : 0xa636261646362617 NSTaggedPointerString : 0xa040000000000049 NSTaggedPointerString : 0xa00000000000000b __NSCFString : 0x6000000315c0

ocストレージは主にデータ領域、ヒープ領域、スタック領域に分けられます。



  • __NSCFConstantString明らかに定数文字列、アドレス0x10c843820当然データ領域に格納されます。
  • __NSCFString ocオブジェクトとして表現NSStringカプセル化CFString0x6000000315c0アドレスは、この文字列オブジェクトがヒープに格納されていることを示しています。
  • NSTaggedPointerStringこのクラスは、これが文字列のタグ付きポインタへのポインタであることを示します。0xa636261646362617このアドレスがなぜそれほど異なるのですか?このクロック文字列のストレージポインタを簡単に紹介しましょう。

Appleで発売 64ビットアーキテクチャのA7デュアルコアプロセッサ iphone 5sの場合、メモリを節約し、実行効率を向上させるために、Appleは提案しました タグ付きポインタ の概念。元のオブジェクトがメモリを浪費する理由を見てみましょう。値が整数であるNSNumberオブジェクトを格納するとします。通常の状況では、整数がNSIntegerの通常の変数である場合、それが占めるメモリはCPUのビット数に関連しています。32ビットCPUでは4バイト、64ビットCPUでは8バイトです。 。の。ポインタタイプのサイズは通常、CPUビット数に関連しています。 1つのポインタが占めるメモリは、32ビットCPUでは4バイト、64ビットCPUでは8バイトです。したがって、通常のiOSプログラムでは、タグ付きポインターオブジェクトがない場合、32ビットマシンから64ビットマシンに移行した後、ロジックは変更されませんが、NSNumberやNSDateなどのオブジェクトが占有するメモリは2倍になります。

興味のある友人はそれを試すことができます、この技術を使用したNSStringの結果だけがここにリストされています。



前の場合@''シンボルによって作成された文字列は引き続き定数文字列です。これは変更されていませんが、採用されています。stringWithFormat NSStringメソッドなどの文字列オブジェクトの作成には違いがあります。

Appleの64ビットOC実装では、オブジェクトポインタのバイナリの最初のビットが1の場合、ポインタはタグ付きポインタです。
0xa000000000000311ここでaのバイナリは1010、最初のバイナリ1これがタグ付きポインタであることを示します010これがNSTaggedPointerStringクラスの最後の桁であることを示しますこのアドレスの文字列の数を示します。ここでは0001 1ビットの文字列があることを示します。ストレージに使用される実際のビット数は、中央の14ビットの16進数のみです。このアドレス自体は、実際には文字列の値を格納します。これは、&strSメモリ値に格納されていると言え、アドレスを装っただけで、データ領域に格納する必要はなく、ヒープを申請する必要もありません。スペース。

NSTaggedPointerStringは、ASCII、6ビットエンコーディング、および5桁エンコーディングの3つのエンコーディングメソッドを格納します。



ASCIIコード

NSTaggedPointerStringに保存されたコンテンツにより、最初と最後の桁が削除されることがわかりました。実際、真ん中の14ビットの16進文字しかありません。次に、ascllコードは8ビットのバイナリで構成されているため、ここでは(14 * 4)/ 8 = 7、8ビットです。 ascllコードは最大7文字を格納できます。 文字列の数は0から7の間です。

[NSString stringWithFormat:@'1']出力アドレス0xa000000000000311、その中31バイナリは0011 0001 ascllコードテーブルでの検索は「1」とまったく同じです。

[NSString stringWithUTF8String: 'abcdabc']ここでの出力は0xa636261646362617です。 ascllエンコーディングを使用する場合、文字列に対応するエンコーディングが右から左に格納されることがわかります。

6桁のコード:

NSTaggedPointerStringは、6ビットのバイナリエンコーディング(14 * 4)/ 6 = 9.333 ...を使用します。これは、最大9文字が格納されていることを示しています。 文字数8〜9

5桁のコード:

5ビットのバイナリコード(14 * 4)/ 5 = 11.2を使用すると、このコードは最大11文字を格納していることがわかります。 文字数は10〜11文字です

NSTaggedPointerStringストレージコードの6桁と5桁のエンコーディングは、通常のコードの文字の頻度に従ってソートされますが、静的ではありません。 Appleは継続的に文字の頻度を更新し、カウントします。システムは毎回異なる場合があります。最初の桁は文字eで、その後にi、l、o、tが続きます... 2つのエンコーディングは、コード化されたビットの数に応じて左から右になります。すべての文字がascllまたは6になるわけではないことは明らかです。 5桁のエンコード。これをエンコードできない場合、システムはNSTaggedPointerStringクラスを使用しません。



参照:
1.タグ付きポインタ文字列
2.iOSタグ付きポインター