如何排查 .NET 内存泄漏
内存泄漏通常表示:一个应用程序的某些对象在完成它的的生命周期后,由于它被其他对象意外引用,导致后续gc无法对它进行回收,长此以往就会导致程序性能的下降以及潜在的 OutOfMemoryException
。
这篇我们通过一个内存泄漏工具对 .NET Core 程序进行内存泄漏分析,如果程序是跑在windows上,那直接可以使用 Visual Studio 进行诊断。
检查托管内存使用
在开始分析内存泄漏之前,你一定要有证据证明真的存在内存泄漏,这里可以用 dotnet-counters
来看下应用程序的各个指标来进行验证。
将程序跑起来
dotnet run
找出程序的 pid,
dotnet-counters ps4807 DiagnosticScena /home/user/git/samples/core/diagnostics/DiagnosticScenarios/bin/Debug/netcoreapp3.0/DiagnosticScenarios
使用 monitor 启动监视器,这里的 --refresh-interval 表示刷新间隔
dotnet-counters monitor --refresh-interval 1 -p 4807
Press p to pause, r to resume, q to quit.Status: Running[System.Runtime]# of Assemblies Loaded 118% Time in GC (since last GC) 0Allocation Rate (Bytes / sec) 37,896CPU Usage (%) 0Exceptions / sec 0GC Heap Size (MB) 4Gen 0 GC / sec 0Gen 0 Size (B) 0Gen 1 GC / sec 0Gen 1 Size (B) 0Gen 2 GC / sec 0Gen 2 Size (B) 0LOH Size (B) 0Monitor Lock Contention Count / sec 0Number of Active Timers 1ThreadPool Completed Work Items / sec 10ThreadPool Queue Length 0ThreadPool Threads Count 1Working Set (MB) 83
重点看一下 GC Heap Size (MB)
指标,可以看到程序启动后当前GC堆内存为 4M,打开链接:https://localhost:5001/api/diagscenario/memleak/20000 后再看看GC堆内存,可以看到一下子就到 30M 了,如下所示:
GC Heap Size (MB) 30
通过对比内存的使用,这下子可以拍胸脯的说,确认内存内存泄漏。
生成dump文件
要想分析程序的内存泄漏,首先要有访问GC堆的权限,这样就可以分析heap内存以及对象之间的关系,然后就可以大胆猜想为啥内存没有得到释放?要想生成 .NET Core 程序的dump文件,可以借助 dotnet-dump
工具。
dotnet-dump collect -p 4807
Writing minidump with heap to ./core_20190430_185145
Complete
分析 core dump
接下来可以使用 dotnet-dump analyze
对已生成的dump文件进行分析。
dotnet-dump analyze core_20190430_185145
这里的 core_20190430_185145
就是你想要分析的dump名,值得一提的是:如果你遇到了 libdl.so cannot be found
错误,建议以安装一下 libc6-dev package
包。
首先我们通过 sos 命令查看 托管堆 上的所有对象统计清单。
> dumpheap -statStatistics:MT Count TotalSize Class Name
...
00007f6c1eeefba8 576 59904 System.Reflection.RuntimeMethodInfo
00007f6c1dc021c8 1749 95696 System.SByte[]
00000000008c9db0 3847 116080 Free
00007f6c1e784a18 175 128640 System.Char[]
00007f6c1dbf5510 217 133504 System.Object[]
00007f6c1dc014c0 467 416464 System.Byte[]
00007f6c21625038 6 4063376 testwebapi.Controllers.Customer[]
00007f6c20a67498 200000 4800000 testwebapi.Controllers.Customer
00007f6c1dc00f90 206770 19494060 System.String
Total 428516 objects
从输出看,大头都是些 String
和 Customer
对象,然后可以通过 mt
参数来获取该方法表下所有的实例对象。
> dumpheap -mt 00007faddaa50f90Address MT Size
...
00007f6ad09421f8 00007faddaa50f90 94
...
00007f6ad0965b20 00007f6c1dc00f90 80
00007f6ad0965c10 00007f6c1dc00f90 80
00007f6ad0965d00 00007f6c1dc00f90 80
00007f6ad0965df0 00007f6c1dc00f90 80
00007f6ad0965ee0 00007f6c1dc00f90 80Statistics:MT Count TotalSize Class Name
00007f6c1dc00f90 206770 19494060 System.String
Total 206770 objects
接下来可以用 !gcroot
查看某一个string到底被谁持有着?
> gcroot -all 00007f6ad09421f8Thread 3f68:00007F6795BB58A0 00007F6C1D7D0745 System.Diagnostics.Tracing.CounterGroup.PollForValues() [/_/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs @ 260]rbx: (interior)-> 00007F6BDFFFF038 System.Object[]-> 00007F69D0033570 testwebapi.Controllers.Processor-> 00007F69D0033588 testwebapi.Controllers.CustomerCache-> 00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer, DiagnosticScenarios]]-> 00007F6C000148A0 testwebapi.Controllers.Customer[]-> 00007F6AD0942258 testwebapi.Controllers.Customer-> 00007F6AD09421F8 System.StringHandleTable:00007F6C98BB15F8 (pinned handle)-> 00007F6BDFFFF038 System.Object[]-> 00007F69D0033570 testwebapi.Controllers.Processor-> 00007F69D0033588 testwebapi.Controllers.CustomerCache-> 00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer, DiagnosticScenarios]]-> 00007F6C000148A0 testwebapi.Controllers.Customer[]-> 00007F6AD0942258 testwebapi.Controllers.Customer-> 00007F6AD09421F8 System.StringFound 2 roots.
从string的引用链看,它是被 CustomerCache
所持有,然后就可以到代码中寻找问题啦。
如何排查 .NET 内存泄漏相关推荐
- 排查Javascript内存泄漏
引言 也许你已经知道,Chrome DevTools里的Performance面板和Memory面板可以用来定位内存问题.但当你真正上手使用它们的时候,往往会觉得不知所措 -- 因为里面有着各种各样的 ...
- unity如何检测内存泄漏_如何排查Java内存泄漏?看懂这一篇就够用了
原文:https://www.toptal.com/java/hunting-memory-leaks-in-java 作者:Jose Ferreirade Souza Filho 译者:Emma来源 ...
- 使用gdb分析coredump文件排查流媒体服务srs偶发内存泄漏问题
内存泄漏 正常情况内存消耗比较平稳,但是异常后如下图可以看到内存在几个小时内内存消耗殆尽导致操作系统直接kill掉srs进程 排查难点 内存泄漏是偶发的这是排查的难点,如果是必现可以借助一些成熟的工具 ...
- window 下内存泄漏检测
在window 下开发进行内存泄漏的检测相对比较容易. 这里只是简单的记录一些东西,没有具体的谈论实现. window 下面内存检测主要可以考虑从两个方面入手,这两个方面并不是一个if else 分支 ...
- 利用MAT进行内存泄漏分析
##前言 对于程序员来说码代码容易,保证代码的稳定性很难.有时候写完一个功能可能只需要一天时间,但是这个功能隐藏的bug导致的线上问题排查可能需要一周或者更长时间.因此,拥有良好的代码结构和编码规范是 ...
- 快速定位解决Android内存泄漏
此文章来源于APP架构师这个公众号 今天的主题是Android开发中的内存泄漏,之所以说这个是因为前几天做了项目中的内存泄漏排查与解决,在这里总结一下,被提供一种快速定位解决Android内存泄漏的方 ...
- 内存泄漏排查攻略之:Show me your Memory
以下文章来源方志朋的博客,回复"666"获面试宝典 来源| cnblogs.com/yougewe/p/11334342.html java 语言有个神奇的地方,那就是你时不时会去 ...
- Java 内存泄漏排查,新技能+1
点击关注公众号,Java干货及时送达 来源 | https://zhenbianshu.github.io/ 前些日子小组内安排值班,轮流看顾我们的服务,主要做一些报警邮件处理.Bug 排查.运营 i ...
- 又一次 Java 内存泄漏排查,新技能+1
点击关注公众号,Java干货及时送达 前些日子小组内安排值班,轮流看顾我们的服务,主要做一些报警邮件处理.Bug 排查.运营 issue 处理的事.工作日还好,无论干什么都要上班的,若是轮到周末,那这 ...
最新文章
- Scikit Learn: 在python中机器学习
- mac 10.12显示隐藏文件
- mysql导出数据表 .xls_mysql数据库导出xls-自定义
- 反思拖延症:持续告诉自己立即做立即做;面对困难时要持续坚持;面对困顿时要转变方法
- Proxy error: Could not proxy request /admin/myResources.do from localhost.jd.com:41000 to http://loc
- 小程序onload_微信小程序开发入门之共享账本(十四)
- cmd xcopy 拷贝文件夹_在纯dos下用xcopy命令怎么复制文件夹
- 主机路由在计算机中的应用
- SharePoint 2010: 对于开发人员
- php 生成随机数组,利用php如何获取随机数组列表
- 波束形成MATLAB代码
- C语言实现移位密码算法,仿射密码算法
- Matlab 图例 位置的不同命令
- 排队器拦截_如何绕过浏览器的弹窗拦截机制
- IT领域的罗马帝国——微软公司
- 关于新冠疫情,美国专家们终于认定了这9大事实
- 冯杰的手写艺术签名怎么写好看
- 用友u8文件服务器备份,用友u8 数据备份到云服务器
- SW如何自定义工程图比例?
- 安徽vfp计算机二级知识,安徽省计算机二级VFP考试理论模拟试题2(附答案)