我有一个在 Linux 上运行的 ASP.NET Core 应用程序(在 Docker 中,在 Kubernetes 上)。我遇到这样的情况:我的完全托管应用程序在 GC 堆上使用 5 MB,但应用程序保留 5 GB(并且将消耗更多,直到通过 OOM 终止)。我使用 dotMemory 收集了内存转储,可以看到内存被非托管内存消耗。GC.GetTotalMemory我通过调用vs得到了相同的图片Process.GetCurrentProcess().WorkingSet64。
该代码是完全托管的,主要是读取文件、处理文件并将处理后的数据存储在数据库中。我使用过DevArt.PostgreSql,但也尝试过Npgsql,但没有什么区别。我还使用单个原始的持久Socket连接。在给定的测试用例中,没有调用 ASP.NET Core 上的 Web API。dotMemory在这些库中以及我的代码部分中都没有显示任何托管泄漏。
内存使用情况将如下所示:
Process.GetCurrentProcess().WorkingSet64=582 MB / GC.GetTotalMemory=372 MB
过了一会儿跳到
Process.GetCurrentProcess().WorkingSet64=600 MB / GC.GetTotalMemory=5 MB
我可以使用以下代码强制执行此集合:
GC.Collect(2, GCCollectionMode.Forced, true, true);
GC.WaitForPendingFinalizers();
GC.Collect(2, GCCollectionMode.Forced, true, true);
Run Code Online (Sandbox Code Playgroud)
因此,我可以得出结论,超过 300 MB 的数据从 GetTotalMemory 转移到了workingSet64。我不知道还有什么办法可以得出这些数字。当内存再次填满时,它可能看起来像这样:
Process.GetCurrentProcess().WorkingSet64=1375 MB / GC.GetTotalMemory=4 MB
(few moments later)
Process.GetCurrentProcess().WorkingSet64=1433 MB / GC.GetTotalMemory=1081 MB
Run Code Online (Sandbox Code Playgroud)
在这种情况下,可以从WorkingSet中回收大量GC内存。然而,这个循环永远不会完美,WorkingSet64 …