質問
.NET 配列のメモリ レイアウトは何ですか?
たとえば、次の配列を考えてみましょう。
Int32[] x = new Int32[10];
配列の大部分は次のようになっていると理解しています。
0000111122223333444455556666777788889999
ここで、各文字は 1 バイトであり、数字は配列のインデックスに対応します。
さらに、すべてのオブジェクトに型参照と syncblock-index があることがわかっているため、上記をこれに合わせて調整できます。
ttttssss0000111122223333444455556666777788889999
^
+- object reference points here
さらに、配列の長さを保存する必要があるため、おそらくこれはより正確です。
ttttssssllll0000111122223333444455556666777788889999
^
+- object reference points here
これで完了ですか?配列にはさらにデータがありますか?
私が尋ねている理由は、かなり大きなデータ コーパスのいくつかの異なるメモリ内表現がどれだけのメモリを使用するかを見積もろうとしていることと、配列のサイズがかなり異なるため、オーバーヘッドが発生する可能性があるためです。 1 つのソリューションでは大きな影響がありますが、もう 1 つのソリューションではそれほど大きな影響はないかもしれません。
基本的に、配列の場合、どのくらいのオーバーヘッドがあるのか、それが基本的な私の質問です。
そしてその前に、 配列が悪い 分隊が目覚めると、ソリューションのこの部分は静的に一度だけ参照して頻繁に構築するタイプのものであるため、ここでは拡張可能なリストを使用する必要はありません。
解決
グレート質問です。私はこのnoreferrer"> 記事をrel="nofollow href="https://web.archive.org/web/20150110150255/http://msdn.microsoft.com/en-us/magazine/cc301755.aspx"このになるRitcherは述べます:
[中略]各アレイは、いくつかの追加を有します に関連するオーバーヘッド情報 それ。この情報は、ランクが含まれています アレイの(次元数) 各次元の下限 配列(ほとんど常に0)、および 各次元の長さ。オーバーヘッド また、各要素の種類が含まれています 配列内ています。
他のヒント
これを調べる 1 つの方法は、WinDbg のコードを確認することです。以下のコードが与えられた場合、それがヒープ上でどのように表示されるかを見てみましょう。
var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
最初に行うことは、インスタンスを見つけることです。これをローカルにしたので、 Main()
, 、インスタンスのアドレスを見つけるのは簡単です。
アドレスから実際のインスタンスをダンプできます。これにより、次のことがわかります。
0:000> !do 0x0141ffc0
Name: System.Int32[]
MethodTable: 01309584
EEClass: 01309510
Size: 52(0x34) bytes
Array: Rank 1, Number of elements 10, Type Int32
Element Type: System.Int32
Fields:
None
これは、それが 10 個の要素と合計サイズ 52 バイトを持つ Int32 配列であることを示しています。
インスタンスが配置されているメモリをダンプしましょう。
0:000> d 0x0141ffc0
0141ffc0 [84 95 30 01 0a 00 00 00-00 00 00 00 01 00 00 00 ..0.............
0141ffd0 02 00 00 00 03 00 00 00-04 00 00 00 05 00 00 00 ................
0141ffe0 06 00 00 00 07 00 00 00-08 00 00 00 09 00 00 00 ................
0141fff0 00 00 00 00]a0 20 40 03-00 00 00 00 00 00 00 00 ..... @.........
01420000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01420010 10 6d 99 00 00 00 00 00-00 00 01 40 50 f7 3d 03 .m.........@P.=.
01420020 03 00 00 00 08 00 00 00-00 01 00 00 00 00 00 00 ................
01420030 1c 24 40 03 00 00 00 00-00 00 00 00 00 00 00 00 .$@.............
52バイトに括弧を挿入しました。
- 最初の 4 バイトは、01309584 のメソッド テーブルへの参照です。
- 次に、配列の長さとして 4 バイトを指定します。
- その後に 0 ~ 9 の数字 (各 4 バイト) が続きます。
- 最後の 4 バイトは null です。よくわかりませんが、インスタンスがロックに使用されている場合、syncblock 配列への参照が保存される場所に違いないと思います。
編集:初投稿で長さを忘れてしまいました。
romkyns が指摘しているように、インスタンスは実際にはアドレス 4 から始まり、最初のフィールドは Syncblock であるため、このリストは少し間違っています。
グレート質問!私は自分自身のためにそれを見てみたかった、そしてそれは試してみる良い機会だったようCordbg.exeに...
単純な整数のアレイのフォーマットであると思わ
ssssllll000011112222....nnnn0000
ここで、Sはシンクブロック、L配列の長さ、および個々の要素です。それは私がそれである理由はわからない、最後の最後に0があるようです。
多次元アレイの場合:
ssssttttl1l1l2l2????????
000011112222....nnnn000011112222....nnnn....000011112222....nnnn0000
Sはシンクブロックである。ここで、、要素の総数T、最初の次元の長さをL1、第2の寸法の長さをL2と、2つの順次の全ての要素が続くゼロ?、そして最終的にゼロ再びます。
オブジェクト列を整数配列として扱われ、その内容は、この時間参照です。ギザギザの配列は参照が他の配列を指すオブジェクト配列である。
配列オブジェクトは、それがあり、各寸法の長さをどのように多くの寸法格納しなければなりません。だからあなたのモデルに追加するために、少なくとも1つのより多くのデータ要素がある。