渐进的GC调用

时间:2012-04-09 21:34:33

标签: c# arrays memory-management hashtable

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

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

3 个答案:

答案 0 :(得分:2)

让垃圾收集器做它的事情。最有效的方法正是GC已经做到的:推迟收集直到实际必须完成。这样就不需要进行比必要更多的集合,并且所有内存回收工作可以一起编组到相对较少的collect调用中,因此它不必经常遍历对象图。

只要确保清除对象的任何引用,这样你就不会意外地使它保持活动的时间超过必要的时间,但只要你这样做,你就不应该真的需要做任何其他事情。

答案 1 :(得分:0)

除了一些非常具体和特殊的情况外,最好的策略是让垃圾收集器按照自己的时间表运行。它是一个高度调整的软件,对CLR的内部工作方式的了解比你或我更多,而且几乎总能做出比我们更好的决策。

如果您在完成对象后关注对象占用的内存,则可以在完成对它们的工作时将各个数组元素置空(可能会使对象更快地被收集)。 / p>

更重要的是,是否需要立即将所有数据保存在内存中?是否有可能一次只加载一点 - 比如从文件中逐步读取?如果是这样,您绝对可以选择用IEnumerable<T>替换数组,允许您根据需要懒洋洋地加载数据,并在完成后自动忘记它。这种方法可以保证降低内存消耗,但需要额外的一些额外计算。

答案 2 :(得分:0)

如果将字符串存储在数组中,则在迭代它们时它们都将保留在内存中。

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

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

对于哈希表,这种方法根本不起作用。在迭代时,您无法安全地从哈希表中删除条目。

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