我可以说服 Garbage Collection 截断列表吗?数组?
Posted
技术标签:
【中文标题】我可以说服 Garbage Collection 截断列表吗?数组?【英文标题】:Can I persuade Garbage Collection to truncate a list? An array? 【发布时间】:2014-01-03 11:00:13 【问题描述】:如果我有一个要修剪的列表以节省内存,我似乎可以设置列表容量,然后等待 GC 释放内存。当 List 升级到下一代时,为其分配的内存似乎是列表容量的函数,而不是最初分配的内存。这节省了我明确的复制,最终意味着总共减少了 1 个副本。
var x = new List<double>(50000000) 1, 2, 3 ;
//Lots of memory used here
GC.Collect(2);
//Still lots of memory used
x.Capacity = 3;
GC.Collect(2);
//Much less memory now used
是否可以用数组以某种方式做同样的事情?
请注意,我不打算显式强制 GC - 这只是为了说明当 GC 最终发生时,内存被释放。
【问题讨论】:
没有。你可以自己“缩小”它***.com/questions/12231569/… 嗯 VB.NET 确实有ReDim Preserve
,但我不在电脑前使用 Reflector 来确认它是如何完成的。
我认为您假设设置容量不是将内部数组复制到较小的数组
ReDim 创建一个新的数组副本——它只是语法糖msdn.microsoft.com/en-us/library/w8k3cys2.aspx
@JamesB - 是的,你是对的。这个问题现在变得无关紧要了。
【参考方案1】:
只需使用TrimExcess
或List<T>
。
这相当于list.Capacity = list.Count
,它分配一个大小为list.Count
的新数组并将所有元素复制到其中。
您可以对数组使用相同的策略,但您必须自己编写代码:
int[] arr = new int[50000];
int count = 3;
int[] compact = new int[count];
Array.Copy(arr, compact, count);
arr = null;
【讨论】:
OP 询问的是数组,而不是列表。 @Spikeh Well 列表在标题中提到,代码具有List<double>
...所以我有点不同意你的评论。虽然这个答案确实缺少很多其他细节。
@AdamHouldsworth “是否可以用数组以某种方式做同样的事情?”。这是一个问答网站,这是这里唯一的问题......
@Spikeh 问题的标题是“我可以说服垃圾收集器截断列表吗?一个数组?”。如果有的话,它是模棱两可的。
在我的回答中用Array.Resize(ref arr, count)
写这个更优雅。当然,它仍然是分配一个新的数组并将项目复制过来。【参考方案2】:
恐怕不会。数组,就其本质而言,是固定大小的。
http://msdn.microsoft.com/en-us/library/9b9dty7d.aspx
具体来说:
维度的数量和每个维度的长度是 在创建数组实例时建立。这些值不能 在实例的生命周期内发生变化。
不过,您可以通过将数组元素设置为 null 来释放内存。当然,您可以手动调整数组大小,但这需要您创建另一个数组并将相关元素复制到其中。
【讨论】:
【参考方案3】:在幕后,x.Capacity = 3;
或 x.TrimExcess()
会将保存它们的私有数组中的所有条目复制到一个新的小数组中。稍后将收集巨大的数组。
要为自己的数组做类似的事情,你可以这样做:
var y = new double[50000000];
//Lots of memory used here
GC.Collect(2);
//Still lots of memory used
Array.Resize(ref y, 3);
GC.Collect(2);
//Much less memory now used
文档:Array.Resize<T>
method
【讨论】:
@Rob 请记住,List<T>
类有一个字段private T[] _items;
,它包含一个包含项目的数组,并且数组中可能还有一些额外的空间。如果更改Capacity
,则旧的_items
实例将被废弃,并创建一个新数组。【参考方案4】:
我认为这相当于您的列表示例
var x = new Double[50000000];
//Lots of memory used here
GC.Collect(2);
//Still lots of memory used
var y = new Double[3];
Array.Copy(x, 0, y, 0, 3);
x = y;
GC.Collect(2);
//Much less memory now used
【讨论】:
以上是关于我可以说服 Garbage Collection 截断列表吗?数组?的主要内容,如果未能解决你的问题,请参考以下文章
Garbage-First Garbage Collection
Java Garbage Collection Basics--转载