记一次 .NET某培训学校系统 内存碎片化分析

这篇具有很好参考价值的文章主要介绍了记一次 .NET某培训学校系统 内存碎片化分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一:背景

1. 讲故事

前些天有位朋友微信上找到我,说他们学校的Web系统内存一直下不去,让我看下到底是怎么回事,老规矩让朋友生成一个dump文件丢给我,看一下便知。

二:WinDbg 分析

1. 托管还是非托管

要想看托管还是非托管,可以用 !address -summary 观察下内存段。


0:000> !address -summary

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    384     7dbe`3d662000 ( 125.743 TB)           98.24%
<unknown>                              9653      241`9e9fd000 (   2.256 TB)  99.98%    1.76%
Stack                                   153        0`125d0000 ( 293.812 MB)   0.01%    0.00%
Image                                  1912        0`0b0f2000 ( 176.945 MB)   0.01%    0.00%
Heap                                    110        0`0669a000 ( 102.602 MB)   0.00%    0.00%
Other                                    12        0`001ce000 (   1.805 MB)   0.00%    0.00%
TEB                                      51        0`00066000 ( 408.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                384     7dbe`3d662000 ( 125.743 TB)           98.24%
MEM_RESERVE                            2794      23f`666dd000 (   2.248 TB)  99.59%    1.76%
MEM_COMMIT                             9098        2`5c2b1000 (   9.440 GB)   0.41%    0.01%

从卦中信息的 MEM_COMMITHeap 来看,应该就是托管内存的问题了。

2. 托管堆排查

要查看托管堆,可以用 !eeheap -gc 观察下。


0:000> !eeheap -gc

========================================
Number of GC Heaps: 8
----------------------------------------
Heap 0 (00000273748727a0)
Small object heap
         segment            begin        allocated        committed allocated size       committed size      
generation 0:
    02b388ff24f0     027615400020     0276157f76f8     027615800000 0x3f76d8 (4159192)   0x400000 (4194304)  
...
generation 1:
    02b388ff5e00     02762a000020     02762a01e460     02762a0b0000 0x1e440 (123968)     0xb0000 (720896)    
generation 2:
    02b388f81840     027385000020     0273853a2b20     027385400000 0x3a2b00 (3812096)   0x400000 (4194304)  
    02b388f818f0     027385400020     0273857ee220     027385800000 0x3ee200 (4121088)   0x400000 (4194304)  
    02b388f81e70     027387400020     0273877914e8     0273877b2000 0x3914c8 (3740872)   0x3b2000 (3874816)  
    02b388f823f0     027389400020     0273897bf580     0273897df000 0x3bf560 (3929440)   0x3df000 (4059136)  
    02b388f82600     02738a000020     02738a3644e0     02738a368000 0x3644c0 (3556544)   0x368000 (3571712)  
    ...
    02b388f85fc0     02739f000020     02739f253e10     02739f257000 0x253df0 (2440688)   0x257000 (2453504)  
    02b388f861d0     02739fc00020     02739fffc9f0     02739ffff000 0x3fc9d0 (4180432)   0x3ff000 (4190208)  
    02b388f86490     0273a0c00020     0273a0f829c0     0273a0fbd000 0x3829a0 (3680672)   0x3bd000 (3919872)  
    02b388f87040     0273a5000020     0273a5332f78     0273a5337000 0x332f58 (3354456)   0x337000 (3371008)  
    02b388f875c0     0273a7000020     0273a72e4710     0273a7305000 0x2e46f0 (3032816)   0x305000 (3166208) 
    ...
Large object heap
         segment            begin        allocated        committed allocated size       committed size      
    02b388f84f40     027399000020     02739908f520     027399090000 0x8f500 (587008)     0x90000 (589824)    
Pinned object heap
         segment            begin        allocated        committed allocated size       committed size      
    02b388f812c0     027383000020     02738300b080     027383011000 0xb060 (45152)       0x11000 (69632)     
------------------------------
GC Allocated Heap Size:    Size: 0x2212923b0 (9146278832) bytes.
GC Committed Heap Size:    Size: 0x23b676000 (9586565120) bytes.

从卦中看当前的托管内存是 9.5G,通过观察内存都是被 Gen2 给吃掉了,那 Gen2 上都是什么对象呢?我们用 !dumheap -stat 观察下。


0:000> !dumpheap -stat
Statistics:
          MT     Count     TotalSize Class Name
...
7ff954ecd918    91,030     9,467,120 System.Reflection.RuntimeMethodInfo
7ff95701c8f0   572,034    18,305,088 System.Globalization.DateTimeFormatInfo+TokenHashValue
7ff954c9fd00 1,010,024    62,198,216 System.String
7ff95502fc10    62,645   173,045,678 System.Byte[]
0273747f9610    28,313 8,761,969,520 Free
Total 3,305,047 objects, 9,143,856,580 bytes

不看卦不知道,一看吓一跳,9G的内存,Free 就吃掉了 8.7G,看样子又是经典的 内存碎片化 了,赶紧到 Gen2 上去看一看狼狈现场。


0:000> !dumpheap 02739fc00020 02739fffc9f0
         Address               MT           Size
    02739fc00020     0273747f9610        717,136 Free
    02739fcaf170     7ff95502fc10          8,216 
    02739fcb1188     7ff955478798             64 
    02739fcb11c8     0273747f9610        607,864 Free
    02739fd45840     7ff95502fc10          8,216 
    02739fd47858     7ff955478798             64 
    02739fd47898     0273747f9610      2,205,336 Free
    02739ff61f30     7ff95502fc10          8,216 
    02739ff63f48     7ff955478798             64 
    02739ff63f88     0273747f9610         99,736 Free
    02739ff7c520     7ff95502fc10          8,216 
    02739ff7e538     7ff955478798             64 
    02739ff7e578     0273747f9610         76,504 Free
    02739ff91050     7ff95502fc10          8,216 
    02739ff93068     7ff955478798             64 
    02739ff930a8     0273747f9610        355,728 Free
    02739ffe9e38     7ff95502fc10          8,216 
    02739ffebe50     7ff955478798             64 
    02739ffebe90     0273747f9610         60,168 Free
    02739fffa998     7ff95502fc10          8,216 
    02739fffc9b0     7ff955478798             64 

Statistics:
          MT Count TotalSize Class Name
7ff955478798     7       448 System.IO.FileSystemWatcher+AsyncReadState
7ff95502fc10     7    57,512 System.Byte[]
0273747f9610     7 4,122,472 Free
Total 21 objects, 4,180,432 bytes
...

卦中信息是明显的 内存碎片化 现象,可以看到每一个 Free 后面都跟着一个 8216,那这玩意是干嘛的,为什么它不会 GC 回收呢?

3. 碎片化排查

要想找到不会回收的原因,我们用 !gcroot 看一下。


0:000> !gcroot 02739fffa998
Caching GC roots, this may take a while.
Subsequent runs of this command will be faster.

HandleTable:
    0000027374723fc0 (async pinned handle)
          -> 02739dc758c8     System.Threading.OverlappedData 
          -> 02739fffa998     System.Byte[] 

从卦中可以看到它是被 System.Threading.OverlappedData 持有,熟悉异步编程的朋友应该都知道IO完成端口,C# 中的 OverlappedData 还会绑定 handlebyte[]IOThread 等信息,我们挖一下其中的 _userState


0:000> !do 02739dc758c8
Name:        System.Threading.OverlappedData
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ff95502bce0  4000b00        8  System.IAsyncResult  0 instance 0000000000000000 _asyncResult
00007ff954af93b0  4000b01       10        System.Object  0 instance 000002739dc75910 _callback
00007ff95547f208  4000b02       18 ...eading.Overlapped  0 instance 000002739dc75880 _overlapped
00007ff954af93b0  4000b03       20        System.Object  0 instance 000002739fffa998 _userObject
00007ff954c9ac30  4000b04       28                  PTR  0 instance 000002b41023f130 _pNativeOverlapped
00007ff954c99250  4000b05       30        System.IntPtr  1 instance 0000000000000000 _eventHandle
00007ff954c1e8c0  4000b06       38         System.Int32  1 instance                0 _offsetLow
00007ff954c1e8c0  4000b07       3c         System.Int32  1 instance                0 _offsetHigh

0:000> !do 000002739dc75880
Name:        System.Threading.ThreadPoolBoundHandleOverlapped
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ff95547f558  4000b08        8 ...ng.OverlappedData  0 instance 000002739dc758c8 _overlappedData
00007ff955478d48  4000d2f       10 ...ompletionCallback  0 instance 00000273869e27a8 _userCallback
00007ff954af93b0  4000d30       18        System.Object  0 instance 000002739fffc9b0 _userState
00007ff9554791a8  4000d31       20 ...locatedOverlapped  0 instance 000002739dc75860 _preAllocated
00007ff954c9ac30  4000d32       30                  PTR  0 instance 000002b41023f130 _nativeOverlapped
00007ff955479790  4000d33       28 ...adPoolBoundHandle  0 instance 0000000000000000 _boundHandle
00007ff954c1b3c0  4000d34       38       System.Boolean  1 instance                0 _completed
00007ff955478d48  4000d2e      930 ...ompletionCallback  0   static 00000273869e2898 s_completionCallback

0:000> !do 000002739fffc9b0 
Name:        System.IO.FileSystemWatcher+AsyncReadState
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ff954c1e8c0  400002b       30         System.Int32  1 instance                1 <Session>k__BackingField
00007ff95502fc10  400002c        8        System.Byte[]  0 instance 000002739fffa998 <Buffer>k__BackingField
00007ff955026688  400002d       10 ...es.SafeFileHandle  0 instance 000002739dc757d8 <DirectoryHandle>k__BackingField
00007ff955479790  400002e       18 ...adPoolBoundHandle  0 instance 000002739dc75828 <ThreadPoolBinding>k__BackingField
00007ff9554791a8  400002f       20 ...locatedOverlapped  0 instance 000002739dc75860 <PreAllocatedOverlapped>k__BackingField
00007ff955479248  4000030       28 ...eSystem.Watcher]]  0 instance 000002739dc75848 <WeakWatcher>k__BackingField

从卦中可以看到原来是 FileSystemWatcher 在作祟,说实话看到这个东西我马上就有条件反射,肯定又是经典的 ReloadOnChange=true 导致的,果然直觉就是对的,一搜代码果然有,截图如下:

记一次 .NET某培训学校系统 内存碎片化分析

三:总结

说实话 ReloadOnChange=true 真的是万恶之源,据往期分析可列出如下四大罪证:

  • 文件句柄暴涨
  • byte[]导致的内存暴涨
  • pinned 导致的内存碎片化
  • 线程池暴涨 导致的程序无响应

大家使用前需 慎之又慎,三思而后行!!!文章来源地址https://www.toymoban.com/news/detail-622967.html

记一次 .NET某培训学校系统 内存碎片化分析

到了这里,关于记一次 .NET某培训学校系统 内存碎片化分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记一次 .NET某道闸收费系统 内存溢出分析

    前些天有位朋友找到我,说他的程序几天内存就要爆一次,不知道咋回事,找不出原因,让我帮忙看一下,这种问题分析dump是最简单粗暴了,拿到dump后接下来就是一顿分析。 程序既然会爆,可能是虚拟地址受限,也可能是系统内存不足,可以用 !address -summary 观察下。 从卦

    2024年01月18日
    浏览(47)
  • 记一次 .NET某管理局检测系统 内存暴涨分析

    前些天有位朋友微信找到我,说他们的WPF程序有内存泄漏的情况,让我帮忙看下怎么回事?并且dump也抓到了,网上关于程序内存泄漏,内存暴涨的文章不计其数,看样子这个dump不是很好分析,不管怎么说,上 windbg 说话。 在 .NET调试训练营 中我一直强调要相信数据,不要相

    2024年04月08日
    浏览(106)
  • 记一次 .NET 某外贸ERP 内存暴涨分析

    上周有位朋友找到我,说他的 API 被多次调用后出现了内存暴涨,让我帮忙看下是怎么回事?看样子是有些担心,但也不是特别担心,那既然找到我,就给他分析一下吧。 这也是我一直在训练营灌输的理念,一定要知道是哪一边的暴涨,否则很可能就南辕北辙了,使用 !addr

    2023年04月23日
    浏览(66)
  • 记一次 .NET 某餐饮小程序 内存暴涨分析

    前些天有位朋友找到我,说他的程序内存异常高,用 vs诊断工具 加载时间又太久,让我帮忙看一下到底咋回事,截图如下: 确实,如果dump文件超过 10G 之后,市面上那些可视化工具分析起来会让你崩溃的,除了时间久之外这些工具大多也不是用懒加载的方式,比如 dotmemory

    2024年02月08日
    浏览(47)
  • 记一次 .NET 某游戏服务后端 内存暴涨分析

    前几天有位朋友找到我,说他们公司的后端服务内存暴涨,而且CPU的一个核也被打满,让我帮忙看下怎么回事,一般来说内存暴涨的问题都比较好解决,就让朋友抓一个 dump 丢过来,接下来我们用 WinDbg 一探究竟。 拿到 dump 之后,首先要判断是托管还是非托管问题,这决定了

    2024年02月15日
    浏览(51)
  • 【镜像取证篇】仿真碎片-记一次镜像仿真失败的复盘过程

    这个是很久以前的一个镜像实验,当时仿真可以看到Windows的启动界面,但却一直无法正常进入系统,不断的尝试修复,都是显示错误,最后把类型改为IDE后,成功仿真进入系统—【蘇小沐】 1、无法仿真成功 实验环境 Windows建议用专业版,功能全。 系统 Windows10专业版 VMware

    2024年02月03日
    浏览(61)
  • 记一次 .NET某防伪验证系统 崩溃分析

    昨晚给训练营里面的一位朋友分析了一个程序崩溃的故障,因为看小伙子昨天在群里问了一天也没搞定,干脆自己亲自上阵吧,抓取的dump也是我极力推荐的用 procdump 注册 AEDebug 的方式,省去了很多沟通成本。 windbg有一个非常强大的点就是当你双击打开后,会自动帮你切换到

    2024年03月28日
    浏览(63)
  • 记一次 .NET 某企业内部系统 崩溃分析

    前些天有位朋友找到我,说他的程序跑着跑着就崩溃了,让我看下怎么回事,其实没怎么回事,抓它的 crash dump 就好,具体怎么抓也是被问到的一个高频问题,这里再补一下链接: [.NET程序崩溃了怎么抓 Dump ? 我总结了三种方案] https://www.cnblogs.com/huangxincheng/p/14811953.html ,采用

    2024年02月10日
    浏览(53)
  • 记一次 .NET某列控连锁系统 崩溃分析

    过年喝了不少酒,脑子不灵光了,停了将近一个月没写博客,今天就当新年开工写一篇吧。 去年年初有位朋友找到我,说他们的系统会偶发性崩溃,在网上也发了不少帖子求助,没找到自己满意的答案,让我看看有没有什么线索,看样子这是一个牛皮藓的问题,既然对方有了

    2024年02月21日
    浏览(55)
  • 记一次 .NET 某埋线管理系统 崩溃分析

    经常有朋友跟我反馈,说看你的文章就像看天书一样,有没有一些简单入手的dump 让我们先找找感觉,哈哈,今天就给大家带来一篇入门级的案例,这里的入门是从 WinDbg 的角度来阐述的,这个问题如果你通过 记日志,分析代码 的方式,可能真的无法解决,不信的话继续往下

    2024年02月11日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包