Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Demo on CLR Profiling

0.00/5 (No votes)
3 Nov 2008 1  
Steps in CLR Profiling an ASP.Net application

Overview

CLR Profiler enables you to look at the managed heap of a process and investigate the behavior of the garbage collector. Using the various views in the tool, you can obtain useful information about the execution, allocation, and memory consumption of your application.
Using CLR Profiler, you can identify code that allocates too much memory, causes too many garbage collections, and holds on to memory for too long.

CLR Profiler Views

Histogram Allocated Types, Histogram Relocated Types, Objects By address, Histogram By Age, Allocation Graph, Assembly, Module, Function, and Class Graph, Heap Graph, Call Graph, Time Line, Call Tree View. Here in this article we will deal with Histogram Allocated Types and Histogram by age.

View Description
Histogram Allocated Types Gives you a high-level view of what object types are allocated (by allocation size) during the lifetime of your application. This view also shows those objects that are allocated in the large object heap (objects larger than 85 KB). This view allows you to click parts of the graph so that you can see which methods allocated which objects.
Histogram By Age Allows you to see the lifetime of the objects on the managed heap.
Allocation Graph Graphically displays the call stack for how objects were allocated. You can use this view to:
  • -See the cost of each allocation by method.
  • -Isolate allocations that you were not expecting.
  • -View possible excessive allocations by a method.

Steps involved in profiling ASP.NET application:

  1. Run CLR Profiler.exe
    The following screen appears

    _1_Start_Screen.JPG

    Make sure that the following check boxes are selected:

    • Profiling active
    • Allocations
    • Calls
  2. Go to File Menu. From the options available, select ‘Profile ASP.NET’. This stops IIS Admin Services which stops other dependant services (World Wide Web Publishing Services). Then World Wide Web Publishing Service is restarted. The following screen then appears:

    _2_StartAsp1.JPG

    _3_StartAsp2.JPG

    _4_Second_Screen.JPG

  3. At this point, start the application in the browser (Open a new browser window) Note: Do not refresh an already opened application.
  4. Next, the following screen appears:

    _5_Third_Screen.JPG

    Browse through the pages you want to profile, and then click on “Kill ASP.NET”.

    _6_kill1.JPG

    _7_Kill2.JPG

  5. Finally, the following summary report is generated.
    Various options available can be viewed by clicking on respective Histogram buttons.

    _8_Summary.jpg

Sample Profiling

Baseline profiling for the Sample Application:

Snap shot of the profiling summary

_8_Summary.jpg

Click Histogram associated with “Allocated bytes” Allocated Bytes Histogram Part 1:

_10_AllocatedBytesBaseline1small.JPG

Colors representing different Object types are specified in the right side of the window. When you scroll through the bars, it displays the object type, total memory occupied by that object, total instances created and the average size of an instance.

Allocated Bytes Histogram part 2:

_11_AllocatedBytesBaseline2small.JPG

As we can see here, there are 1,68,037 instances of strings that have been created of size < 64 bytes. One of the main reasons for this would be the fact when we concatenate strings, a new instance of the string is created with the same name, but the old instance is not removed. To improve this situation, we can use string builder objects instead of strings.

To begin with let us modify a small piece of code in one of the user controls (i.e. using sting builder instead of string). The following code snippet depicts the change. One of the properties in the code

/// <summary>
/// Gets the selected text , the items are separated by comma
/// </summary>
public  string SelectedText
{
    get
    {
        string selText = string.Empty;
        foreach (System.Web.UI.WebControls.ListItem li in DDList.Items )
        {
            if (li.Selected )
            { selText += li.Text + ","; }
        }
        if (selText.Length > 0)
        	selText = selText.Length > 0 ? selTExt.Substring(0,selText.Length-1) : selText;
        return selText;
    }
    set
    {	_SelectedText   =  value;
    	DDLabel.Text    =  _SelectedText;
    	DDLabel.ToolTip =  _SelectedText;
    }
}

The same property as above, but with the necessary code modifications.

/// <summary>
/// Gets the selected text , the items are separated by comma
/// </summary>
public  StringBuilder SelectedText
{
    get
    {
        StringBuilder selText = new StringBuilder();
        foreach (System.Web.UI.WebControls.ListItem li in DDList.Items )
        {
            if (li.Selected )
            { selText.Append(li.Text).Append(','); }
        }
        if (selText.Length > 0)
        {
        	String strTemp;
        	strTemp = selText.ToString();
        	if (selText.Length > 0)
        	{
        		selText.Remove(0, selText.Length);
        		selText.Append(strTemp.Substring(0, strTemp.Length - 1));
        	}
        }
        return selText;
    }
    set
    {	_SelectedText   =  value;
    	DDLabel.Text    =  _SelectedText;
    	DDLabel.ToolTip =  _SelectedText;
    }
}

Two properties were changed in the entire coding. After the changes were done, when the profiler was ran. Profiling for the application after the code changes:

Snap shot of the profiling summary:

_14_ProfiledSummary.jpg

There has been a remarkable change in the Allocated bytes section from 172,365,764 to 85,497,789. Similarly, the Relocated bytes have reduced from 32,073,455 to 14,284,343.

Replacing “String” with “String Builder” is one of the ways to improve Memory management. Other techniques could also be used like caching, Pooling, effective Session handling, etc.

Allocated Bytes Histogram part 1:

_15_AllocatedBytesSBBaseline1small.JPG

Allocated Bytes Histogram part 2:

_16_AllocatedBytesSBBaseline2small.JPG

Comparison:

Total Allocated bytes before code changes: 172,365,764
After code changes: 85,497,789
Improvement in %age in Total Allocated Bytes: 50.397

String Instances created of size <64 bytes before code changes: 168,037 (7.1 MB) 44bytes average.
After code changes: 52,898 (2.4 MB) 46bytes average.

Improvement in %age of String instances (of <64 bytes) created: 68.52

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here