在C#中,假设您运行许多线程,使用大量对象和RAM进行大量计算。最后,所有线程都完成了。然后你运行GC.Collect()
。你就是不要停止这个过程。
除非您在静态变量中存储对某些对象的引用,否则我认为最终使用的RAM会回到0,除了加载的DLL或者使用大量RAM的东西(很多意味着几GB) )。
是真的吗?
我们可能没有意识到剩余的大量RAM使用情况吗? (不包括由错误代码引起的内存泄漏)
答案 0 :(得分:0)
我们可能没有意识到剩余的大量RAM使用情况吗?
是。实际上GC.Collect()
不会收集所有已分配的内存。它只收集所有“小”对象的世代0,1,2。
注意:甚至不清楚GC.Collect()
是否总是导致0,1和2代的完整垃圾收集。人们有不同的策略来处理它但我不想详细说明因为我没有最终的答案,它似乎依赖于.NET版本。
还有另一个堆大对象堆,有时称为第4堆(甚至第3代,这不是一个好名字),其中分配了大小> 85000的所有对象。
这个堆的功能完全不同。阅读例如:
大对象堆看起来是由进程(由Windows)保留的,而它实际上充满了可以被新(大)对象使用的“漏洞”,并被C#内存管理器看作是免费的。
在.NET 4.5.1之前无法手动压缩大对象堆。它只发生在CLR需要/想要的时候。
CLR是否经常压缩LOH取决于您使用的垃圾收集器。通常,ASP.NET中默认使用的server GC不压缩LOH。实际上,这适用于.NET 4.5,但可能在下一版本中发展。在.NET版本中,管理LOH的策略往往会发生很大变化。并非所有解释过的细节都是正确的。
据我所知,这可能是观察几GB剩余RAM(不是内存泄漏)的主要原因。大多数情况下这不是问题。你会在这里找到更多:When is memory, allocated by .NET process, released back to Windows