我可以说服 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】:

只需使用TrimExcessList&lt;T&gt;

这相当于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&lt;double&gt;...所以我有点不同意你的评论。虽然这个答案确实缺少很多其他细节。 @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&lt;T&gt; method

【讨论】:

@Rob 请记住,List&lt;T&gt; 类有一个字段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--转载

GC(Garbage Collection)垃圾回收机制

garbage collection - 垃圾收集

java 垃圾收集(Garbage Collection)之 哪些内存需要回收

从ASP.NET Core 3.0 preview 特性,了解CLR的Garbage Collection