为什么 net core 2.0 中的垃圾收集器不释放所有内存

Why doesn't garbage collector in net core 2.0 free all memory

我是 运行 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();

我测试了你的代码,确实和你描述的一样。拍了一张快照,看了一下对象,内存里还有一个List<Test>

如果您 运行 它处于释放模式,所有内存都会按预期释放。

所以我猜,这是调试模式下的 bug 行为。

编辑:

Debug extends the lifetime for some objects to the end of the method to allow you to inspect variables.

我对其进行了测试,如果将生成列表的代码放在单独的方法中,所有内存都会被释放。

如果此引用类型(列表)是此方法的本地引用类型,JIT 编译器实际上可以在堆栈而不是堆上分配它,并且 Console.Readline(); 堆栈永远不会被释放,但我真的不知道如何你测试一下。

关于 GC 之间的区别,是的,我认为我们公司曾经遇到过问题,我们实际上发现控制台应用程序的 GC 与 Web 应用程序的不同。据我所知,Web 应用程序中的 GC 是 运行 服务器模式,但不记得控制台应用程序的 GC 模式。

更多关于 GC 模式的信息:https://blogs.msdn.microsoft.com/seteplia/2017/01/05/understanding-different-gc-modes-with-concurrency-visualizer/