C#List size vs double size

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

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

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

鉴于下面的代码

 var size = 1000000; var numbers = new List(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 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是8,000,036字节,底层数组是8,000,012字节。 这适用于引用类型( Array )通常的12字节开销和双倍的1,000,000乘8字节。 最重要的是List为上面显示的字段增加了另外24个字节的开销。

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

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