SharpDevelop Community

Get your problems solved!
Welcome to SharpDevelop Community Sign in | Join | Help
in Search

Siegfried Pammer

April 2009 - Posts

  • Merging of Calls – Pinpointing Interesting Methods

    As mentioned in the previous post, SharpDevelop 3.1 will contain a built-in profiler.

    Today we'll talk about what data the profiler collects, and what exactly "merging" is.

    We’ll use the following sample program for exploring the topic:

    using System;
    using System.Threading;

    namespace ICSharpCode.Profiler.Example1
    {
        class Program
        {
            static void DoCalculation(bool doLotsOfWork) {
                if (doLotsOfWork) {
                    int target = Environment.TickCount + 1000;
                    while (Environment.TickCount < target) { }
                } else
                    Thread.Sleep(100);
            }
           
            static void SomeMethod() {
                DoCalculation(true);
            }
           
            static void SomeOtherMethod() {
                for (int i = 0; i < 10; i++) {
                    DoCalculation(false);
                }
            }
           
            static void Main() {
                SomeMethod();
                SomeOtherMethod();
            }
        }
    }

    SomeMethod and SomeOtherMethod take the same amount of time, but for different reasons.

    If we simply store timing information per method, it would seem that DoCalculation spends 50% of the time in get_TickCount and 50% in Thread.Sleep.

    But a good profiler should be able to show that only the invocations of SomeMethod spend their time in get_TickCount, whereas SomeOtherMethod ends up spending time in Thread.Sleep.

    Or, assume you have a program with a textbox and a button. You click on the button, then change the text (input to the program) and then run the button code again. The other input might mean that the performance characteristics of the button method change dramatically - so ideally, we should be able to view each click separately.

    What data does the profiler have to collect to do this? The easiest solution would be to record all function calls. For each function call, store the function ID, the call start time, and the call end time.

    That way, we don't lose any data; we can reconstruct the application's stack at every point in time.
    Of course, if you are looking into a performance issue, you don't want to look at individual stack traces - you want a little more overview. Or expressed for our textbox/button example: It is nice to be able to separately view the data for each button click; but initially, you'll want to look at all data at once.

    Now we get to our data model: when you're using the SharpDevelop profiler, you're dealing with "merged" sets of individual calls. Instead of seeing a single call stack, you'll see the tree of all call stacks.

    For our example code, this looks like in the following screenshot:


     
    Note that the ten calls to DoCalculation inside SomeOtherMethod were merged into a single node in the tree view (a "merged" call). In this view, you are not able to view an individual call's timing data, only the sum of all individual times. However, the DoCalculation call inside SomeMethod and that in SomeOtherMethod are still separate, as these have different call stacks.

    If you want to view them together, select both calls and use Right Click > Merge.

    A new tree will open with all 11 calls merged together:


     
    No matter whether we're dealing with multiple calls after each other, or with calls in different positions in the tree, it's always the same operation: merging. You can even merge calls of different functions together - though unless the functions do similar things, you won't get useful results.

    For example, here you can see SomeMethod and SomeOtherMethod merged together:


     
    Note that merging functions also merges their children (grouped by function name).

    Now it's pretty clear what the timeline control above does: the profiler takes all root nodes from all stack traces in the selected time span, and merges nodes belonging to the same thread.

    However, naïvely storing every function call individually takes a lot of space - about 7 GB (!) for SharpDevelop starting and opening its own solution (SharpDevelop.sln). That's why the profiler limits you to selecting start and end positions for the time spans with a granularity of about 500ms: during profiling, the profiler hook merges the calls into data sets of about 500ms.

    We never actually create the "function start,end"-entries proposed above, but directly build a merged representation as the profiler runs. That way we dramatically reduce the size of the profiler output: only 198 MB for SharpDevelop starting and opening its own solution.

    In the next post we will give you a brief overview of all the other commands you can access in the context menu of each call and how to use them.

    Posted Apr 13 2009, 02:20 PM by siegi44 with no comments
    Filed under:
  • Introducing a New Tool in SharpDevelop – The Profiler

    Nearly one year ago, we started building a new tool for SharpDevelop: a profiler. It will make it easier to analyze and improve the performance of applications developed using SharpDevelop. In the next few weeks we are going to give you an overview of all the different aspects of the profiler, its usage and we will shed some light on its implementation and technical details.

    Using the Profiler

    To start a new profiler session just go to “Quality Tools” > “Profiler” and then you can decide whether to profile the currently opened project or you can select a program to run.


    During execution of the application, performance data is collected. On program end, SharpDevelop will automatically open up the session and display the collected data.

     

    In the “Overview” tab, all threads and all calls are listed. In the “Top 20” tab 20 methods, in which most time is spent during run time, are listed. On the right side you can see the ring diagram. The concept of the ring diagram was taken from the Ubuntu “Disk Usage Analyzer”. It can be used to easily navigate to deep levels of the call tree. Just click on a call to move there. If you want to go back to the call you had selected before, just click inside the gray circle in the middle.

    To show details on a call in the ring diagram simply move the mouse over it and a tool tip with important information will be displayed. The gray circle represents the call currently selected in the tree view. The innermost ring is a pie chart showing the children of the selected call. The size of each piece is proportional to the time spent inside that call. The other rings represent the deeper levels of the call tree.

    In the next post we will show you the “merge” feature, which allows you to view multiple parts of the call tree at once. The “merge” feature is used by the “Top 20” tab and the timeline too.

    Posted Apr 04 2009, 06:43 PM by siegi44 with no comments
    Filed under:
Powered by Community Server (Commercial Edition), by Telligent Systems
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.