serge
serge

Reputation: 15229

Compare 2 method's performance

I have the following:

public class Logger
{
    public static void LogStartMethod(MethodBase method)
    {
        Console.WriteLine("{0} Method '{1}' started", DateTime.Now, method.Name);
    }

    public static void LogStartMethod1()
    {
        StackTrace stackTrace = new StackTrace();
        MethodBase method = stackTrace.GetFrame(0).GetMethod();
        LogStartMethod(method);
    }

    public static void LogStartMethod2()
    {
        MethodBase method = MethodBase.GetCurrentMethod();
        LogStartMethod(method);
    }
}

I would like to identify the most performant method between LogStartMethod1 or LogStartMethod2...

Let's make abstraction of what that concrete method does, but is there a tool (online, or Visual Studio add-in) able to compare the performance of 2 methods?

I now that there are a lot of commercial performance profilers... and we should pay or use Visual Studio Ultimate to have a performance tool for a entire solution....

I would like just to compare 2 methods, it's all...

Upvotes: 0

Views: 958

Answers (4)

Gusdor
Gusdor

Reputation: 14334

I can tell you now that anything that assembles a stack trace will be slower than similar(tm) code that does not.

The fastest way to grab the calling methods name is using the System.Runtime.CompilerServices.CallerMemberName attribute. When you compile the code, the compile inserts the method name as a string literal. It is very quick but requires C# .5

This is my tried and tested perf code with sample methods thrown in to demonstrates the issue:

class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, Action> tasks = new Dictionary<string, Action>();
        List<string> results = new List<string>();

        tasks.Add("Task 1", Task1);
        tasks.Add("Task 2", Task2);
        tasks.Add("Task 3", Task3);

        string input = "This is a sample string";
        int count = 9999;

        Console.Write("Warming up...");
        foreach (var item in tasks.Values)
        {
            item();
        }
        Console.WriteLine("Done.");

        Console.WriteLine();
        Console.WriteLine();

        foreach (var item in tasks)
        {
            var time = RunPerf(item.Key, count, item.Value);
            results.Add(string.Format("{0}\t\t{1}", item.Key, time));
        }

        Console.WriteLine();
        Console.WriteLine("RESULTS");
        foreach (var item in results)
        {
            Console.WriteLine(item);
        }

        Console.ReadLine();
    }

    public static void Task1()
    {
        StackTrace stackTrace = new StackTrace();
        MethodBase method = stackTrace.GetFrame(0).GetMethod();
        LogStartMethod(method);
    }

    public static void Task2()
    {
        MethodBase method = MethodBase.GetCurrentMethod();
        LogStartMethod(method);
    }

    public static void Task3()
    {
        LogStartMethod();
    }

    public static void LogStartMethod(MethodBase method)
    {
        Console.WriteLine("{0} Method '{1}' started", DateTime.Now, method.Name);
    }
    public static void LogStartMethod([System.Runtime.CompilerServices.CallerMemberName]string methodName = null)
    {
        Console.WriteLine("{0} Method '{1}' started", DateTime.Now, methodName);
    }

    static TimeSpan RunPerf(string name, int count, Action action)
    {
        var sw = new System.Diagnostics.Stopwatch();
        Console.WriteLine(string.Format("Starting perf for {0}. {1} times", name, count));

        sw.Start();
        for (int i = 0; i < count; i++)
        {
            action();
        }
        sw.Stop();
        Console.WriteLine(string.Format("{0} completed in {1}", name, sw.Elapsed));

        return sw.Elapsed;
    }
}

Note. Be sure to run this code in release. It requires C#5. I recommend using a .net 4.5 project

RESULTS
Task 1          00:00:00.7226149
Task 2          00:00:00.5001454
Task 3          00:00:00.4690296

Upvotes: 2

Konrad Kokosa
Konrad Kokosa

Reputation: 16878

I suggest using simply Performance Counters on two solutions, one using method LogStartMethod1 and second using LogStartMethod2. Call this method for a few minutes continuously, and watch counters like % Processor Time and .NET CLR Memory for running process and measure of course a total number of method executions. Then you will see time processing difference along with difference in both CPU and memory consumption.

Upvotes: 1

Sam Axe
Sam Axe

Reputation: 33738

The StopWatch class can measure speed.
call StopWatch.Start before your test, and StopWatch.Stop afterwards.

Just remember to run the speed test in release mode, not debug mode.

Upvotes: 5

mnemonic
mnemonic

Reputation: 1645

VS 12 Ultimate: check out menu item ANALYZE & Start Performance Analysis --- it delivers interesting feedback and not only related to 2 methods --- have tried it this week and the result was really fruitful for both current state and future direction of some coding issues.

Upvotes: 1

Related Questions