一:背景

去年 GC架构师 Maoni 在 (2021 .NET 开发者大会)

[https://ke.segmentfault.com/course/1650000041122988/section/1500000041123017] 上演示过 PerfView 的 Diff 功能来寻找内存增量,个人感觉这个功能非常不错,简单省事,所以这里就整合到 PerfView 专题中,分享一下给大家。

二:洞察内存增量

1. 什么是内存增量

其实非常好理解,就是当你的程序出现了内存泄漏,你可以在程序内存增长的过程中截取两个 dump 文件,然后通过 PerfView 观察其中的内存增量是什么? 帮助我们快速找出可能被泄漏的对象。

当然你用 WinDBG 的话也是没有问题的,只不过需要用肉眼扫一下而已,接下来举两个例子说明一下。

2. 静态集合的内存泄漏

很多 dump 的内存泄漏,源自于里面的某一个 static 变量无限堆积所致,为了方便说明,先上一段测试代码。


internal class Program
{
static void Main(string[] args)
{
Task.Run(RunTest);
Console.ReadLine();
} public static List<string> my_big_list = new List<string>(); static void RunTest()
{
for (int i = 0; i < 50000; i++)
{
my_big_list.Add(string.Join(",", Enumerable.Range(0, 10000)));
Console.WriteLine(i);
}
}
}

接下来在程序的运行过程中,我们分别截取两个 dump 文件, 点击菜单栏的 Memory -> Take Heap Snapshot 按钮,在 Filter 中搜索需要采集的进程,然后点击 Dump GC Heap 即可,参考如下图:

稍等片刻,你就会看到两个 gcdump 文件,这个和普通的 dump 是不一样的,算是 PerfView 专用的轻量级 dump 文件,截图如下:

接下来点击两个 gcdump 中的 Heap Stacks,对比 inc% 列后发现,内存都被一个叫 my_big_list 变量给吃掉了,前者的count为 10509, 后者是 15172,截图如下:

虽然肉眼可以简单观察,但这里可以使用专业的 Diff 功能,让 PerfView 帮我洞察 栈 的总体增量差异,点击菜单栏中的 Diff -> With Baseline: Heap Stacks [.....] 按钮,即让本 gcdump 和另一个 gcdump 做比较,截图如下:

不过要注意的是,这两个窗口一定要打开,这个是比较坑的,哈哈,接下来就会看到如下图:

从图中可以清晰的看到,这两个 dump 的增量主要来自于 my_big_list 集合,往细处说就是 string 增长了 4663 个。

3. 事件event泄漏

我们再看一个事件泄漏的例子,参考如下代码:


// event 泄漏
class Program
{
static event Action TestEvent; static void Main(string[] args)
{
var memory = new TestAction(); //handle 泄漏
for (int i = 0; i < int.MaxValue; i++)
{
TestEvent += memory.Run; if (i % 500 == 0)
{
Console.WriteLine(i);
}
} Console.ReadLine();
} public static void OnTestEvent()
{
if (TestEvent != null)
{
TestEvent();
}
else
{
Console.WriteLine("Test Event is null");
}
} class TestAction
{
public void Run()
{
Console.WriteLine("TestAction Run.");
}
}
}

将程序运行起来,用 Process Explorer 抓两个 dump 文件下来,然后点击 Memory -> Take Heap Snapshot From Dump 按钮,截图如下:

在弹出的对话框中设置需要提取的 dump 文件,稍等片刻就会生成如下两个 gcdump 文件,截图如下:

接下来将两个 gcdump 都打开,发现内存都被程序中的一个叫 TestEvent 占用了,如下图所示:

接下来就可以使用 Diff 对比功能了,可以观察到,TestEvent 下面的 Action 增量了将近 700w 个,截图如下:

这里稍微说一下,为什么会增量 700w 的 Action,这主要是因为 event 是一个多播委托,内部有一个 Action 集合,也正是这个 Action 集合 在无限膨胀。

PerfView专题 (第十一篇):使用 Diff 功能洞察 C# 内存泄漏增量的更多相关文章

  1. PerfView专题 (第五篇):如何寻找 C# 托管内存泄漏

    一:背景 前几篇我们聊的都是 非托管内存泄漏,这一篇我们再看下如何用 PerfView 来排查 托管内存泄漏 ,其实 托管内存泄漏 比较好排查,尤其是用 WinDbg,毕竟C#是带有丰富的元数据,不像 ...

  2. PerfView专题 (第四篇):如何寻找 C# 中程序集泄漏

    一:背景 前两篇我们都聊到了非托管内存泄漏,一个是 HeapAlloc ,一个是 VirtualAlloc,除了这两种泄漏之外还存在其他渠道的内存泄漏,比如程序集泄漏,这一篇我们就来聊一聊. 二: 程 ...

  3. VC使用CRT调试功能来检测内存泄漏

    信息来源:csdn     C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:“最大的长处也可能成为最大的弱点”,那么 C/C++ 应用程序正好印证了这句话.在 C/C+ ...

  4. PerfView专题 (第三篇):如何寻找 C# 中的 VirtualAlloc 内存泄漏

    一:背景 上一篇我们聊到了如何用 PerfView 去侦察 NTHeap 的内存泄漏,这种内存泄漏往往是用 C 的 malloc 或者 C++ 的 new 分配而不释放所造成的,这一篇我们来聊一下由 ...

  5. PerfView专题 (第八篇):洞察 C# 内存泄漏之寻找静态变量名和GC模式

    一:背景 这篇我们来聊一下 PerfView 在协助 WinDbg 分析 Dump 过程中的两个超实用技巧,可能会帮助我们快速定位最后的问题,主要有如下两块: 洞察内存泄漏中的静态大集合变量名. 验证 ...

  6. PerfView专题 (第十篇):洞察 C# 终结队列引发的内存泄漏

    一:背景 C# 程序内存泄漏的诱发因素有很多,但从顶层原理上来说,就是该销毁的 用户根 对象没有被销毁,从而导致内存中意料之外的对象无限堆积,导致内存暴涨,最终崩溃,这其中的一个用户根就是 终结器队列 ...

  7. PerfView专题 (第七篇):如何洞察触发 GC 的 C# 代码?

    一:背景 上一篇我们聊到了如何用 PerfView 洞察 GC 的变化,但总感觉还缺了点什么? 对,就是要跟踪到底是什么代码触发了 GC,这对我们分析由于 GC 导致的 CPU 爆高有非常大的参考价值 ...

  8. PerfView专题 (第六篇):如何洞察 C# 中 GC 的变化

    一:背景 在洞察 GC 方面,我觉得市面上没有任何一款工具可以和 PerfView 相提并论,这也是为什么我会在 WinDbg 之外还要学习这么一款工具的原因,这篇我们先简单聊聊 PerfView 到 ...

  9. 第四十三篇、利用NSProxy解决NSTimer内存泄漏问题

    问题描述: 用NSTimer来实现每隔一定时间执行制定的任务,例如最常见的广告轮播图.如果我们在 timerWithTimeInterval:1 target:self 中指定target为当前控制器 ...

随机推荐

  1. Linux离线包管理器RPM

    Linux离线包管理器RPM RPM 是RedHat Package Manager(RedHat软件包管理工具). 1.rpm常用参数介绍 查看rpm是否安装 rpm -q rpm包名 [root@ ...

  2. Java开发学习(三)----Bean基础配置及其作用范围

    一.bean基础配置 对于bean的基础配置如下 <bean id="" class=""/> 其中,bean标签的功能.使用方式以及id和clas ...

  3. 运行时应用自我保护(RASP):应用安全的自我修养

    应用程序已经成为网络黑客想要渗透到企业内部的绝佳目标. 因为他们知道如果能发现并利用应用程序的漏洞,他们就有超过三分之一的机会成功入侵. 更重要的是,发现应用程序漏洞的可能性也很大. Contrast ...

  4. vue.js中英文api

    全局配置 Vue.config is an object containing Vue's global configurations. You can modify its properties l ...

  5. Java Web servlet 详解

    执行原理 当服务器接收到客户端浏览器的访问时,会解析请求的URL路径,获取访问的Servlet的资源路径 查找web.xml文件,看是否有对应的<url-pattern>标签体内容 如果有 ...

  6. 深度学习基础-基于Numpy的感知机Perception构建和训练

    1. 感知机模型   感知机Perception是一个线性的分类器,其只适用于线性可分的数据.          f(x) = sign(w.x + b) 其试图在所有线性可分超平面构成的假设空间中找 ...

  7. PTA(BasicLevel)-1013 数素数

    一.问题描述 令 P​i​​ 表示第 i 个素数.现任给两个正整数 M≤N≤10​4​​,请输出 P​M​​ 到 P​N​​ 的所有素数. 输出格式:输入在一行中给出 M 和 N,其间以空格分隔. 输 ...

  8. CSS 盒子模型(一)

    CSS 盒子模型(一) 本人在校学生,主学后端,后来发现前端的基础都忘得差不多了才想着写文章回来复习!欢迎留言交流. 什么是盒子呢? 拿下举例,我们可以把每个红框都比作一个盒子,他们可以是任意的 HT ...

  9. Python 中生成器的原理

    生成器的使用 在 Python 中,如果一个函数定义的内部使用了 yield 关键字,那么在执行函数的时候返回的是一个生成器,而不是常规函数的返回值. 我们先来看一个常规函数的定义,下面的函数 f() ...

  10. Note -「Dsu On Tree」学习笔记

    前置芝士 树连剖分及其思想,以及优化时间复杂度的原理. 讲个笑话这个东西其实和 Dsu(并查集)没什么关系. 算法本身 Dsu On Tree,一下简称 DOT,常用于解决子树间的信息合并问题. 其实 ...