如何解决GC不会释放内存,但是会导致托管内存减少和非托管内存增加
我有一个在Linux(在Docker,在Kubernetes上)上运行的ASP.NET Core应用程序。我遇到的情况是,完全托管的应用程序在GC堆上使用5 MB,但该应用程序保留5 GB(并且将消耗更多空间,直到通过OOM将其杀死)。我使用dotMemory收集了一个内存转储,并且可以看到该内存已由非托管内存占用。我通过调用GC.GetTotalMemory
与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,true);
因此,我可以得出结论,有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
在这种情况下,可以从WorkingSet中回收大量GC内存。但是,这个周期从来都不是完美的,WorkingSet64的增加一直到50GB以上,并且由于OOM而终止了该过程。
该计算机具有较高的内核数(32)和RAM(64 GB)。我尝试了GC的两个变体,但没有区别。
以某种方式,内存不会释放回操作系统。
Gen 0和1为空。
任何建议,我将如何找到根本原因。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。