文档章节

【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题

o
 osc_pn11u1x9
发布于 2018/08/06 10:50
字数 1504
阅读 18
收藏 0

精选30+云产品,助力企业轻松上云!>>>

前言

一般来说.NET程序员是不用担心内存分配释放问题的,因为有垃圾收集器(GC)会自动帮你处理。但是GC只能收集那些不再使用的内存(根据对象是否被其它活动的对象所引用)来确定。所以如果代码编写不当的话,仍然会出现内存泄漏的问题,常见的情况有:一个静态变量引用了一个应该被释放的对象,事件注册后不解除注册,非托管资源使用后没有手动释放。不断的内存泄漏终会引起内存不足,挂掉你的程序。

对于这种内存泄漏问题,有很多的分析工具可以使用,常见的有CLRProfiler、ANTS Performance Profiler等。不过从vs2013起,vs自带了一个分析工具-Diagnostic Tool,默认debug时会自动打开,如果没有打开的话就按快捷键Ctrl+Alt+F2。

如下图: 
这里写图片描述

开始使用

这里以静态变量持有应释放的对象为例,简单介绍下使用方法。 
这里有个winform程序,主要功能即使点击按钮后,输出名为“jim”的个人信息:

private void button1_Click(object sender, EventArgs e)
{
     var p = PersonManager.Get("jim"); label1.Text += p.Name + " " + p.Age + "\n"; }
  • 1
  • 2
  • 3
  • 4
  • 5

Person和PersonManager类的信息如下:

namespace MemLeak
{
    public class Person
    {
        public string Name { get; set; } public int Age { get; set; } public byte[] BinaryData { get; set; } } public static class PersonManager { static List<Person> people = new List<Person>(); public static List<Person> People { get { return people; } } public static Person Get(string name) { //正常逻辑 //var per = People.FirstOrDefault(o => o.Name == name); //if(per==null) //{ // per = new Person(); // per.Age = 23; // per.Name = name; // per.BinaryData = File.ReadAllBytes(@"D:\2.zip");//一个38MB的文件 // people.Add(per); //} //return per; //错误逻辑 Person p = new Person(); p.Age = 23; p.Name = name; p.BinaryData = File.ReadAllBytes(@"D:\2.zip");//一个38MB的文件 people.Add(p); return p; } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

1. 捕获内存快照

程序运行起来后,从下图可以看到内存占用大约在18M左右,此时点击“截取快照”新建一个快照: 
这里写图片描述

然后click按钮5次,然后再点击 截图快照 ,如下: 
这里写图片描述 
从曲线图中可以明显看到内存从18M逐步增长到227M。第二次快照与第一次相比对象增加了19个,堆上的内存使用增加了191M左右。 
这里写图片描述 
点击图中的(+19)字样,可以进入到快照详细对比界面。

2. 详细对比

这里写图片描述
如图所示,我们先来看下选中的那一行是什么意思: 
这里写图片描述
可以看到MemLeak.Person这个对象的计数差异为+5,计数是5。表示这两次快照之间这个Person对象从0个变成了5个增加了5个。大小差异是增加了195601040个字节,这几个从字面意思看都很好理解。唯一有点难度的可能是非独占大小(字节),一眼看不出来是干什么的。但是我们注意到了List<MemLeak.Person>对象的大小是68字节而非独占大小却是195601108字节。 
非独占大小的统计方式如下: 
这里写图片描述

其中最下层的stringbyte[],由于没有子节点了,所以它们的非独占大小就是它们本身的大小。Address的非独占大小=自己本身的大小+String的非独占大小(50字节)+Byte[]的非独占大小(100字节)=200字节。Customer的非独占大小=自己本身(100字节)+String的非独占大小(100字节)+Address的非独占大小(200字节)=400字节。 
所以这也就解释了List<MemLeak.Person>,自身大小仅是68字节,但是由于它是一个List内部包含了5个Person对象,所以它的非独占大小就是5个Person对象大小的和。

3. 哪里产生了泄漏?

这里我先将过滤器里“仅我的代码”和“折叠小型对象类型”前面的勾去掉,便于分析。 
这里写图片描述 
因为我们值需要看当前程序集(MemLeak)的内存信息,所以在搜索类型名的框里直接输入我们程序集的名称,将其他一些没用的过滤掉。 
这里写图片描述
是不是清爽了很多! 
分析内存当然要拿占用内存增多最大的对象开刀,点击MemLeak.Person,在下面的“根的路径”视图中可以看到增加的5个Person对象是在一个Person[]数组中。 
这里写图片描述
但是我们好像并没有声明过这样的数组,所以继续展开: 
这里写图片描述 
原来是在一个List里面,而且这个List还是静态的。这时候就要想到内存泄漏的原因,可能就是代码哪里的静态变量持续占有应该释放的对象了。然后更改为正确代码就OK了。

4. 查看对象中哪种数据类型占用内存较多?

切换到的引用选项卡(“引用的类型”)。 
这里写图片描述
可以看到本例中PersonByte[]类型的占用内存较多,所以我们就可以重点排查Person中哪里用到了Byte[]类型,进而去优化。

当初取消勾选的那两个选项是什么?

第一个是“仅我的代码”: 
勾上之后,会过滤掉那些.Net Runtime产生的一些对象和一些很常见的系统认为与你的程序无关的一些对象。

第二个是:“折叠小的对象类型”: 
勾上后,会过隐藏掉那些非独占大小小于托管堆总大小0.5%的对象。将这些小对象的非独占大小合并的父节点中。如下: 
这里写图片描述

这两个选项默认都勾上即可。

其它

对于生产环境中的软件,分析内存时可以多次抓取dump文件,用vs打开后分析比对。 
这里写图片描述 
不过只有vs的企业版才有这个功能。


参考

Memory Usage Tool while debugging in Visual Studio 2015

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题

原文:【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题 一般来说.NET程序员是不用担心内存分配释放问题的,因为有垃圾收集器(GC)会自动帮你处理。但是GC只能收集那些...

osc_kc130nmf
2018/05/26
2
0
盘点灵活实用的SQL Server第三方工具

  【IT168 资讯】监控并优化SQL Server性能,以及识别和解决SQL Server数据库中的性能瓶颈,这些对于数据库管理员(DBA),开发人员和应用程序支持团队来说都是一项艰巨的任务。影响SQL Ser...

TechTarget中国
2014/08/05
0
0
AIX:诊断程序

一、诊断技巧 诊断前,应清楚以下几点 1.错误日志分析(Error log analysis,ELA)是诊断工作的主要部分 2.独立诊断(Stand-alone diagnostics)不执行错误日志分析,除了在引导独立诊断模式...

抖嘛看猩猩
2017/04/14
0
0
AIX:诊断程序

一、诊断技巧 诊断前,应清楚以下几点 1.错误日志分析(Error log analysis,ELA)是诊断工作的主要部分 2.独立诊断(Stand-alone diagnostics)不执行错误日志分析,除了在引导独立诊断模式...

抖嘛看猩猩
2017/04/14
0
0
运用DebugDiag诊断ASP.Net异常

Debug Diagnostic Tool (DebugDiag)是用来帮助诊断IIS/COM+等应用假死、性能差、内存泄露及碎片和崩溃等问题的工具。 本文介绍如何运用DebugDiag诊断特定的ASP.Net异常: 1. 按照操作系统的类...

寻那一片风
2015/03/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 那么长的绳子,你这是放风筝呢

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @ 巴拉迪维:黑豹乐队的单曲《无地自容》 耳畔突然响起旋律,是那首老歌。中国摇滚有了《一无所有》不再一无所有;中国摇滚有了《无地自容》不...

小小编辑
41分钟前
31
1
《吐血整理》-顶级程序员书单集

你知道的越多,你不知道的越多 给岁月以文明,而不是给文明以岁月 前言 王潇:格局决定了一个人的梦想,梦想反过来决定行为。 那格局是什么呢? 格局是你能够看见的深度、广度和密度。 王潇认...

敖丙
2019/12/11
8
0
我可以在Android版式中加下划线吗? - Can I underline text in an Android layout?

问题: 如何在Android布局xml文件中定义带下划线的文本? 解决方案: 参考一: https://stackoom.com/question/A31z/我可以在Android版式中加下划线吗 参考二: https://oldbug.net/q/A31z/...

法国红酒甜
44分钟前
18
0
干掉ELK | 使用Prometheus+Grafana搭建监控平台

什么是Prometheus? Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus使用Go语言开发,是Google BorgMon监控系统的开源版本。 Prometheus的特点 · 多维度...

木九天
今天
34
0
拉勾网拉你上勾

预览 需求简介 拉勾网是一个互联网行业的一个招聘网站,上面有许多职位,于是乎,小编想提取指定职位的基本信息(职位名,薪水,工作经验,工作地点,教育背景),然后插入 MongoDB 数据库,...

木下瞳
2019/04/17
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部