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

68 天前
 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 上的几个方法都无效
3837 次点击
所在节点    .NET
26 条回复
Metatron7
68 天前
supemaomao
68 天前
给个建议,不知道适不适合 op ,如果你能在本机调试复现的话,用 JB 的 dotMemory (其它的当然也行) 跑一下,每隔 10 分钟拍一个快照,对比快照能知道是哪里的内存没被释放。如果是在服务器上的话,那我就没试过了。
Bazingal
68 天前
大于 0.5MB 的对象加起来才 900M ,总共占用 7G 多,应该是大量小对象占用的
sss15
68 天前
我也想到了这个人,但没想起名字,github 和博客园都私信找他看看吧,他的博文都是处理这种的
0o0o0o0
68 天前
这个统计总和才 900 多 MB ,得把小于 0.5M 的,也就是所有的对象的统计输出都发出来才行
luckybricks9711
68 天前
试过 dumpobject 吗,堆上小对象是什么内容?有 full dump 会好查点。
0o0o0o0
68 天前
最好是可以在本地调试状态复现,使用 vs 的快照分析,可以具体查看对象大小以及依赖关系,可以很快速找到根源
luckybricks9711
68 天前
查是肯定能查出来的,用 debugdiag 连续抓几个 dump 对着看,才能找出是哪些对象在增加内存,如果还不好定位问题还有 Time Travel Debugging
sss15
68 天前
你只给了一个站 10 分钟后抓取的 dump ,Total 12,315,255 objects, 7,342,657,549 bytes
你是不是等 10 分钟后再抓一个 dump ,看看总量变化是多少,占用内容变化是多少,这个 dump 应该是堆的内容,只能知道内存中的变量有没有变化,空间占了多少。
你还需要 dump 一个栈的内容,看看当前执行的方法情况,才能定位到具体代码可能在哪里发生泄漏
hez2010
68 天前
如果可以的话建议把 dotnet-dump collect 生成的 dump 文件发给会分析的人去看(里面可能包含你们业务的数据因此要谨慎)。
shapper
68 天前
奔溃日记和调用栈信息都没有,错误描述都没有,也没有帮你猜错误吧。。。。
FFFFourwood
68 天前
我们有个产品从 7 升到 8 内存泄漏严重.…
我们研究了俩月 无果 ,最后在 azure 上把内存拉高了……
ZZ74
68 天前
没对比,没法看。盲猜问题出在 Core.Models.Order 涉及 UserPricePolicy 逻辑相关。有可能是外包水平的码农写逻辑时无脑查几乎所有数据
ke1e
68 天前
很简单,用 Rust 重写
locksheep
68 天前
贴的 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
68 天前
我看了下原帖
> 查了很多文档 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
68 天前
@ke1e #14 什么语言都避免不了泄露吧。
holinhot
67 天前
@ppxppx PHP 这种可以吧
HaroldFinchNYC
67 天前
@Metatron7 这哥们看着确实不错,有点水平
neilq
67 天前
- 一些配置信息用 redis 做一下缓存,比如 Models.Setting ,Models.WxReplyRule 等,不要每次都从数据库查
- 我怀疑程序大量使用了 static 变量缓存数据,还是某些表的全量数据
- Models.Order 存在 select all 到内存中情况 ,WxReplyRule 疑似也存在这个情况
- 随机数生成算法再优化一下

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

https://www.v2ex.com/t/1076054

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

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

© 2021 V2EX