.NET数组的内存布局

什么是.NET数组的内存布局?

拿这个数组为例:

Int32[] x = new Int32[10]; 

我明白,arrays的大部分是这样的:

 0000111122223333444455556666777788889999 

每个字符是一个字节,数字对应于数组中的索引。

另外,我知道所有对象都有一个types引用和一个同步块索引,所以上面可以调整为:

 ttttssss0000111122223333444455556666777788889999 ^ +- object reference points here 

此外,数组的长度需要被存储,所以也许这是更正确的:

 ttttssssllll0000111122223333444455556666777788889999 ^ +- object reference points here 

这是完整的吗? 数组中有更多的数据吗?

我问的原因是,我们正在试图估计一个相当大的数据语料库的几个不同的内存表示将会花费多less内存,并且数组的大小变化很大,所以开销可能有一个在一个解决scheme中产生了巨大的影响,但是在另一个解决scheme中可能没有那么多

所以基本上,对于一个数组来说,有多less开销,这基本上是我的问题。

而在arrays坏队伍醒来之前,解决scheme的这一部分是一个静态的一次构build一次引用的东西,所以使用可生成列表在这里是没有必要的。

伟大的问题。 我发现这篇文章里面包含了值types和引用types的框图。 另请参阅Ritcher的这篇文章 :

[snip]每个数组都有一些额外的开销信息与之相关联。 该信息包含数组的秩(维数),数组每个维的下界(几乎总是0)以及每个维的长度。 开销还包含数组中每个元素的types。

检查这个的一种方法是查看WinDbg中的代码。 所以给出下面的代码,让我们看看如何出现在堆上。

 var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

首先要做的是find实例。 因为我已经在Main()了一个本地,所以很容易find该实例的地址。

从地址我们可以转储实际的实例,这给了我们:

 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 

这告诉我们,它是我们的Int32数组,10个元素,总大小为52个字节。

让我们转储实例所在的内存。

 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个字节的括号。

  • 前四个字节是对01309584方法表的引用。
  • 然后四个字节的数组的长度。
  • 之后是数字0到9(每四个字节)。
  • 最后四个字节是空的。 我不完全确定,但我想这一定是在用于locking实例的情况下存储对syncblock数组的引用的地方。

编辑:忘了第一篇文章的长度。

列表有些不正确,因为romkyns指出实例实际上是从地址开始的 – 4,第一个字段是同步块。

好问题! 我想自己看看,这似乎是一个很好的机会尝试CorDbg.exe …

对于简单的整型数组来说,格式是:

 ssssllll000011112222....nnnn0000 

其中s是同步块,l是数组的长度,然后是单个元素。 看来终于有个0了,我不知道为什么。

对于multidimensional array:

 ssssttttl1l1l2l2???????? 000011112222....nnnn000011112222....nnnn....000011112222....nnnn0000 

其中s是同步块,t是元素的总数,l1是第一维的长度,l2是第二维的长度,然后是两个零,然后依次是所有元素,最后是零。

对象数组被视为整数数组,这次的内容是引用。 锯齿形数组是引用指向其他数组的对象数组。

一个数组对象将不得不存储它有多less维度和每个维度的长度。 所以至less还有一个数据元素添加到模型中