Analyzing User Code with Subsystems

Skip to end of metadata
Go to start of metadata

In previous sections we took care of how our app works with .NET subsystems. But what about finding bottlenecks in our own code? What can subsystems offer for this case? The answer is - hot spots. For each opened subsystem, you can see the list of 10 calls that make the largest contribution in the subsystem’s own time. This makes subsystems a complete solution for analyzing your code from performance perspective and almost eliminates the need of drilling down the call tree. Let’s look at this in action.

  1. Open the list of hot spots for User code in MyProfile
    As you see, the overall execution time of the User code subsystem is insignificant 13 ms. Surely, it’s nothing to improve here. Nevertheless, we’ll use the current example, so that you can get an idea of how to use subsystems for profiling your own code.
     We have already dealt with the database and chart visualization performance, so the GetTemperature call is of no interest to us right now. Next to it comes the CalculateAverage function which is responsible for calculating the average temperature for the selected date. Let’s look on this call in more details. For example, we’re not OK with this time and decide to find out where it comes from.
  2. To open the call’s back trace, you can simply open the context menu for the call (with the right click) and select Go to backtrace.

    The CalculateAverage call will be opened in a new tab. Let’s use the Default profile (as the one containing all common .NET subsystems) to analyze the call.
  3. As you see from the code, all the method (lasts 3ms) does is displaying the result of some static TempData.CalcAverage method on the lblAvgTemp label. If we switch dotTrace Performance to the Call Tree view, we will see the underlying CalcAverage method in more details.

    This method uses the TempList list that stores temperature values and a for loop to calculate the average. So, the most obvious improvement is to refuse from this method at all and use the Average method of the List class. Let’s do this.
  4. In our source we simply replace TempData.CalcAverage().ToString() with the call for the Average method of the List class.  
    After the change, the CalculateAverage() method will look like follows
  5. Get the performance snapshot one more time and check the results.

As you see, the overall time reduced to 1 ms. At the same time, the Linq subsystem requires 0.523 ms (comparing to 0.103 ms in the previous snapshot) as the main job is now done by the System.Linq.Enumerable.Average method.

  • No labels