Use CLR Profiler
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
1using System;
2public class ProfilerSample1
3{
4 static void Main (string[] args)
5 {
6 int start = Environment.TickCount;
7 for (int i = 0; i < 1000; i++)
8 {
9 string s = "";
10 for (int j = 0; j < 100; j++)
11 {
12 s += "Outer index = ";
13 s += i;
14 s += " Inner index = ";
15 s += j;
16 s += " ";
17 }
18 }
19 Console.WriteLine("Program ran for {0} seconds",
20 0.001*(Environment.TickCount - start));
21 }
22}
23
ProfilerSample2.cs
1using System;
2using System.Drawing;
3
4public class ProfilerSample2
5{
6 static void Main()
7 {
8 int start = Environment.TickCount;
9 for (int i = 0; i < 100*1000; i++)
10 {
11 Brush b = new SolidBrush(Color.Black); // Brush has a finalizer
12 string s = new string(' ', i % 37);
13
14 // Do something with the brush and the string.
15 // For example, draw the string with this brush - omitted
16 }
17 Console.WriteLine("Program ran for {0} seconds",
18 0.001*(Environment.TickCount - start));
19 }
20}
21
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.
Use CLR Profiler的更多相关文章
- CLR Profiler
检查c#代码内存泄露工具-CLR Profiler 大家都知道.net有一套自己的内存(垃圾)回收机制,除非有一些数据(方法)长期占有内存不随着垃圾回收功能而释放内存,这样就造成了我们经常说的内存泄露 ...
- CLR Profiler 性能分析工具 (转)
原文地址:http://www.cnblogs.com/kevinlzf/archive/2010/11/12/1876066.html 下载地址:http://www.microsoft.com/e ...
- CLR Profiler 性能分析工具
CLR Profiler 性能分析工具 CLR Profiler 性能分析工具 CLR Profiler 有两个版本,分别用于CLR1.1 和 CLR2.0,至于CLR4试了一些也可以,但不知道是否完 ...
- How To: Use CLR Profiler
(翻译)How To: Use CLR Profiler 第一次翻译对我而言比较长的E文,有很多不足之处,请见谅.(个人的习惯GC又做了名词又做了名词) 原文:http://msdn.micros ...
- 使用CLR Profiler分析.NET程序
使用CLR Profiler分析.NET程序 就像剥去.NET语法糖衣的工具(Reflector等)很多一样,我们可以用来分析.NET程序性能的工具有很多,如前面一片博文DebugLZQ给大家介绍的v ...
- 转:检查c#代码内存泄露工具-CLR Profiler工具使用
大家都知道.net有一套自己的内存(垃圾)回收机制,除非有一些数据(方法)长期占有内存不随着垃圾回收功能而释放内存,这样就造成了我们经常说的内存泄露.内存持续增长得不到释放等问题导致APS.NET网站 ...
- 使用CLR Profiler查看C#运行程序的内存占用情况
http://blog.csdn.net/wy3552128/article/details/8158938 https://msdn.microsoft.com/en-us/library/ff65 ...
- Visual Studio CLR Profiler
http://blogs.msdn.com/b/dotnet/archive/2013/04/04/net-memory-allocation-profiling-with-visual-studio ...
- CLR via C#学习笔记----知识总概括
第1章 CLR的执行模型 托管模块的各个组成部分:PE32或PE32+头,CLR头,元数据,IL(中间语言)代码. 高级语言通常只公开了CLR的所有功能的一个子集.然而,IL汇编语言允许开发人员访问C ...
随机推荐
- Android-BaseLine基础性开发框架
比较基础性的Android快速开发框架Android-BaseLine,Android-BaseLine实现的功能远远没有其他框架多,一个很好的框架不应该显得太过臃肿,很多功能一般情况下我们可能用不到 ...
- iOS单元测试1
iOS单元测试1 iOS单元测试分为两种类型的测试: 应用测试.应用程序测试可以检查app的代码组件,比如计算机的算术运算的例子.你可以利用应用程序测试来确保你的UI空间控件保持原有位置,并且你的控件 ...
- 【读书笔记】iOS网络-HTTP-请求内容
一,GET方法. 从服务器获取一段内容,用HTTP术语来说就是实体.GET请求通常不包含请求体,不过也是可以包含的.有些网络缓存设施只会缓存GET响应.GET请求通常不会导致服务器端的数据变化. 二, ...
- eclipse智能提示
原文地址:http://www.cnblogs.com/myitm/archive/2010/12/17/1909194.html Windows→Preferences→Java→Editor→Co ...
- Dev Grid拖拽移动行
效果图 源码下载 拖拽时带行截图效果实现代码 /// <summary> /// 拖拽帮助类 /// </summary> public static class DragHe ...
- 使用网站processon在线作图
网站:https://www.processon.com/ 该网站提供多种图形的在线制作,并支持多人协作. 目前提供以下图形的制作: 个人管理界面:
- 传递给后台的Json数据解析
后台代码如下: public void ProcessRequest(HttpContext context) { context.Response.ContentType = "appli ...
- 【CSharp】C#开发ActiveX插件
这几天Web项目中需要用到ActiveX插件(PS:听说这个是好久好久的东西了...),由于项目中需要调用本地资源所以只能研究研究这位老兄了. 先说说自己学习他的经历,开始的时候是用百度引擎检索自己所 ...
- ASP.NET操作Cookie
1.生成Cookie public static void SetDataByCookie(string mainKey, string subKey, string value, string do ...
- SeekableByteChannel 和 FileChannel
Java7中引入了SeekableByteChannel接口,允许我们定位到文件的任意位置进行读写.注意这里的写,不是新增式的插入,而是覆盖,当然在文件末尾的写,是新增. java.nio.chann ...