Line-by-line profiling with dotTrace Performance

dotTrace Performance allows us to profile an application in several ways. We can choose between sample profiling, tracing profiling and line-by-line profiling. Generally sampling profiling is used first to acquire a high-level overview of call performance in an application, after which tracing and line-by-line profiling is used to close in on a performance issue.

Profiling types

Sampling is the fastest and the least precise mode of profiling. With sampling, dotTrace basically grabs current call stacks on all threads once in a while. When capturing a snapshot, the number of calls isn’t available and times are approximate. Accuracy cannot be more than the sampling frequency.

Tracing is slower yet more precise than sampling. Instead of grabbing call stacks on all threads, tracing subscribes to notifications from the CLR whenever a method is entered and left. The time between these two notifications is taken as the execution time of the method. Tracing gives us precise timing information and the number of calls on the method level.

Line-by-line is the slowest yet most precise mode of profiling. It collects timing information for every statement in methods and provides the most detail on methods that perform significant work. We can specify exactly which methods we want to profile or profile all methods for which dotTrace Performance can find symbol information.

Advantages of line-by-line profiling

Line-by-line profiling is the most accurate method since it provides exact timing information on the statement level. While sampling and tracing give us an idea of the individual methods being called and their execution time, these profiling methods do not provide statement-level info. When a method body contains a lot of logic, sampling and tracing will not provide information that is accurate enough to analyze performance of that method. Consider the following source code:

If we use tracing profiling, dotTrace allows us to find out that the Foo method is taking up 98,82% of execution time. However if we look at the source code view at the bottom, there is no information provided on which statement(s) are responsible for this.

By right-clicking the Foo method, we can add this function to a line-by-line profiling session.

Once we’ve run line-by-line profiling, the source code view provides us with profiling information at the statement level. This becomes clear when having a look at the source code view below. We can clearly see that the for loop consists of 3 statements that are executed by the CLR. What’s more important though, is the color coding dotTrace uses to visualize the number of calls per statement. Line 24 is being executed 400 times, the light blue background for that line depicts that it uses most execution time relative to other statements.

Using line-by-line profiling, we are able to have a very detailed view on our application’s performance. Using sampling or tracing we can determine which methods are taking most execution time which we can drill further into using line-by-line profiling.