.NET Core应用程序进程内存在对象被释放后不会减少。

8
我有一个问题,关于在Windows上运行的ASP .NET Core 2.1应用程序,它会增加内存消耗,最终崩溃并需要杀死.NET Core Host进程。我怀疑原因可能是后台每小时运行的同步任务,经确认禁用它可以解决该问题。
我使用VisualStudio 2019诊断工具对此同步任务进行了分析,发现了一种我无法理解的行为:

enter image description here

正如你所看到的,我拍摄了3个快照:

  1. 同步方法开始时
  2. 同步方法结束时
  3. 稍晚一些,当我们退出范围时

在快照表中,我看到一个对我来说似乎合理的行为:任务期间(2)堆大小显著增长,并在退出范围(3)时几乎恢复到初始大小(1)。然而,“进程内存”图表显示了不同的情况:内存消耗增加了,但从未下降。 我以发布模式使用dotnet run启动应用程序,并查看由.NET Core Host进程使用的内存时,发现相同的行为。

我有两个问题:

  1. 为什么堆大小和进程内存之间会有这种分歧?它们不应该密切相关吗?
  2. 这可能是我的Web应用程序崩溃的原因吗?看起来是这样,但内存消耗增加应该是暂时的,而不是永久的,直到崩溃。我该如何解决?

备注:我已经用一个简单的 .NET Core 控制台应用程序(2.1和2.2)复现了相同的行为,没有任何依赖项,因此这与 ASP 部分或任何其他库无关:

internal class Program
{
    private static void Main()
    {
        new Whatever().AllocateSomeStrings();
        // Snapshot3
        Console.ReadKey();
    }
}

public class Whatever
{
    public void AllocateSomeStrings()
    {
        // Snapshot1
        List<string> numbers = Enumerable.Range(0, 50000).Select(n => n.ToString()).ToList();
        // Snapshot2
    }
}

“我已经用一个简单的 .NET Core 2.1 控制台应用程序复现了相同的行为,没有依赖项。” - 你能分享一下吗?另外,你能验证一下这个问题是否仍然出现在 2.2 或者 3.0 上吗?虽然 2.1 作为 LTS 版本仍然得到支持,但了解这是否仍然是一个当前问题将会很有意思。 - poke
那么当它最终崩溃时,肯定是 OutOfMemoryException 吗?你观察到了那个异常吗? - Matthew Watson
1
你是在Linux上运行吗?服务器GC通常只会在系统面临内存压力时释放内存,而这在Linux上从不发生 - 相反,当内存耗尽时,占用最多内存的进程将被终止。 - Luaan
您的问题的答案如下: 我刚刚在我的问题中添加了简单的控制台应用程序代码。我已经尝试过2.1和2.2,结果相同,但还没有尝试3.0。 我正在Windows上运行。 我实际上看到了 OutOfMemoryException - Tao Gómez Gil
你好,最终你找到了解决这个内存问题的方法吗? - Konstantinos Papakonstantinou
显示剩余2条评论
1个回答

5
回答自己的问题:
  1. 堆大小在创建对象时增加,在GC处理时减少。当堆大小增加时,进程内存也会增加,但是当堆大小减小时,并不一定会减少进程内存。这些内存可能会一直分配给进程,除非其他进程需要它(机器可用内存变少),强制释放。这个过程不是由GC处理的,GC操作在进程级别上操作。参见:.NET进程分配的内存何时释放回Windows
  2. 我发现根本问题是代码中的内存泄漏,一个写得很差的while循环,修复后解决了应用崩溃问题。

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