ANTS CLR and Memory Profiler In Depth Review (Part 1 of 2 – CLR Profiler)

One of the things that people might not know about me, is my obsession to make my code as efficient as possible.  Many people might not realize how much of a task or undertaking that this might be, but it is surely a task as monumental as climbing Mount Everest, except this time it is a challenge for the mind…  In trying to make code efficient, there are many different factors that play a part – size of project or solution, tiers, language used, experience and training of the programmer, technologies used, maintainability of the code – the list can go on for quite some time.

I spend quite a bit of time when developing trying to determine what is the best way to implement a feature to accomplish the efficiency that I look to achieve.  One program that I have recently come to learn about – Red Gate ANTS Performance (CLR) and Memory profiler gives me tools to accomplish that job more efficiently as well.  In this review, I am going to cover some of the features of the ANTS profiler set by compiling some hideous example code to test against.

Notice

As a member of the Geeks With Blogs Influencers program, one of the perks is the ability to review products, in exchange for a free license to the program.  I have not let this affect my opinions of the product in any way, and Red Gate nor Geeks With Blogs has tried to influence my opinion regarding this product in any way.

Introduction

The ANTS Profiler pack provided by Red Gate was something that I had not heard of before receiving an email regarding an offer to review it for a license.  Since I look to make my code efficient, it was a no brainer for me to try it out!  One thing that I have to say took me by surprise is that upon downloading the program and installing it you fill out a form for your usual contact information.  Sure enough within 2 hours, I received an email from a sales representative at Red Gate asking if she could help me to achieve the most out of my trial time so it wouldn’t go to waste. 

After replying to her and explaining that I was looking to review its feature set, she put me in contact with someone that setup a demo session to give me a quick rundown of its features via an online meeting.  After having dealt with a massive ordeal with one of my utility companies and their complete lack of customer service, Red Gates friendly and helpful representatives were a breath of fresh air, and something I was thankful for.

ANTS CLR Profiler

The ANTS CLR profiler is the thing I want to focus on the most in this post, so I am going to dive right in now. Install was simple and took no time at all.  It installed both the profiler for the CLR and Memory, but also visual studio extensions to facilitate the usage of the profilers (click any images for full size images):

image

The Visual Studio menu options (under ANTS menu)

image

Starting the CLR Performance Profiler from the start menu yields this window

If you follow the instructions after launching the program from the start menu (Click File > New Profiling Session to start a new project), you are given a dialog with plenty of options for profiling:

image

The New Session dialog.  Lots of options.  One thing I noticed is that the buttons in the lower right were half-covered by the panel of the application.  If I had to guess, I would imagine that this is caused by my DPI settings being set to 125%.  This is a problem I have seen in other applications as well that don’t scale well to different dpi scales.

The profiler options give you the ability to profile:

  • .NET Executable
  • ASP.NET web application (hosted in IIS)
  • ASP.NET web application (hosted in IIS express)
  • ASP.NET web application (hosted in Cassini Web Development Server)
  • SharePoint web application (hosted in IIS)
  • Silverlight 4+ application
  • Windows Service
  • COM+ server
  • XBAP (local XAML browser application)
  • Attach to an already running .NET 4 process

Choosing each option provides a varying set of other variables/options that one can set including options such as application arguments, operating path, record I/O performance performance counters to record (43 counters in all!), etc…  All in all, they give you the ability to profile many different .Net project types, and make it simple to do so.  In most cases of my using this application, I would be using the built in Visual Studio extensions, as they automatically start a new profiling project in ANTS with the options setup, and start your program, however RedGate has made it easy enough to profile outside of Visual Studio as well.

On the flip side of this, as someone who lives most of their work life in Visual Studio, one thing I do wish is that instead of opening an entirely separate application/gui to perform profiling after launching, that instead they would provide a Visual Studio panel with the information, and integrate more of the profiling project information into Visual Studio. 

So, now that we have an idea of what options that the profiler gives us, its time to test its abilities and features.

Horrendous Example Code – Prime Number Generator

One of my interests besides development, is Physics and Math – what I went to college for.  I have especially always been interested in prime numbers, as they are something of a mystery…  So, I decided that I would go ahead and to test the abilities of the profiler, I would write a small program, website, and library to generate prime numbers in the quantity that you ask for.  I am going to start off with some terrible code, and show how I would see the profiler being used as a development tool.

First off, the IPrimes interface (all code is downloadable at the end of the post):

    interface IPrimes
    {
        IEnumerable<int> GetPrimes(int retrieve);
    }

Simple enough, right?  Anything that implements the interface will (hopefully) provide an IEnumerable of int, with the quantity specified in the parameter argument.  Next, I am going to implement this interface in the most basic way:

    public class DumbPrimes : IPrimes
    {
        public IEnumerable<int> GetPrimes(int retrieve)
        {
            //store a list of primes already found
            var _foundPrimes = new List<int>() { 2, 3 };

            //if i ask for 1 or two primes, return what asked for
            if (retrieve <= _foundPrimes.Count())
                return _foundPrimes.Take(retrieve);

            //the next number to look at
            int _analyzing = 4;

            //since I already determined I don't have enough
            //execute at least once, and until quantity is sufficed
            do
            {
                //assume prime until otherwise determined
                bool isPrime = true;
                
                //start dividing at 2
                //divide until number is reached, or determined not prime
                for (int i = 2; i < _analyzing && isPrime; i++)
                {
                    //if (i) goes into _analyzing without a remainder,
                    //_analyzing is NOT prime
                    if (_analyzing % i == 0)
                        isPrime = false;
                }
                
                //if it is prime, add to found list
                if (isPrime)
                    _foundPrimes.Add(_analyzing);
                
                //increment number to analyze next
                _analyzing++;
            } while (_foundPrimes.Count() < retrieve);

            return _foundPrimes;
        }
    }

This is the simplest way to get primes in my opinion.  Checking each number by the straight definition of a prime – is it divisible by anything besides 1 and itself.

I have included this code in a base class library for my solution, as I am going to use it to demonstrate a couple of features of ANTS.  This class library is consumed by a simple non-MVVM WPF application, and a simple MVC4 website.  I will not post the WPF code here inline, as it is simply an ObservableCollection<int>, a label, two textbox’s, and a button.

Starting a new Profiling Session

So, in Visual Studio, I have just completed my first stint developing the GUI and DumbPrimes IPrimes class, so now I want to check my codes efficiency by profiling it.  All I have to do is build the solution (surprised initiating a profiling session doesn’t do this, but I suppose I can understand it), and then click the ANTS menu, followed by Profile Performance.  I am then greeted by the profiler starting up and already monitoring my program live:

image

You are provided with a realtime graph at the top, and a pane at the bottom giving you information on how to proceed.  I am going to start by asking my program to show me the first 15000 primes:

image

After the program finally began responding again (I did all the work on the main UI thread – how bad!), I stopped the profiler, which did kill the process of my program too.  One important thing to note, is that the profiler by default wants to give you a lot of detail about the operation – line hit counts, time per line, percent time per line, etc…  The important thing to remember is that this itself takes a lot of time.  When running my program without the profiler attached, it can generate the 15000 primes in 5.18 seconds, compared to 74.5 seconds – almost a 1500 percent increase.  While this may seem like a lot, remember that there is a trade off.  It may be WAY more inefficient, however, I am able to drill down and make improvements to specific problem areas, and then decrease execution time all around.

Analyzing the Profiling Session

After clicking ‘Stop Profiling’, the process running my application stopped, and the entire execution time was automatically selected by ANTS, and the results shown below:

image

Now there are a number of interesting things going on here, I am going to cover each in a section of its own:

Real Time Performance Counter Bar (top of screen)

At the top of the screen, is the real time performance bar.  As your application is running, this will constantly update with the currently selected performance counters status.  A couple of cool things to note are the fact that you can drag a selection around specific time periods to drill down the detail views in the lower 2 panels to information pertaining to only that period.

After selecting a time period, you can bookmark a section and name it, so that it is easy to find later, or after reloaded at a later time.  You can also zoom in, out, or fit the graph to the space provided – useful for drilling down.

It may be hard to see, but at the top of the processor time graph below the time ticks, but above the red usage graph, there is a green bar. This bar shows at what times a method that is selected in the ‘Call tree’ panel is called. Very cool to be able to click on a method and see at what times it made an impact.

image

As I said before, ANTS provides 43 different performance counters you can hook into.  Click the arrow next to the Performance tab at the top will allow you to change between different counters if you have them selected:

image

Method Call Tree, ADO.Net Database Calls, File IO – Detail Panel

Red Gate really hit the mark here I think. When you select a section of the run with the graph, the call tree populates to fill a hierarchical tree of method calls, with information regarding each of the methods.  

image

By default, methods are hidden where the source is not provided (framework type code), however, Red Gate has integrated Reflector into ANTS, so even if you don’t have source for something, you can select a method and get the source if you want.  Methods are also hidden where the impact is seen as insignificant – methods that are only executed for 1% of the time of the overall calling methods time; in other words, working on making them better is not where your efforts should be focused. – Smart!

Source Panel – Detail Panel

The source panel is where you can see line level information on your code, showing the code for the currently selected method from the Method Call Tree.  If the code is not available, Reflector takes care of it and shows the code anyways!

image

As you can notice, there does seem to be a problem with how ANTS determines what line is the actual line that a call is completed on.  I have suspicions that this may be due to some of the inline code optimizations that the CLR applies upon compilation of the assembly.  In a method with comments, the problem is much more severe:

image

As you can see here, apparently the most offending code in my base library was a comment – *gasp*!  Removing the comments does help quite a bit, however I hope that Red Gate works on their counter algorithm soon to improve the logic on positioning for statistics:

image

I did a small test just to demonstrate the lines are correct without comments.

For me, it isn’t a deal breaker, as I can usually determine the correct placements by looking at the application code in the region and determining what makes sense, but it is something that would probably build up some irritation with time.

Feature – Suggest Method for Optimization

A neat feature to really help those in need of a pointer, is the menu option under tools to automatically suggest methods to optimize/improve:

image

Nice feature – clicking it filters the call tree and stars methods that it thinks are good candidates for optimization.  I do wish that they would have made it more visible for those of use who aren’t great on sight:

image

Process Integration

I do think that this could have a place in my process.  After experimenting with the profiler, I do think it would be a great benefit to do some development, testing, and then after all the bugs are worked out, use the profiler to check on things to make sure nothing seems like it is hogging more than its fair share.  For example, with this program, I would have developed it, ran it, tested it – it works, but slowly.

After looking at the profiler, and seeing the massive amount of time spent in 1 method, I might go ahead and try to re-implement IPrimes (I actually would probably rewrite the offending code, but so that I can distribute both sets of code easily, I’m just going to make another implementation of IPrimes).  Using two pieces of knowledge about prime numbers can make this method MUCH more efficient – prime numbers fall into two buckets 6k+/-1 , and a number is prime if it is not divisible by any other primes before it:

    public class SmartPrimes : IPrimes
    {
        public IEnumerable<int> GetPrimes(int retrieve)
        {
            //store a list of primes already found
            var _foundPrimes = new List<int>() { 2, 3 };

            //if i ask for 1 or two primes, return what asked for
            if (retrieve <= _foundPrimes.Count())
                return _foundPrimes.Take(retrieve);

            //the next number to look at
            int _k = 1;

            //since I already determined I don't have enough
            //execute at least once, and until quantity is sufficed
            do
            {
                //assume prime until otherwise determined
                bool isPrime = true;
                int potentialPrime;
                
                //analyze 6k-1
                //assign the value to potential
                potentialPrime = 6 * _k - 1; 

                //if there are any primes that divise this, it is NOT a prime number
                //using PLINQ for quick boost
                isPrime = !_foundPrimes.AsParallel()
                                       .Any(prime => potentialPrime % prime == 0);

                //if it is prime, add to found list
                if (isPrime)
                    _foundPrimes.Add(potentialPrime);

                if (_foundPrimes.Count() == retrieve)
                    break;

                //analyze 6k+1
                //assign the value to potential
                potentialPrime = 6 * _k + 1;

                //if there are any primes that divise this, it is NOT a prime number
                //using PLINQ for quick boost
                isPrime = !_foundPrimes.AsParallel()
                                       .Any(prime => potentialPrime % prime == 0);

                //if it is prime, add to found list
                if (isPrime)
                    _foundPrimes.Add(potentialPrime);

                //increment k to analyze next
                _k++;
            } while (_foundPrimes.Count() < retrieve);

            return _foundPrimes;
        }
    }

Now there are definitely more things I can do to help make this more efficient, but for the scope of this example, I think this is fine (but still hideous)!

Profiling this now yields a happy surprise 27 seconds to generate the 15000 primes with the profiler attached, and only 1.43 seconds without.  One important thing I wanted to call out though was the performance graph now:

image

Notice anything odd?  The %Processor time is above 100%.  This is because there is now more than 1 core in the operation.  A better label for the chart in my mind would have been %Core time, but to each their own.

Another odd thing I noticed was that the profiler seemed to be spot on this time in my DumbPrimes class with line details in source, even with comments..  Odd.

Profiling Web Applications

The last thing that I wanted to cover, that means a lot to me as a web developer, is the great amount of work that Red Gate put into the profiler when profiling web applications.  In my solution, I have a simple MVC4 application setup with 1 page, a single input form, that will output prime values as my WPF app did.  Launching the profiler from Visual Studio as before, nothing is really different in the profiler window, however I did receive a UAC prompt for a Red Gate helper app to integrate with the web server without notification.

After requesting 500, 1000, 2000, and 5000 primes, and looking at the profiler session, things are slightly different from before:

image

As you can see, there are 4 spikes of activity in the processor time graph, but there is also something new in the call tree:

image

That’s right – ANTS will actually group method calls by get/post operations, so it is easier to find out what action/page is giving the largest problems…  Pretty cool in my mind!

Overview

Overall, I think that Red Gate ANTS CLR Profiler has a lot to offer, however I think it also has a long ways to go. 

3 Biggest Pros:

  • Ability to easily drill down from time graph, to method calls, to source code
  • Wide variety of counters to choose from when profiling your application
  • Excellent integration/grouping of methods being called from web applications by request – BRILLIANT!

3 Biggest Cons:

  • Issue regarding line details in source view
  • Nit pick – Processor time vs. Core time
  • Nit pick – Lack of full integration with Visual Studio

Ratings

Ease of Use (7/10) – I marked down here because of the problems with the line level details and the extra work that that entails, and the lack of better integration with Visual Studio.

Effectiveness (10/10) – I believe that the profiler does EXACTLY what it purports to do.  Especially with its large variety of performance counters, a definite plus!

Features (9/10) – Besides the real time performance monitoring, and the drill downs that I’ve shown here, ANTS also has great integration with ADO.Net, with the ability to show database queries run by your application in the profiler.  This, with the line level details, the web request grouping, reflector integration, and various options to customize your profiling session I think create a great set of features!

Customer Service (10/10) – My entire experience with Red Gate personnel has been nothing but good.  their people are friendly, helpful, and happy!

UI / UX (8/10) – The interface is very easy to get around, and all of the options are easy to find.  With a little bit of poking around, you’ll be optimizing Hello World in no time flat!

Overall (8/10) – Overall, I am happy with the Performance Profiler and its features, as well as with the service I received when working with the Red Gate personnel.  I WOULD recommend you trying the application and seeing if it would fit into your process, BUT, remember there are still some kinks in it to hopefully be worked out.

My next post will definitely be shorter (hopefully), but thank you for reading up to here, or skipping ahead!  Please, if you do try the product, drop me a message and let me know what you think!  I would love to hear any opinions you may have on the product.

Code

Feel free to download the code I used above – download via DropBox

Print | posted on Monday, October 22, 2012 7:51 AM

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Comment:
Verification: