【发布时间】:2020-04-15 21:48:50
【问题描述】:
当我把这段代码放在一个小的控制台项目中时:
Console.WriteLine($"Mémoire avant allocation 1G: {GC.GetTotalMemory(false)}");
byte[] buf = new byte[1000000000];
Console.WriteLine($"Mémoire après allocation 1G: {GC.GetTotalMemory(false)}");
buf = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine($"Mémoire après libération 1G: {GC.GetTotalMemory(false)}");
我得到以下结果(如预期):
Mémoire avant allocation 1G: 30028 Mémoire après allocation 1G: 1000038252 Mémoire après libération 1G: 29472
现在我正在处理的大型应用程序中的代码完全相同,我得到了这个结果:
Mémoire avant allocation 1G: 153152496 Mémoire après allocation 1G: 1153152552 Mémoire après libération 1G: 1146813960
如您所见,GC.Collect 在这里什么都不做。
这是为什么呢?
【问题讨论】:
-
据我所知,垃圾收集器可以通过收集有关某个程序如何消耗内存的信息来修改条件何时以及如何检查和释放未使用的对象。在创建大量大对象的情况下,GC 策略可能与第一个描述的情况不同。
-
“大应用程序”是否在服务器操作系统上运行?垃圾收集在服务器操作系统上的行为非常不同。此外,GC.Collect 启动垃圾收集过程,不能保证垃圾收集的内容。在像 Windows 7/10 这样的“客户端”操作系统上,它更具侵略性,在服务器操作系统上,它允许更多的内存使用,因为垃圾收集是一个性能密集型过程。此外,您正在创建大字节数组,这些数组将直接进入大对象堆 (LOB),而在服务器操作系统上,它不会经常被垃圾收集。
-
附录:LOB=LOH,不是单独的而是直接进入gen2。有趣的东西:docs.microsoft.com/en-us/dotnet/standard/garbage-collection/…
-
对于这两种情况,PC 是相同的(Win10 有大量可用 RAM - 总共 64Go - 在两种情况下都没有内存压力)。 “大”应用程序只是一个经过很长一段时间(10 年左右)开发的应用程序,有几个团队在开发它,所以我对它的各个方面都不是很熟悉。