2017-04-05 95 views
8

我有这样的事情:列表<object>内存开销

List<object> res = new List<object>(); 
... 
while (...) 
{ 
    byte[] val = //get new byte[4] 
    res.Add(val); //if this is commented memory usage goes from 2Gb to 180Mb 
} 

return res; 

现在val总是字节[4]和有大约3700元。所以我认为res应该在37 * 10^6 * 4字节= 148 MB左右,但真正的内存使用量在2GB左右。如果我评论res.Add(val);,则内存使用率为100 MB。

那么内存去哪里?

enter image description here enter image description here

EDIT

我试图使用UINT代替字节[4],但结果是相同的: enter image description here

EDIT2

好的,使用uint而不是字节[4] List<uint>()而不是List<object>使内存大约300 MB。

+1

如何计算内存使用量?任务管理器? – HimBromBeere

+5

对于3700万个对象,2GB的容量降低到每个盒装值54个字节,包括运行时间(GC)的簿记和一般.NET的开销,并且您的程序不小,因为您指示100 MB的占用空间当它什么都不做时。你为什么认为'List '是相关的?数组是否显示相同的行为?你想解决什么问题? – CodeCaster

+0

@HimBromBeere使用VS调试器,查看屏幕截图 – ren

回答

7

这是一个分配大量微小物体的常见问题:物体开销(通常可忽视)会发挥作用。

37 * 10^6×4个字节= 148 MB

假设的4个字节的阵列将占有四个字节在存储器不正确。除了四个字节的有效负载之外,数组对象必须存储数组的长度,一个同步块和一个类型指针。这可以在32位系统上产生12个字节的开销,或者在64位系统上产生24个字节。

除了数组对象的单个开销之外,还需要考虑内存分配器的开销,内存对齐的开销以及垃圾回收器的开销。所有的事情放在一起,看到使用的总内存增长到2Gb并不是不合理的。

解决此问题的一种方法是切换到uint s的列表,每个列表占用四个字节。当您需要存储四个字节时,将它们转换为uint,并将其存储在列表中。当您需要返回字节时,请将uint转换为临时的四字节数组。使用BitConverter来处理在uint s和byte之间的转换。

+1

嗯,令人惊讶的是,这并没有减少内存,我把问题的屏幕截图 – ren

+1

@ren你使用'列表'或'列表'?对象列表将承载“装箱”该值的开销,这接近数组的开销。 uint列表的开销要小得多。 – dasblinkenlight

+1

是的,这个工作,内存现在〜300Mb。谢谢。 – ren