为什么.NET Core 2.0中的垃圾收集器不能释放所有内存?

3
我正在 net core 2.0 上运行简单的代码,垃圾回收后,我的程序仍然占用 140 MB 的内存。有人知道为什么吗?我该如何减少它?我还有一个问题。控制台应用程序和 Web 应用程序的垃圾回收有什么区别吗?
var rand = new Random();

var list = new List<Test>();

for(int i = 0; i < 10_000_000; i++)
{
    list.Add( new Test {
        Id  = i,
        Number = rand.NextDouble(),
        Number1 = rand.NextDouble(),
        Number2 = rand.NextDouble(),
        Number3 = rand.NextDouble(),
        Number4 = rand.NextDouble(),
        Number5 = rand.NextDouble(),
        Number6 = rand.NextDouble(),
        Number7 = rand.NextDouble(),
        Number8 = rand.NextDouble(),

    });
}

Console.WriteLine("End of generation");
Console.ReadLine();

for(int i = 0; i < list.Count; i++)
{
    list[i] = null;
}

list = null;

GC.Collect(1);

GC.WaitForPendingFinalizers();

GC.Collect(2);

GC.WaitForPendingFinalizers();

GC.Collect(3);

GC.WaitForPendingFinalizers();

Console.ReadLine();

你测试过这个在.NET框架上,才能说这是一个.NET Core的“问题”吗? - Camilo Terevinto
我在.NET Framework上尝试了一下,在发布和调试模式下都会回到10 MB。看起来内存问题只存在于.NET Core的调试模式中。在Core 2.0上以发布模式运行代码后,它正常工作。 - user9159375
@user9159375 - 你应该向微软报告这个问题。听起来像是一个bug,而且由于它在发布模式下不会发生,可能不会被其他人报告。 - NightOwl888
你如何测量RAM的消耗?即使GC为进程释放了内存,CLR可能不会立即将其返回给操作系统,或者操作系统可能不会立即标记它为空闲状态。 - Nick
4
将产生列表的代码放在一个单独的方法中运行,看看是否有所改变。调试会延长某些对象的寿命到方法结束,以便您检查变量。如果在方法的任何点创建了临时变量,那么将创建的变量更改为null并不重要,可能仍然存在一个悬挂的引用。如果您将此代码移动到一个单独的方法中并调用它,在开始收集垃圾之前,这样的临时变量将不再存在,并且可能会改变结果。 - Lasse V. Karlsen
显示剩余2条评论
2个回答

8

我测试了你的代码,和你描述的一样。我拍了一个快照并查看了对象,内存中仍然有一个 List<Test>

如果在发布模式下运行,所有内存都会被正常释放。

所以我猜,在调试模式下这是一种错误行为。

编辑:Lasse Vågsæther Karlsen发表了一个有趣的评论:

调试模式延长了某些对象的生命周期到方法结束,以便你检查变量。

我测试了一下,如果将产生列表的代码放在单独的方法中,所有内存都会被释放。


5
我认为这并不应该称作一个漏洞,很可能这就是它的预期工作方式。 - DavidG
1
“分离方法”的想法很好。这对我也起作用了。 - dpelisek

1
如果此引用类型(列表)仅在此方法中使用,则JIT编译器实际上可以将其分配到堆栈上,而不是堆上,并且使用Console.Readline();时,堆栈永远不会被取消分配,但我真的不知道如何测试这一点。
关于GC之间的区别,是的,我认为我们公司曾经遇到过问题,我们发现控制台应用程序的GC与Web应用程序的GC不同。 据我所记得,Web应用程序中的GC是以服务器模式运行的,但我不记得控制台应用程序的GC模式。
有关GC模式的更多信息,请参见:https://blogs.msdn.microsoft.com/seteplia/2017/01/05/understanding-different-gc-modes-with-concurrency-visualizer/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接