【问题标题】:C# List<double> size vs double[] sizeC# List<double> 大小与 double[] 大小
【发布时间】:2009-10-02 07:51:54
【问题描述】:

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

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

【问题讨论】:

  • 您的意思是“应用程序的大小大约大 3 或 4 KB”。数组是动态分配的,因此结果 exe 文件无关紧要。而是查看任务管理器“Mem Usage”参数

标签: c# .net arrays generic-list


【解决方案1】:

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

给定下面的代码

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&lt;double&gt; 是 8,000,036 字节,而底层数组是 8,000,012 字节。这非常适合引用类型 (Array) 的通常 12 字节开销和双精度的 1,000,000 乘以 8 字节。除此之外,List&lt;T&gt; 还为上面显示的字段增加了 24 字节的开销。

结论:我没有看到任何证据表明List&lt;double&gt; 对于相同数量的元素会比double[] 占用更少的空间。

【讨论】:

  • 没错,我检查了三次,大小几乎一样,实际上List略大。我不知道第一次可能出了什么问题,我确实在使用 CLR 分析器运行应用程序时遇到了一些问题,所以当我运行 1,000,000 双打代码时,也许我正在查看应用程序的不同实例。感谢您解决这个问题。
  • Carlo,我已经学会质疑分析/剖析工具的所有结果,并且总是得到“第二意见”,即使结果符合我的预期。很多时候它只是无法解释,但有时隐藏在“奇怪”背后的更深层次的理解。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-25
    • 2014-05-06
    • 2018-04-21
    • 2014-02-14
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多