有没有 .NET 大神帮忙看看困扰了好几个大神一年的内存泄露问题,优化了一年越变越严重,现在一小时崩一次

2024-09-26 17:00:02 +08:00
 drymonfidelia
这一年在 V 站关于这个问题已经发了好几个贴了,一直没解决 /t/1037900
已经从 ASP.NET Core 5 升级到 6 了,之前升过 8 内存泄露更严重了,又退回 6
最早加每 5 分钟强制 GC 一次,缓解了几个月,又开始两天一崩
然后搞了双实例负载均衡,两台机器 4 小时重启一次,重启时间错开,缓解了几个月
最近请求量翻了两倍,然后变成了一小时一崩,这么频繁重启再接下去肯定会出现重启也解决不了问题的情况,只好再来求助
目前请求量是每天 6~9 千万(客户端大量轮询请求,随硬件分发无法更新,导致请求量比较大)
按照 https://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/debug-memory-leak 的教程,运行 10 分钟后抓取 dump 的 heap statistics 如下
https://pastebin.com/BnxB8S0R

另外 analyze 的时候所有命令都提示 ERROR: The GC heap is not in a valid state for traversal. (Use -ignoreGCState to override.) 加上 -ignoreGCState 又不返回内容,不知道为什么,stackoverflow 上的几个方法都无效
5557 次点击
所在节点    .NET
26 条回复
Metatron7
2024-09-26 17:10:41 +08:00
supemaomao
2024-09-26 17:31:15 +08:00
给个建议,不知道适不适合 op ,如果你能在本机调试复现的话,用 JB 的 dotMemory (其它的当然也行) 跑一下,每隔 10 分钟拍一个快照,对比快照能知道是哪里的内存没被释放。如果是在服务器上的话,那我就没试过了。
Bazingal
2024-09-26 17:37:50 +08:00
大于 0.5MB 的对象加起来才 900M ,总共占用 7G 多,应该是大量小对象占用的
sss15
2024-09-26 17:52:51 +08:00
我也想到了这个人,但没想起名字,github 和博客园都私信找他看看吧,他的博文都是处理这种的
0o0o0o0
2024-09-26 17:54:54 +08:00
这个统计总和才 900 多 MB ,得把小于 0.5M 的,也就是所有的对象的统计输出都发出来才行
luckybricks9711
2024-09-26 17:56:47 +08:00
试过 dumpobject 吗,堆上小对象是什么内容?有 full dump 会好查点。
0o0o0o0
2024-09-26 17:59:47 +08:00
最好是可以在本地调试状态复现,使用 vs 的快照分析,可以具体查看对象大小以及依赖关系,可以很快速找到根源
luckybricks9711
2024-09-26 18:00:11 +08:00
查是肯定能查出来的,用 debugdiag 连续抓几个 dump 对着看,才能找出是哪些对象在增加内存,如果还不好定位问题还有 Time Travel Debugging
sss15
2024-09-26 18:03:08 +08:00
你只给了一个站 10 分钟后抓取的 dump ,Total 12,315,255 objects, 7,342,657,549 bytes
你是不是等 10 分钟后再抓一个 dump ,看看总量变化是多少,占用内容变化是多少,这个 dump 应该是堆的内容,只能知道内存中的变量有没有变化,空间占了多少。
你还需要 dump 一个栈的内容,看看当前执行的方法情况,才能定位到具体代码可能在哪里发生泄漏
hez2010
2024-09-26 20:25:49 +08:00
如果可以的话建议把 dotnet-dump collect 生成的 dump 文件发给会分析的人去看(里面可能包含你们业务的数据因此要谨慎)。
shapper
2024-09-26 20:55:32 +08:00
奔溃日记和调用栈信息都没有,错误描述都没有,也没有帮你猜错误吧。。。。
FFFFourwood
2024-09-26 21:17:33 +08:00
我们有个产品从 7 升到 8 内存泄漏严重.…
我们研究了俩月 无果 ,最后在 azure 上把内存拉高了……
ZZ74
2024-09-26 21:21:40 +08:00
没对比,没法看。盲猜问题出在 Core.Models.Order 涉及 UserPricePolicy 逻辑相关。有可能是外包水平的码农写逻辑时无脑查几乎所有数据
ke1e
2024-09-26 21:33:54 +08:00
很简单,用 Rust 重写
locksheep
2024-09-26 22:28:12 +08:00
贴的 Text 里好像有很多 EntityQueryable 查询和 ChangeTracker 追踪检测更改的,不知道是不是因为在查询时一直追踪导致的问题……菜鸡默默围观……
https://blog.csdn.net/ousetuhou/article/details/135218175
https://blog.csdn.net/dongnihao/article/details/126475145
https://learn.microsoft.com/zh-cn/ef/core/change-tracking/change-detection
csys
2024-09-26 23:24:59 +08:00
我看了下原帖
> 查了很多文档 gcdump 都是不会去触发 GC 的

我不知道你查的什么文档
但是官方文档是明确有说
> To walk the GC heap, this command triggers a generation 2 (full) garbage collection

然后
> 如果运行 dotnet-gcdump 则能立即恢复正常水平
gc 能回收,说明不是泄露

有极大概率是你分配的大对象太多了,大对象在 LOH 里不会被优先回收

解决方案:
1. 好好优化下自己的代码,减少巨大对象,会频繁创建的大对象不要 new ,用 ObjectPool
2. 调整 GCLOHThreshold ,让大对象别进 LOH
ppxppx
2024-09-26 23:32:53 +08:00
@ke1e #14 什么语言都避免不了泄露吧。
holinhot
2024-09-27 03:49:15 +08:00
@ppxppx PHP 这种可以吧
HaroldFinchNYC
2024-09-27 04:22:24 +08:00
@Metatron7 这哥们看着确实不错,有点水平
neilq
2024-09-27 09:25:00 +08:00
- 一些配置信息用 redis 做一下缓存,比如 Models.Setting ,Models.WxReplyRule 等,不要每次都从数据库查
- 我怀疑程序大量使用了 static 变量缓存数据,还是某些表的全量数据
- Models.Order 存在 select all 到内存中情况 ,WxReplyRule 疑似也存在这个情况
- 随机数生成算法再优化一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1076054

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX