从C#中的大型数据结构中释放内存

我的模拟代码中有一些SortedListSortedDictionary结构,随着时间的推移,我会在其中添加数百万个项目。 问题是垃圾收集器没有快速释放足够的内存,因此应用程序的性能受到很大影响。 我的最后一个选择是使用GC.Collect()方法,以便我可以回收那个内存。 有没有人有不同的想法? 我知道Flyweight模式是另一种选择,但我希望其他建议不需要对我的代码进行大量重构。

我认为SortedList使用数组作为支持字段,这意味着在Large对象堆上分配大的SortedList 。 大对象堆可以进行碎片整理,这可能导致内存不足exception,而原则上仍有足够的可用内存。
看到这个链接 。

这可能是您的问题,因为对GC.collect的中间调用会阻止LOH在某些情况下进行严重碎片整理,这就解释了为什么调用它可以帮助您减少问题。

通过将大对象拆分成较小的片段可以减轻该问题。

你正在打击“没有免费午餐”的原则。 你不能假设列表中的数百万个项目不会影响性能。 只有SortedList <>应该是一个问题,它将开始在大对象堆中分配内存。 这个分配不会很快被释放,它需要第二代收集来再次从LOH中抽出东西。 此延迟不应影响程序的性能。

你可以做的一件事是避免内部数组的多个副本,当它继续增长时,SortedList <>会阻塞到LOH中。 尝试猜测容量的良好值,以便预先分配大型阵列。

接下来,使用Perfmon.exe或TaskMgr.exe并查看程序的页面错误增量。 你分配的时候应该很忙。 如果您看到低值(100或更低),那么您可能会遇到分段页面文件的问题。 在运行XP的旧机器上常见的祸害。 对磁盘进行碎片整理并使用SysInternals的PageDefrag实用程序可以创造非凡的奇迹。

我首先要对您的应用程序进行一些内存分析,以确保您从这些列表中删除的项目(我假设是从您的post编写方式发生的)实际上是正确发布的,而不是在各处闲逛。

我们在谈论什么样的性能以及在什么操作系统上? 如果我记得,GC将在需要时运行,而不是立即或甚至“很快”运行。 因此,任务管理器显示分配给您的应用程序的高内存不一定是个问题。 如果您将机器置于更高的负载下(例如运行多个应用程序副本)会发生什么? 在这种情况下,内存是否会被更快地回收,或者您是否开始耗尽内存?

我希望这些问题的答案能帮助你指明正确的方向。

好吧,如果你保留这些结构中的所有项目,GC将永远不会收集资源,因为它们仍然有对它们的引用。

如果需要收集结构中的项目,则必须将其从数据结构中删除。

要清除整个数据结构,请尝试使用Clear()并将数据结构引用设置为null 。 如果仍然没有足够快地收集数据,请调用CC.Collect()