【问题标题】:How free memory used by a large list in C#?C# 中的大列表使用了多少空闲内存?
【发布时间】:2013-07-31 02:11:12
【问题描述】:

我有一个名为Population 的列表,它包含了很多职位,但有时我会停止使用它。如何释放资源? 那么这是部分代码:

 private List <BasePopulation> Population=new List <BasePopulation>();
 Population.SomeMethod();
 Population.Clear();

我使用了 Clear 方法,但不起作用。有什么想法吗?

【问题讨论】:

标签: c# list garbage-collection


【解决方案1】:

编辑,改写我关于处置的答案。 好吧,当我输入 Clean 时,我一定是在想象一些事情。我假设如果清除列表中的所有项目不是免费资源,那么您尝试释放的资源是不受管理的。基于该假设,您需要 BasePopulation 来实现 IDisposable,以便当垃圾收集器拾取该对象时,可以释放这些资源。

http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

【讨论】:

  • IDisposable 的实现应该如何帮助“更快地接受它”?
  • 对不起,这是清除方法
  • 你还是错了。建议你放弃,去了解一下 GC。
  • OP 对非托管资源只字未提。此外,“释放资源”并不意味着“释放对象使用的内存”。
  • 顺便说一句,这里有一个很好的article,关于 GC 的工作原理。
【解决方案2】:

你能做的最好的事情就是什么都不做。垃圾收集器 GC 会自动为您完成这项工作。由于 List 不是 IDisposable,因此您无法处置它。

Clear 只会从 List 中删除元素,但不会释放它。

【讨论】:

  • “垃圾收集器”缩写为“GC”,而不是“GAC”。 “GAC”是“全局程序集缓存”。
【解决方案3】:

好吧,既然垃圾收集器 (GC) 会为您处理内存管理,那么您可以做的第一件事就是删除对列表(以及包含的元素)的所有引用,以便 GC 能够下次删除。例如,您可以通过显式设置来做到这一点

Population = null;

如果这对您来说还不够,例如因为您真的渴望摆脱现在和的对象可以接受非最佳运行时行为,您可以告诉 GC现在通过

开始收集对象
GC.Collect();

有关此方法的更多信息可以找到here

如上所述,这种做法会导致性能损失,因为它会强制 GC 在程序中通常不会清理的某个点清理资源。因此,通常不鼓励直接调用该方法,但如果这确实是您应用程序中的一个特殊点,它可能会满足您的需求。作为一个实际的例子,我已经成功地改善了一个程序中的峰值内存使用率,该程序在初始化期间需要大量对象,一旦实际程序执行开始就可以丢弃这些对象。在这里,初始化后调用GC.Collect() 的性能损失是合理的。

【讨论】:

  • 但是不能保证GC.Collect() 会收集到这个精确的人口对象。它会回收东西,但不一定是所有东西。
  • 是的,完全正确。但如果情况合适,至少值得一试(见我的更新)
  • 我听说Population = null; 会让事情变得更糟。它构成了对Population 的引用,因此将GC 延迟到该引用之后。你最好什么都不做。
  • 但是如果你不摆脱对对象的引用,那么 GC 将无法收集对象(除非包含 Population 的对象本身正在被收集)
  • 设置对null 的引用是取消其指向的对象的有效方法。事实上,这可能是唯一的方法。想想一个拥有大byte[](类成员)的单例类。当不再需要它时,您还要如何解除它?我真的看不出这个答案有什么问题。我错过了什么吗?
【解决方案4】:

问题可能是Clear 没有按照您的想法进行操作。 Clear 只是将 List 标记为空,而不调整它在幕后使用的内部数组的大小。但是,它将删除对单个 BasePopulation 实例的所有引用。因此,如果没有其他数据结构引用它们,它们将有资格进行垃圾收集。但是,它不会直接减小List 的大小。我刚刚使用 ILSpy 验证了这一点。

你有两个选择。

  1. 设置Population = null。这将取消整个对象实例的根,使其符合垃圾回收条件。

  2. 在此List 上致电TrimExcess。这将调整内部数组的大小。

【讨论】:

  • 将列表设置为空不是多余的吗?如果我没记错的话,一旦 Jitter 检测到该对象将不再被读取,而不是在引用变为 null 时,该对象就有资格进行 GC。
  • @Pierre-LucPineault:你是对的。好吧,除了 local 引用。对于问题中的 类成员 引用,垃圾收集器无法执行相同的优化,因为很难(或可能)预测将来是否会读取它。
  • @BrianGideon:我也有类似的问题。我有 C# 中的列表,其中包含许多项目。我想释放这个列表占用的内存。这样我就可以将新项目添加到列表中。释放此内存的最佳方法是什么?
  • @Giorgi:我的回答中的#1 或#2 是否有任何理由不适合你?
  • @BrianGideon:我将使用#1。将列表引用设置为 NULL。我需要将项目添加到列表中。但是每次我添加一些固定数量的项目时,我都可以 NULL 列表,例如,在我添加 100 000 个项目后,我会将它 NULL 以便我可以再添加 100 000 个等(因为我不需要旧的不再)。没事吧?
【解决方案5】:

您必须清除列表,然后调用 GC 将其从内存中删除。用广泛的方法如下:

public static void ClearMemory<T>(this List<T> lista)
{
    int identificador = GC.GetGeneration(lista);
    lista.Clear();
    GC.Collect(identificador, GCCollectionMode.Forced);
}

【讨论】:

    猜你喜欢
    • 2012-09-18
    • 2016-06-30
    • 2018-05-02
    • 2015-03-21
    • 1970-01-01
    • 2010-09-08
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多