dotTrace 2016.2 Help

Timeline Viewer Concepts

As mentioned in Basic Concepts, the main idea behind timeline profiling is collecting temporal call stack and thread state data. Thus, it allows you not only evaluate the performance of certain methods but also get detailed info about how performance flaws are distributed in time. This is extremely helpful in analyzing UI freezes, sync delays, excessive garbage collections, file I/O, and other interval events.

Timeline Viewer UI is tailored for convenient work with the event timeline: It is a set of filters and diagrams that allows you to filter and visualize temporal data.


Analysis workflow in Timeline Viewer is quite simple:

  1. You select profiling data on input. This can be either Time data, Memory Allocation data, or data about raised Exceptions.
  2. You slice and dice the data using filters (not only using Filters - Timeline and Call Stack can also add filtering by time, thread, or particular method). The result of filters' work is always a set of time intervals or point events selected by a specific condition. For example, you can ask the viewer to "Select all time intervals where the Main thread is running" or "Select all time intervals where blocking garbage collection is performed".
  3. You view and analyze the filtered data.

Here we come to a couple of concepts you need to know for successful data analysis in Timeline Viewer.

Everything Is a Filter

Both steps 2 and 3 are performed using the same UI controls. Thus, each control is used not only to set a specific filter but also to display a chunk of filtered information.

For example, the Thread State filter not only allows you to apply a filter by thread state but also displays how long selected threads were in particular states.

Filters Are Chained Together

Filters can be grouped in chains. Complex filter combinations allow you to analyze almost any aspect of your app.

For example, if you combine the "Select all time intervals where the Main thread is running" and "Select all time intervals where blocking garbage collection is performed" filters, you will get the resulting filter "Select all time intervals where the Main thread is running during garbage collections". In other words, this filter combination will leave only the time intervals where the Main thread toggled GCs. The Call Stack | Top Methods filter will show you the exact methods that toggled collections.

How This Works. Example

For example, you have an app running three threads: Main Thread, Thread#1, and Thread#2. Your app extensively works with file system: it reads and writes to disk a lot, which results in poor app performance. You decide to profile the app and find the methods that can be optimized.

StepHow This Looks in Timeline Viewer
1. You run dotTrace and profile your app during the performance drop. For simplicity, let's take that profiling lasted 100 ms. The Threads diagram looks like follows:

It appears that most of the profiling time all three threads worked (blue intervals). There were also time intervals where threads waited (pale blue).
2. You look at Interval Filters in the Filters window to determine events that took place in the app.

Interval Filters show that File I/O was quite significant and took 100 ms - 33.33% of the total analyzed time interval (which is equal 300 ms = 3 threads * 100 ms profiling time).
3. You select File I/O in Interval Filters to apply filter by file I/O operations.
The filter you get is "Select all time intervals where Main Thread, Thread#1, and Thread#2 performed file operations."

After you apply the filter, the values in all filters are recalculated related to the file I/O time. For example, the User Code value of 95.00% says that almost all file operations were performed by your own code.

The Threads diagram also filters out the file I/O intervals:

It appears that the majority of file operations (80.00%) were performed by Thread#2.
4. You select Thread#2 in the Threads diagram to apply the filter by this thread. The resulting filter you get is "Select all time intervals where Thread#2 performed file I/O operations". The Threads diagram filters out the thread:

Interval Filters are also recalculated related to Thread#2:

Thus, 100.00% of User Code say that all Thread#2 file operations were performed by your own code.
5. You look at Top Methods in the Call Stack window to determine methods that performed file operations. The filter shows that 90.00% of file operations were performed by MyApp.SomeReadMethod.
It might also be worth to investigate Call Tree and find out who calls MyApp.SomeReadMethod. This makes sense as MyApp.SomeReadMethod is probably a simple low level method that only reads from disk.
6. You optimize the MyApp.SomeReadMethod method or the methods that call it in order to reduce the amount of file operations.
Last modified: 15 December 2016