V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
drymonfidelia
V2EX  ›  .NET

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

  •  1
     
  •   drymonfidelia · 86 天前 · 3943 次点击
    这是一个创建于 86 天前的主题,其中的信息可能已经有所发展或是发生改变。
    这一年在 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 上的几个方法都无效
    26 条回复    2024-10-31 16:24:32 +08:00
    Metatron7
        1
    Metatron7  
       86 天前   ❤️ 3
    supemaomao
        2
    supemaomao  
       86 天前
    给个建议,不知道适不适合 op ,如果你能在本机调试复现的话,用 JB 的 dotMemory (其它的当然也行) 跑一下,每隔 10 分钟拍一个快照,对比快照能知道是哪里的内存没被释放。如果是在服务器上的话,那我就没试过了。
    Bazingal
        3
    Bazingal  
       86 天前
    大于 0.5MB 的对象加起来才 900M ,总共占用 7G 多,应该是大量小对象占用的
    sss15
        4
    sss15  
       86 天前
    我也想到了这个人,但没想起名字,github 和博客园都私信找他看看吧,他的博文都是处理这种的
    0o0o0o0
        5
    0o0o0o0  
       86 天前
    这个统计总和才 900 多 MB ,得把小于 0.5M 的,也就是所有的对象的统计输出都发出来才行
    luckybricks9711
        6
    luckybricks9711  
       86 天前
    试过 dumpobject 吗,堆上小对象是什么内容?有 full dump 会好查点。
    0o0o0o0
        7
    0o0o0o0  
       86 天前
    最好是可以在本地调试状态复现,使用 vs 的快照分析,可以具体查看对象大小以及依赖关系,可以很快速找到根源
    luckybricks9711
        8
    luckybricks9711  
       86 天前
    查是肯定能查出来的,用 debugdiag 连续抓几个 dump 对着看,才能找出是哪些对象在增加内存,如果还不好定位问题还有 Time Travel Debugging
    sss15
        9
    sss15  
       86 天前   ❤️ 1
    你只给了一个站 10 分钟后抓取的 dump ,Total 12,315,255 objects, 7,342,657,549 bytes
    你是不是等 10 分钟后再抓一个 dump ,看看总量变化是多少,占用内容变化是多少,这个 dump 应该是堆的内容,只能知道内存中的变量有没有变化,空间占了多少。
    你还需要 dump 一个栈的内容,看看当前执行的方法情况,才能定位到具体代码可能在哪里发生泄漏
    hez2010
        10
    hez2010  
       86 天前
    如果可以的话建议把 dotnet-dump collect 生成的 dump 文件发给会分析的人去看(里面可能包含你们业务的数据因此要谨慎)。
    shapper
        11
    shapper  
       86 天前
    奔溃日记和调用栈信息都没有,错误描述都没有,也没有帮你猜错误吧。。。。
    FFFFourwood
        12
    FFFFourwood  
       86 天前 via iPhone
    我们有个产品从 7 升到 8 内存泄漏严重.…
    我们研究了俩月 无果 ,最后在 azure 上把内存拉高了……
    ZZ74
        13
    ZZ74  
       86 天前
    没对比,没法看。盲猜问题出在 Core.Models.Order 涉及 UserPricePolicy 逻辑相关。有可能是外包水平的码农写逻辑时无脑查几乎所有数据
    ke1e
        14
    ke1e  
       86 天前 via Android
    很简单,用 Rust 重写
    locksheep
        15
    locksheep  
       86 天前
    贴的 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
        16
    csys  
       86 天前
    我看了下原帖
    > 查了很多文档 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
        17
    ppxppx  
       86 天前 via Android
    @ke1e #14 什么语言都避免不了泄露吧。
    holinhot
        18
    holinhot  
       85 天前
    @ppxppx PHP 这种可以吧
    HaroldFinchNYC
        19
    HaroldFinchNYC  
       85 天前
    @Metatron7 这哥们看着确实不错,有点水平
    neilq
        20
    neilq  
       85 天前
    - 一些配置信息用 redis 做一下缓存,比如 Models.Setting ,Models.WxReplyRule 等,不要每次都从数据库查
    - 我怀疑程序大量使用了 static 变量缓存数据,还是某些表的全量数据
    - Models.Order 存在 select all 到内存中情况 ,WxReplyRule 疑似也存在这个情况
    - 随机数生成算法再优化一下
    aw2350
        21
    aw2350  
       85 天前
    建议检查 引用的第三方包;再检查类似 闭包 的方法使用导致 内存逃逸
    Smokovsky
        22
    Smokovsky  
       85 天前
    VS 搞不定就 windbg ,再搞不定就去公众号 @一线码农聊技术,专门搞.net 泄露/异常的,一般最多花个几百就能搞定。
    yazoox
        23
    yazoox  
       85 天前
    follow, take a look. :-)
    ke1e
        24
    ke1e  
       85 天前 via Android
    @ppxppx 你只要不 unsafe ,几乎不会出现泄露
    ppxppx
        25
    ppxppx  
       85 天前 via Android
    @ke1e 我以前用 rust 写过一个转发流量的应用,遇到一个 bug 好像就是 TCP 连接关闭后忘记在 map 释放对象了,导致的结果就是运行一会服务器内存就爆炸了。我觉得这种类型的泄漏没有语言能解决。
    isnullstring
        26
    isnullstring  
       51 天前
    是不是加载太多数据了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1524 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 16:56 · PVG 00:56 · LAX 08:56 · JFK 11:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.