From: http://www.c-sharpcorner.com/UploadFile/shivprasadk/452069230108152009163244PM/4520692301.aspx?ArticleID=50bdd822-23d0-4baa-ab0a-21314b94d9e5

.net代码性能降低的一个主要原因是内存消耗。很多开发人员在解决性能瓶颈的时候将精力集中在执行时间上,仅仅有执行时间是不能说明性能问题的。这篇文章讲述使用CLR Profiler研究系统的内存分配。

CLR Profiler 从官方下载即可。作者的版本是2.0版本,有点老了。

Features of CLR profiler

CLR Profiler的主要作用有以下两点:

  • 呈现一个.net application分配了多少内存的完整报告。可以看到每种类型分配多少,每个函数分配了多少,每个方法份分配了多少。
  • 提供了方法调用花了多少时间的报告。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

Do not use CLR on production and as a starting tool for performance evalution

CLR 是一个侵入式的工具。当你使用CLR Profiler进行程序性能调优的时候,它注入了每个方法中,以生成HeapData。如下图所示:

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

How  Can  we Run CLR Profiler

下载完毕CLR Profiler后,根据处理器类型选择不同的CLRProfiler.exe.  双击启动:

接下来需要决定Profiler程序的什么内容。CLR可以Profiler如下内容: 内存分配和方法调用的次数,所以可以选择需要Profiler的内容然后点击StratApplication即可。如下图:

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

一旦你的程序执行完毕后,可以看到如下图所示的Profiler概况。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

使用CLR可能遇到的问题

假如你碰到了如下的情况并且CLR没有体制运行,可能是以下两个原因:

  • 你的运行环境是.net20但是你运行的CLR  Profiler的版本是1.1
  • 你没有在GAC中注册ProfilterOBJ.dll

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

将要进行Profiler的应用程序

这个应用程序主要是Profiler  String的+操作和StringBuilder的操作。代码如下所示:

private void UsingSimpleStrings()
{
string strSimpleStrings = "";
for (int i = 0; i < 1000; i++)
    {
        strSimpleStrings = strSimpleStrings + "Test";
    }
}
The function which uses 'StringBuilder' class to do concatenation.
private void UsingStringBuilders()
{
    StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < 1000; i++)
    {
        strBuilder.Append("Test");
    }
}
Both these functions are called through a button click.
private void btnDoProfiling_Click(object sender, EventArgs e)
{
   UsingSimpleStrings();
   UsingStringBuilders();
}

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

Using CLR  Profiler to profilter our sample

运行CLR Profiler, 点击Start application,  运行程序,关闭程序。可以看到一个概览的窗体。

假如点击histogram按钮的话能够看到每种类型分配的内存的历史图。如下图所示:

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

假如你对每个函数分配了多少内存感兴趣,可以点击以下'Allocation Graph'.。这个图呈现了每个函数消耗了多少内存。由于有非常多的函数,这个报告也比较复杂,以至于我们都不能够找到我们的函数 UsingStringBuilders和UsingSimpleStrings。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

可以通过查找函数来简化上图,点击右键选择’Find Routine ‘‘,可以看到有两个函数被调用。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

The search now zooms on the method as shown in the below figure. Now double click on the 'btnDoProfiling_Click' box as highlighted in the below figure.

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

双击后可以看到如下图所示的细节,现在看起来好多了。但是第二个函数去哪里了呢,原来Report是有粒度过滤的。选择Everything就能够看到一切。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

现在可以看到其他的函数了。可以看到’UseSimpleStrings‘和’UseStringBuilders’所占的内存的大小。如下图:

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

That was a tough way an easy way

假如我们有一千个函数的话,是不可能每个调用图都能够看到的想要的函数的,比较好的方式导出细节到一个Excel中,然后再分析。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

Once you click on call tree you will be shown something as shown below. Click on view --> All functions --> you will be shown all functions --> click on file and save it as CSV.

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

Once you have exported the complete data to CSV, you can easily locate your methods and functions and see how much data has been allocated.

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

Simplifying results using Comments

假如你知道要优化哪个方法,你可以在方法调用的时候**优化。也就是说我们可以在应用程序中**CLR Profiler。

为了在代码中使用Profiler, 需要添加引用“CLRProfilerControl.dll”. 这个DLL和Profiler.exe在同一目录下。

然后你可以直接在代码中调用profiler control,如下所示:

private void btnDoProfiling_Click(object sender, EventArgs e)
{
   CLRProfilerControl.LogWriteLine("Entering loop");
   CLRProfilerControl.AllocationLoggingActive = true;
   CLRProfilerControl.CallLoggingActive = true;
   UsingSimpleStrings();
   UsingStringBuilders();
   CLRProfilerControl.AllocationLoggingActive = false;
   CLRProfilerControl.CallLoggingActive = false;
   CLRProfilerControl.LogWriteLine("Exiting loop");
   CLRProfilerControl.DumpHeap();
}

然后运行CLR Profiler,启动我们的应用程序。需要保证没有选择profile active因为我们要在代码中**这些内容。
.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

现在你可以在Histogram中看到有限的数据。只有很少的来自“String.String”和“System.Text.StringBuilder”类型的的内存分配。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

而且内存分配图现在也很整洁了。之前的一团糟的图形已经没有了。注意这里我们仍然需要在Detail中选择”EveryThing“粒度。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

As Said before do not get carried away with execution time

在概览页可以看到Comments按钮。点击它将会看到启动和结束时间。不要忘了在代码中移除这一部分。

.net垃圾回收学习【NET Best Practice No: 1:- Detecting High Memory consuming functions in .NET code】【翻译&&学习】...

Entering loop (1.987 secs)
Exiting loop (2.022 secs)

结论:

  • CLR Profiler可以用来查找函数、类、程序集分配的内存。
  • CLR Profiler不应该用在生产环境中。
  • CLR Profiler不应该作为评估性能的一个起点。我们可以通过运行一个计数器,得到执行时间较长的方法,然后通过CLR来优化。
  • 可以使用Histogram查看内存分配和Call Graph来看方法级别的内存分配。
  • 如果你知道那些代码需要优化,可以在Application中**它。

转载于:https://www.cnblogs.com/sunshinefly128/archive/2011/08/30/2159062.html

相关文章:

  • 2022-01-16
  • 2022-02-18
  • 2022-12-23
  • 2021-10-20
  • 2021-12-31
  • 2021-06-25
  • 2022-03-04
  • 2022-12-23
猜你喜欢
  • 2022-01-02
  • 2021-09-20
  • 2021-09-27
  • 2021-11-14
  • 2021-06-07
  • 2021-08-30
  • 2022-01-15
相关资源
相似解决方案