2

有没有一种有效的方法将数组的部分内存返回给系统?我正在使用 C# 遍历一个大字符串数组和一个包含(> 100k 个元素)的哈希表,并且在我完成它们后将单个元素设置为 null。我已经尝试在各个级别和整个循环中调用垃圾收集器,但它们都没有将内存返回给系统(完全调用垃圾收集器并等待挂起的终结器会导致我的代码变得非常缓慢且无响应)。
我考虑过将数组分成 n 部分并在每个部分完成后调用 gc 但这似乎很乱

GC.Collect(1);
GC.Collect(2);
....
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
4

3 回答 3

2

让垃圾收集器做它的事情。最有效的方法正是 GC 已经做的:推迟收集,直到它们真正必须完成。这样一来,它就不必进行不必要的收集,并且所有内存回收工作都可以集中到相对较少的收集调用中,因此它不必过于频繁地遍历对象图。

只需确保清除对该对象的所有引用,这样您就不会意外地使其存活时间超过必要的时间,但只要您这样做,您就不需要做任何其他事情。

于 2012-04-09T21:48:52.447 回答
0

除了一些非常特殊和例外的情况外,最好的策略是让垃圾收集器按照自己的时间表运行。这是一款经过高度优化的软件,比你我更了解 CLR 的内部工作原理,而且几乎总是会做出比我们更好的决策。

如果您在处理完对象后担心对象消耗的内存,则可以在完成对它们的工作时将各个数组元素清空(可能使对象可以更快地被收集)。

更重要的是,是否需要一次将所有数据保存在内存中?是否可以一次只加载一点 - 例如,从文件中增量读取?如果是这样,您绝对可以选择将数组替换为IEnumerable<T>,从而允许您根据需要延迟加载数据,并在完成后自动忘记它。这种方法可以保证降低您的内存消耗,但代价是一些轻微的额外计算。

于 2012-04-09T22:02:48.543 回答
0

如果您将字符串存储在一个数组中,那么当您遍历它们时,它们都将保留在内存中。

实际的迭代不会大大增加内存压力:您创建的任何新对象都将被有效地进行垃圾回收。

null对于数组的特定情况,您可以在读取数组条目后将其设置为。我会反对它:如果您在迭代开始时没有出现内存不足的问题,那么您可能也会在其余部分中幸存下来。一旦不再需要它,请确保对数组的所有引用都清空。在调试时,您可以在您认为不再引用该数组的位置添加 GC.Collect()。您应该观察到分配的内存大幅下降。如果这没有发生,则您在其他地方有更多对数组的引用或对数组内容的引用。

对于哈希表,这种方法根本行不通。在迭代它们时,您不能安全地从哈希表中删除条目。

现在,如果您使用的是哈希表,这意味着您并不真正关心项目的顺序。在这种情况下,您可以重新设计算法以在读取数据时对其进行处理,而无需将其保留在数组或哈希表中。

于 2012-04-09T22:04:41.953 回答