zoukankan      html  css  js  c++  java
  • How To: Use CLR Profiler

    (翻译)How To: Use CLR Profiler

     

    第一次翻译对我而言比较长的E文,有很多不足之处,请见谅。(个人的习惯GC又做了名词又做了名词)

    原文:http://msdn.microsoft.com/en-us/library/ms979205.aspx

    概况

    CLR Profiler 能让你观察一个进程托管堆和研究(investigate)垃圾回收机制的行为表现。使用该工具中不同的视图,你能获得关于你运用程序的执行,分配和内存消耗的有用信息。

    CLR Profiler 不是一个分析问题的出发点。然而,它帮助你验证和隔离问题代码并追踪内存泄漏。使用CLR Profiler,你能了解代码分配了多少内存,引起了多少垃圾回收和占内存多久。

    注:CLR Profiler 是一个使你的应用的执行比起正常情况下明显(significantly)慢(有的地方是10-100倍)的插入式(intrusive)工具。它的设计目的不是在产品环境下使用的。

    你必须知道的

    CLR Profiler的主要功能是让你明白你的应用在使用托管、GC堆时如何互相协作的(interact with).你能分析一些更为重要的信息:

    *谁分配了一些什么在托管堆

    *哪些对象在托管堆中存活(survive)了下来

    *谁是对象的持有者

    *GC在你的应用程序的生命周期中做了什么

    分析的结构存放在日志文件中。你能通过CLR Profiler中的视图菜单查看这些文件以不同的方式,展现出对应的图表(corresponding graph)。表1列出了最为有用的视图。 

    表1:CLR Profiler视图

    视图

    描述

    Histogram Allocated Types

    给你一个高等级的视图,它指出对象类型(分配的大小)在你的应用程序的生命周期内被分配的情况。这个视图也显示那些被分配在大对象堆(对象超过85KB)中的对象。

    这个视图允许你点击图标的各个部分,为了你能看见哪些方法分配了哪些对象。

    Histogram Relocated Types 

    显示已被GC(重新)分配(位置)的对象,因为他们在一次GC后存活了下来(就是别人还引用他们)

    Objects By Address

    提供一个任意特定时间(at a given time)托管堆情况的图片

    Allocation Graph

    用图表显示调用的堆栈是如何分别的对象。你能使用的视图有:

    *查看方法的分配成本(the cost of each alloction)

    *隔离你不期望的分配

    *找出有可能过度分配的方法

    Assemby,Module,Function,and Class Graph

    有4个非常相仿的视图。他们允许你看哪些方法涉及到了哪些程序集、类、模块、方法

    Heap Graph

    显示托管堆上所有对象,以及他们的关联信息。

    Call Graph

    使你查看哪些方法调用了哪些别的方法和多少频率。

    你能使用这个图表摸索着了解类库的调用成本并判定调用这个方法的需求量和哪些方法被调用。

    Time Line

    显示GC的在你的应用程序中的重新分配情况(就是那些么有被清楚的对象)。使用这个视图去:

    *研究了解GC的行为

    *判定在3代中有多少GC发生(0,1,2代),和发生频率。

    *判定哪些对象在GC后存活,被提升到了下一代。

    你能选择时间点或间隔(intervals),通过右击去显示在这个时间间隙内(interval)谁分配了内存。

    Call Tree View

    提供一个你应用程序执行的视图,它是基于文本按年代分级。使用这个视图可以:

    *查看什么类型被分配及他们的大小

    *查看哪些程序集因方法调用而被被加载

    *分析终结(finalizer)的使用,和他们的执行次数

    *识别(indentify)方法在哪些地方没有使用"close"或"dispose",从而引发瓶颈。

    *分析在你意料之外的分配。

    Profiling Applications
    在这节中,你将创建一个小的C#控制台应用程序例子,并通过使用CLR Profiler了解这个应用程序。

    Creating Sample Applications for Profiling
    "Sample: ProfilerSample1" 
     "Sample: ProfileSample2."代码如下

    ProfilerSample1.cs

    Code

    ProfilerSample2.cs

    Code


    To create sample console applications for profiling

    1.创建一个ProfilerSample文件夹去存放示例的代码。

    2.在ProfilerSample文件夹中,创建2个C#文件,名为ProfilerSample1.cs和ProfileSample2.cs。从“Sample:ProfilerSample1”和“Sample:ProfileSample2”中将代码示例拷贝到文件中。

    3.打开cmd命令窗口,找到ProfilerSample文件夹,并通过下面的命令编译代码。(注意设置环境变量)

    csc /t:exe /out:ProfilerSample1.exe ProfilerSample1.cs
    csc 
    /t:exe /out:ProfilerSample2.exe ProfilerSample2.cs

     

    使用CLR Profiler去分析应用程序
    在这节中,你将分析ProfilerSample1.exe。

    To use CLR Profiler to profile the application

    1.打开CLR Profiler(CLRProfiler.exe).

    2.确保下列选项已经勾选:

    *Profiling active

    *Allocations

    *Calls

    2.点击Start Application。

    3.在打开的窗口中,找到(navigate to)你保存示例代码ProfilerSample文件夹所在位置,并选择profilersample1.exe应用程序。

    4.Interact with the application as needed and then close the application.

    分析ASP.NET 应用程序

    通过下面的步骤去分析asp.net应用程序

    1.启动CLR Profiler。

    2.确保下列选项已经勾选:

    *Profiling active

    *Allocations

    *Calls

    3.在File菜单中点击Profile ASP.NET。

      CLR Profiler 完全关闭互联网信息服务(internet infomation services ,iis),添加那些需要分析的环境变量(environment vaiables),重启iis。CLR Profiler然后提示(prompt)你加载ASP.NET应用程序和等待ASP.NET工作京城启动。

    4.使用MS的IE浏览你所想分析的ASP.NET应用程序。你总能运行你的Web应用程序通过客户端工具,如Microsoft Application Center Test(ACT,http://msdn.microsoft.com/en-us/library/aa287452.aspx.)。

    5.当你已完成应用程序的运行,请点击CLR Profiler窗口中的 Kill ASP.NET。CLR Profiler关闭IIS,移除环境变量,重启IIS。

    注意:有时候工具的当前版本不能对第4步页面的加载做出反映。如果出现这个问题,试着改变ASP.NET进程级别(identity)至System在machine.config中的<ProcessModel>中。你完成分析你的应用程序后,确保你改变的应用程序级别再该回到Machine。

    识别通常的GC问题(issues)

    你能使用CLR Profiler.exe去识别并使与GC有关的问题隔离。

    这些包括以下的内存消耗(consumption)问题:

    *过度(Excessive)分配

    *未知分配

    *内存泄漏(leak)

    他们总包括以下GC问题:

    *过度收集

    *长期存在(Long-lived)的对象

    *执行GC所花的时间百分比

    注意:更多关于使用CLR Profiler解决通常GC问题的详细信息,请看CLRProfiler.doc中的"Common Garbage Collection Problems and How They are Reflected In These Views" ,它在安装CLR Profiler文件夹的位置。

    识别你的应用程序在哪分配了内存

    你想去处理内存消耗问题,那么知道应用程序在哪做了内存分配是非常重要的。

    识别你的应用程序哪分配了内存,有下面几个步骤:

    1.在CLR Profiler中启动示例程序。

    2.分析内存的分配类型。

    3.判定谁分配了内存。

    4.评估(evaluate)你能减少那些分配。 

    第一步:在CLR Profiler中启动示例程序。

    打开CLR Profiler并运行你先前(earlier)所创建的ProfilerSample1.exe应用程序。


    第二步:分析内存的分配类型

    在View菜单上,点击Histogram Allocated Types。CLR Profiler 显示一个类型于图1的窗口。

    图1:

    这个图表显示了在应用程序运行期间已被分配的对象。在这个例子中,大约2GB的对象被分配,几乎都是字符串。原因是当你在示例代码的方法中操作字符串时,.net分配一个新的字符串空间,拷贝老的并相加组成新的存放进去。(这句话的意思就是当你申明string str="";后你执行str+="new";时先前的str=""所在的空间还是在那,str+="new",是一个新的内存空间,它存放的是""+"new"的结果。)

    使用Higtogram Allocated Tyoes视图查看那些大对象(超过85k的)堆分配。你能选择左边特定的柱形条或右边方格,并通过右击他们查看是谁分配了这些内存。显示了一个新的视图,它展现给你一个在你应用程序运行周期内这些对象被谁分配的高级视图。


    第三步
    Determine Who is Allocating the Memory
    在View菜单中,点击Allocation Graph。你也可以通过点击如图1所示的那个视图中的某一个柱形条,右击show who allocated。点击这个菜单项显示关于所选分配的特定详细内容,而不是所有分配。(这句话说的应该是图2视图中的一个个小项)CLR Profiler 显示的图标如图2所示。

     视图2:

    在这个例子中,你能看见几乎所有的(nearly all of)内存从string.Concat方法处所分配的情况。

    Allocation Graph视图能使你:

    *看见每个方法的内存分配成本。

    *分析那些出乎你意料的分配。

    *比较做了相同工作的不同方法。

    第四步Evaluate What You Can Do to Reduce the Allocations
    现在你知道你的应用程序在哪分配了内存,评估你能否减少(reduce)这些内存的消耗(consumption)。在这个例子中,一个选择(option)是使用StringBuilder而不是使用string的拼接(concatenation)。

    分析你的应用程序的(内存)分配情况

    你的应用程序的(内存)分配情况告诉你,对象分配在什么位置,对象的生命周期,GC的行为。轻而易举(walk through)的得知,应用程序持有的对象(和内存)是否比起通常情况下更长。再来看看ProfilerSample2.exe示例。

    分析你的应用程序分配情况,通过以下步骤:

    1.在CLR Profiler中运行示例程序。

    2.识别长期存在的对象。Identify long-lived objects.

    3.分析GC在你的应用程序中的行为。

    4.评估是否可以减少对象的生命周期和如何减少。

    第一步Run CLR Profiler on the Sample Application
    启动CLR Profiler和运行ProfilerSample2.exe程序。

    第二步Identify Long-Lived Objects
    示例代码分配了100000个SolidBrush对象和一些string,导致总的分配约9MB。这个分配绝大多数是SolidBrush对象。通过选择Histogram Resallocated Types 视图,你能看见大约4MB内存因SolidBrush对象被再分配(reallocate).这个信息指出(indicate),SolidBrush对象在GC后未被清楚,并被提升到了更好的(GC)代。

    判定什么类型的对象被提升和这些对象共计使用了多少内存,可以点击View菜单的Objects by Address。如图3所示:

    图3:

    注意1,2代几乎由SolidBrush对象组成。

    第三步Analyze GC Behavior over the Lifetime of Your Application

    点击VIew菜单上的Time Line产看更多详细信息。设置纵坐标(Vertical Scales)为5,横坐标(Horizontal Scales)为1,当滑轮向右移动,你应该看见一个类似图4的窗口。

    图4:

    在图中,你能看见一个“双锯齿”的样式。GC0代去掉(get rid of)的字符串,但保留(retain)brushes(换句话说,brushes在收集中存活了下来)。不久,GC1代清楚了brushes。

    双锯齿样式指示GC0代未能回收(reclaim)所有的内存,对象被更高的代所收集。

    在这点上,你能看见那些在GC中存活下来的对象,并且你需要研究他们。首先一种肯能研究领域是SolidBrush终结(finalizer).

    在工具的主菜单上,单击Call Tree 打开一个调用的树。查看finalizers列的调用情况,通过查找线程表直到找到finalizer线程。(我的CallTree窗口是自己通过鼠标拉大的,不看是很小的个窗口)

    这个树显示NATIVE FUNCTION(UNKNOW ARGUMENTS)已触发了总共1000234次调用。

    因为对象么有被清楚直到finalizer线程启动,对象无法作为一个被提升的结果收集。图5显示的就是一个类似树图的窗口。

    图5:

    第四步Evaluate Whether and How to Reduce Object Lifetimes
    一旦你知道了那些对象是长期存在的,看看你是否能减少他们的生命周期。在这个例子中,你简单的去确保SolidBrush被立刻Dispose在他们不再(on longer)需要的时候,通过把它包含在using 块中。

    附加的一些资源:

    关于使用CLR Profiler解决通常有关CG问题的详细信息,请看"Common Garbage Collection *Problems and How They are Reflected In These Views," 在CLRProfiler.doc,位于CLRProfiler.exe工具的安装目录中。

    *学习关于托管代码的更重要的性能因素(performance factor),请查看MSDN文章,"Writing High-Performance Managed Applications: A Primer," at http://msdn.microsoft.com/library/en-us/dndotnet/html/highperfmanagedapps.asp.

    *关于GC的工作信息,和如何优化(optimize)GC,请查看MSDN article, "Garbage Collector Basics and Performance Hints," at http://msdn.microsoft.com/library/en-us/dndotnet/html/dotnetgcbasics.asp.

    *关于CLR Profiler执行2个不同方法去解决同一个问题的比较和对照信息,请查看MSDN TV片段,"Profiling Managed Code with the CLR Profiler," at http://msdn.microsoft.com/msdntv/episode.aspx?xml=episodes/en/20030729CLRGN/manifest.xml.

     
     
     
    标签: 翻译测试

    使用CLR Profiler分析.NET程序内存不断上升的图文教程

    我们知道.NET是带有垃圾回收机制的,出现出现了.NET应用程序内存不断飙升的情况一般是由某些数据长期存活在内存中又不能被当成垃圾数据回收的原因造成的。

    后来就在各搜索引擎上进行了各种搜索,有说使用windebug分析dump,但需要大量时间琢磨,有人说是不是硬件问题,还有人说中毒了,最后找到了一款微软推出的CLRProfiler工具,貌似很强大,遂MSDN了一把,MSDN是这样说的:

    Who allocates what on the managed heap.
    Which objects survive on the managed heap.
    Who is holding on to objects.
    What the garbage collector does over the lifetime of your application.

    CLR Profiler 是用来观察托管堆内存分配和研究垃圾回收行为的一种工具。使用该工具中不同的视图,你能获得关于你运用程序的执行、内存的分配和消耗等有用信息。

    得到这些信息以后就决定使用一下,让服务端运行了一会儿,停止以后得到分析结果,最终在Allocation Graph视图下了解到原来是下载文件DownloadFile方法下的byte[]数组引起的,短短不到一分钟的时间竟然占用了两百多兆的内存,好了,这下可找到“原凶”了,有得折腾了

    方案1.把要下载的数据一并加载到内存,用户在下载的时候通过position来获取byte[]不新建直接返回,是能解决问题,但这就大大降低了服务端的可用性啊,只能当做小文件服务端,太不合理。

    方案2.由于下载文件的时候返回的是一个可序列化的类,所以想是不是这里出现了问题,可以直接返回byte[],以最基本的数据头->数据长度->数据->数据尾来实现,但这样一来要改的东西太多了,服务端客户端,协议重构,眼看着就要落幕的项目却要重头再来心有不甘那,再加上还有一堆任务在后面赶着,这不是坑自己吗,也放弃了。

    然后又回到各种网络资料搜索上,经过一番查找后了解到,byte[]最终也是会被回收的,只要是托管的数据都是能被回收的,只是周期可能会长一些,最后又回到了Remoting本身上,抱着试一试的心态把WellKnowObjectMode由SingleTon改为了SingleCall,跑了一晚上最后稳定在了200M上下,总算松了口气。

    使用SingleTon本来是想节省内存消耗的,可没想到得不偿失如此的大费周折,遂总结出SingleTon并不适合并发量大的服务端程序,SingleTon是单线程模式,在调用每个方法的时候都会被加锁,猜测造成数据一直不能被释放的原因是由这些锁造成的,由于连接的数量太多导致连接一直处于排队状态,造成了后面连接的客户端响应过慢,连接超时,在这里也给大家一个教训还是用SingleCall实在。

    上面说了这么多只是跟大家分享一下解决问题的经验,还有叙述了一下问题的所在,如果各位有不同的见解请一定要指出来,毕竟.NET内存分配、垃圾回收本就比较复杂。

    然事与愿违却柳暗花明
    这篇文章的重点是讲如何使用CLRProfiler来查找.NET程序的内存分配情况的,下面就开始吧。

    下载CLR Profiler
    http://search.microsoft.com/en-us/DownloadResults.aspx?q=clr%20profiler
    可根据自己.NET的版本下载相应的CLRProfiler,下面以.NET4.0版本为例。
    CLRProfiler可以分析应用程序,服务和ASP.NET编写的程序,以下以应用程序为例为大家演示如何简单使用CLRProfiler。

    下面是一个拆箱装箱的例子CLRProfilerTestDemo,通过这个例子来观察进程托管堆的分配和研究垃圾回收机制的行为表现,代码如下:

    using System;
    using System.Collections.Generic;
    
    namespace CLRProfilerTestDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 100 * 1000; i++)
                {
                    Boxing box = new Boxing();
                }
    
                Environment.Exit(Environment.ExitCode);
            }
        }
    
        class Boxing
        {
            private List<object> box = new List<object>();
            private List<int> unbox = new List<int>();
    
            public Boxing()
            {
                for (int i = 0; i < 1000; i++)
                {
                    box.Add(i);
                    unbox.Add((int)box[i]);
                }
            }
        }
    }

    运行CLRProfiler,选中Allocation和Calls选项如下图:

    编译程序,点击Start Application选择CLRProfilerTestDemo.exe,将会运行此程序,运行一段时间后,点击Kill Application,CLRProfiler将会显示分析结果。

    打开Allocated bytes直方图界面,如下图,在右侧的分配类型区可以找到可疑的类Boxing

    下面是Allocation Graph内存分配视图,在这个视图当中我们可以看出堆栈是如何分别对象的。

    通过CLRProfiler工具进行这几步简单的操作即可找出造成应用程序内存飙升的源头,并想办法修复,很简单吧,如果感兴趣的朋友可以去网上更加详细的了解。

     
  • 相关阅读:
    vueJs+webpack单页面应用--vue-router配置
    webstorm IDE添加Plugins----添加vue插件
    WebStorm 11、PhpStorm 10免费激活(不需要注册码)
    webpack react基础配置二 热加载
    webpack react基础配置一
    移动端页面去掉click点击 背景色变化
    css美化checkbox radio样式
    ie11媒体查询以及其他hack
    angularJS ng-grid 配置
    网络7. TCP/IP网络之网络接口层
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3555060.html
Copyright © 2011-2022 走看看