使用PerfView诊断.Net GC的问题

PerfView 概述:数组

PerfView是一个能够帮助你分析CPU和内存问题的工具软件。它很是轻量级也不会入侵诊断的程序,在诊断过程当中对诊断的程序影响甚微。dom

Visual Studio自带的性能分析功能在CPU占用、时间消耗、内存分配等方面的诊断效果还算不错,但PerfView能够提供更加丰富的诊断分析信息。工具

在这篇文章中,我将使用PerfView给你展示以下功能:性能

  • GC回收发生的频率以及回收所消耗的时间;
  • 获取致使Large object分配的缘由;
  • 内存被谁占用了;
  • 对比哪一个托管对象增大的最快。

 

测试程序测试

如今咱们准备一个将会致使内存泄露的程序,用来确保使用PerfView能够达到咱们所指望的效果。它是一个WinForm应用程序,后台代码以下:spa

    public partial class Form1 : Form
    {
        private List<int[]> arrays = new List<int[]>();
        Random random = new Random();

        public Form1()
        {
            InitializeComponent();

            Thread thread = new Thread(Start);
            thread.IsBackground = true;
            thread.Start();
        }

        private void Start(object obj)
        {
            while (true)
            {
                int[] a = new int[random.Next(90000, 100000)];
                arrays.Add(a);
                Thread.Sleep(10);
            }
        }
    }

 

使用PerfView进行跟踪3d

开启PerfView,你将会看到以下窗口:code

PerfView的使用手册被集成在这个程序中,你能够菜单栏来进行访问。orm

而后点击菜单“Collect-->Collect”来进行数据采集,用来分析生成诊断结果:对象

无需修改任何初始化配置,点击“Start Collection”按钮,PerfView将会开始采集全部进程的事件数据。

数十秒以后,你能够点击“Stop Collection”按钮,PerfView将会中止采集并生成诊断文件“PerfViewData.etl.zip”:

 

获取GC Stats

双击“GCStats”报表,将会弹出一个窗口,窗口中显示了每个进程GC信息,找到咱们的测试程序。

关于测试程序咱们将会获得以下汇总信息表:

进一步往下看,还会显示GC触发的缘由:

如上图所示,此次GC的collection的发生是由于large object的分配。

 

获取致使large object分配的缘由

从PerfView的主界面,双击打开“GC Heap Alloc Stacks”窗口,而后双击测试程序的进程,以后弹出的窗口将根据内存分配从大到小的次序显示堆栈信息:

PerfView会将全部的large object分配都归类在LargeObject节点下面,双击该节点能够看到以下信息:

备注:若是你在上图所示的界面中看到“OTHER<<clr?>>”,能够对其鼠标右击,而后点击“Lookup Symbols”,来获取CLR和Windows的功能名称。

上图中主要列的说明以下:

Inc%:表示该对象分配的字节占全部记录分配的百分比;

Inc:该对象分配字节的总数;

Inc Ct:该对象分配的次数。

从上图能够看出,巨多的large object都是来自Start方法的Int32数组,PerView精确地诊断出咱们预期的效果。

 

谁形成了内存泄露

 PerfView能够经过heap dump来查看占用内存的对象的路径。

从主界面点击菜单项“Memory-->Tale Heap Snapshot”,弹出窗口以下图所示:

找到咱们的测试程序并选中,而后点击“Dump GC Heap”按钮,数秒后再点击“CLose”按钮,最后会生成一个“.gcdump”文件。

双击打开“WindowsFormsApplication1.gcdump”窗口,显示以下所示:

PrefView精确地诊断出,是static variables占用了内存。

 

使用两个Heap Dump来查看对象所占内存的变化状况

在应用程序连续运行的状况下,对其进行两次Take Heap Sanpshot,确保两次生成的文件名称不一致。同时打开这两个.gcdump文件的窗口,经过任一一个窗口的diff菜单项功能,都能以另外一个窗口的数据为基准进行对比。