C#List <double> size vs double [] size </double>

时间:2009-10-02 07:51:55

标签: c# .net arrays generic-list

所以我只是在测试微软的CLR Profiler,我做了一个小程序,创建了一个包含1,000,000双打的List。我检查了堆,结果列出了&lt;&gt;大小约为124KB(我不记得确切,但它就在那附近)。这真的震撼了我的世界,如果它有100万双打怎么可能是124KB呢?无论如何,之后我决定检查双[1000000]。令我惊讶的是(不是因为这是我对List&lt;&gt; = P的预期),数组大小为7.6MB。巨大的差异!!

他们怎么会有所不同? List&lt;&gt;如何?管理它的项目是如此(令人难以置信)内存效率?我的意思是,它不像其他7.5 mb在其他地方,因为在我创建了100万双打之后,应用程序的大小大约增加了3或4 KB。

2 个答案:

答案 0 :(得分:18)

List<T>使用一个数组来存储值/引用,所以我怀疑除了增加的List<T>开销之外,大小会有任何差异。

鉴于以下代码

var size = 1000000;
var numbers = new List<double>(size);
for (int i = 0; i < size; i++) {
   numbers.Add(0d);
}

堆对于相关对象来说是这样的

0:000> !dumpheap -type Generic.List  
 Address       MT     Size
01eb29a4 662ed948       24     
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
662ed948        1           24 System.Collections.Generic.List`1[[System.Double,  mscorlib]]
Total 1 objects

0:000> !objsize 01eb29a4    <=== Get the size of List<Double>
sizeof(01eb29a4) =      8000036 (    0x7a1224) bytes     (System.Collections.Generic.List`1[[System.Double, mscorlib]])

0:000> !do 01eb29a4 
Name: System.Collections.Generic.List`1[[System.Double, mscorlib]]
MethodTable: 662ed948
EEClass: 65ad84f8
Size: 24(0x18) bytes
 (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
65cd1d28  40009d8        4      System.Double[]  0 instance 02eb3250 _items    <=== The array holding the data
65ccaaf0  40009d9        c         System.Int32  1 instance  1000000 _size
65ccaaf0  40009da       10         System.Int32  1 instance  1000000 _version
65cc84c0  40009db        8        System.Object  0 instance 00000000 _syncRoot
65cd1d28  40009dc        0      System.Double[]  0   shared   static _emptyArray
    >> Domain:Value dynamic statics NYI
 00505438:NotInit  <<

0:000> !objsize 02eb3250 <=== Get the size of the array holding the data
sizeof(02eb3250) =      8000012 (    0x7a120c) bytes (System.Double[])

因此List<double>是8,000,036字节,底层数组是8,000,012字节。这非常适合引用类型(Array)的通常12字节开销和双倍的1,000,000乘8字节。最重要的是List<T>为上面显示的字段增加了另外24个字节的开销。

结论:对于相同数量的元素,我没有看到List<double>占用的空间少于double[]的证据。

答案 1 :(得分:1)

请注意,List是动态增长的,通常每次达到内部缓冲区大小时都会增加一倍。因此,新列表最初会有4个元素数组,在添加前4个元素后,第5个元素将导致内部重新分配将缓冲区加倍(4 * 2)