很长时间以来我都在公司dotnet开发的软件上做各种性能优化,包括各种崩溃、线程池资源不足、死锁、以及很多性能慢的代码问题等,类似这种cpu相关问题都比较好查出来。
这个过程中经常遇到内存占用过高的问题,也是各种办法都试用了一遍,包括DOTNET GC相关的各种配置,还给docker加内存限制,但是一直都解决不了,比如以下这些:
- 服务器模式:https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector#workstation-vs-server
- 后台垃圾回收:https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector#background-gc
- 动态适应应用程序大小 (DATAS):https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector#dynamic-adaptation-to-application-sizes-datas
- 高内存百分比:https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector#high-memory-percent
- 节省内存:https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector#conserve-memory
以上全部解决不了问题,通过dump-counters诊断看,GC012代以及LOH等占用都不高,但是WorkingSet占用是它们总和的好几倍,并且长时间保持这个状态。意思就是程序实际并没有使用太多内存,但是整个进程看内存占用却很高,似乎GC工作了但并没有把内存释放回操作系统。通过dump分析内存发现大量的空闲内存,碎片也没有那么多。空闲的内存是程序曾经高负载时申请使用的,之后低负载就没有释放回操作系统。
搜索后发现了两个dotnet的issues:
https://github.com/dotnet/runtime/issues/90640
https://github.com/dotnet/runtime/issues/49317
看来遇到这个问题的不只我一个人,似乎从dotnet7开始就会有这个问题,dotnet8加入的DATAS配置也无法解决这个问题。
按照这个issue说的加这两个环境变量,验证发现真的可以解决问题,只是cpu占用会稍微多点,这个可以接受。
MALLOC_ARENA_MAX: 2
MALLOC_TRIM_THRESHOLD_: 85000
这个问题可能针对的是不太单纯的应用程序,会出现有时需要更多内存,而常规情况下只需要少量内存的情况。
标签:collector,占用,dotnet,内存,https,DOTNET,runtime,com From: https://www.cnblogs.com/pains/p/18535414