Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Measuring time performance of code blocks automatically

0.00/5 (No votes)
17 Feb 2012 1  
This article shows an easy and automatic way to measure estimate elapsed time while executing code blocks

Introduction

In many cases as programmers develop their applications sometimes they need to know the time that some of code blocks takes to execute. One of the old school ways is to use TickCounts. In this article we use the same trick but in a more user-friendly way.

An improvement I have made in this approach is that the output of result (elapsed time) will show in a proper way! automatically or with a callBackFunction .

Used Namespaces

This class uses three namespaces' functionalities:

using System;
using System.Diagnostics;
using System.IO; 

About the code

The implemented class is inherited from IDispose interface. which applies Disposal attribute to our class that has a great part in this class:

/// <summary>
/// Measures time elapsed for especific code blocks automatically
/// </summary>
class Measurment : IDisposable  

The constructor of this class has two overrides:

/// <summary>
/// Launch time counter immediately.
/// </summary>
/// <param name="callBackFunction">At object's disposal the measured time will send to target function</param>
public Measurment(Action<TimeSpan> callBackFunction);  
 

/// <summary>
/// Launch time counter immediately.
/// </summary>
/// <remarks>
/// The Measured time will print out any way, at any type of Application.
/// </remarks>
public Measurment(); 

The main one takes an delegate predefined in mscorlib.dll signatured as:

public delegate void Action<in T>(T obj);

So the client code can either initialize delegate for callBackFunction:

 // A delegate to call when this object is disposing.
 protected Action<TimeSpan> callBackFunction { get; set; } 

In order to calling when the code blocks region is over and pass throw the elapsed time to callBackFunction at the disposal of the Measurment's object or not ( uses the other constructor ).

In both way the class initialize its callBackFunction.

The constructor with no argument will initialize the callBackFunction as follow:

public Measurment() :
    this((time) =>
    {
        // Here we test if this running project is a console App. or not.
        if (Console.In != StreamReader.Null)
        {
            // we simply throw our calculated elapsed time in console page.
            Console.WriteLine(String.Format("Estimated elapsed time : {0}", time));
        }
        else
        {
            // in here we know that this Running App. type is not a console App. 
            // so we trying to create a batch file in order to show the result in a 
            // promissing way.
            try
            {
                // getting a tmpFile path and name.
                String tmpPath = Path.GetTempFileName() + ".bat";
                using (StreamWriter sw = new StreamWriter( 
                                                        new FileStream(
                                                                        tmpPath, 
                                                                        FileMode.Create,
                                                                        FileAccess.Write, 
                                                                        FileShare.None
                                                                    )
                                                        )
                        )
                        {
                            // writting a proper message in our batch file to show.
                            sw.WriteLine(
                                String.Format("@echo off
                                                \r\n echo Estimated elapsed time : {0} 
                                                \r\n echo. 
                                                \r\n echo.
                                                \r\n pause", time)
                                       );
                        }
                 // Launching created tmpFile and wait till its closed.
                 Process.Start(tmpPath).WaitForExit();
                 // Cleaning up
                 File.Delete(tmpPath);
            }
             catch { }
        }
    })
{}    

The constructor will send a Lambda Expression[^] to the other constructor in order to setting callBackFunction.

The main constructor of the class(the one with parameter) handles the class' initialization:

public Measurment(Action<TimeSpan> callBackFunction)
{
    if (callBackFunction == null)
        throw new ArgumentNullException("callBackFunction",
                                        "this param. cannot be null.");
    
    // initialize the callBackFunction
    this.callBackFunction = callBackFunction;

    // set the startTick
    startTick = Environment.TickCount;
} 

Note:

The function that send as delegate should signature has as follow :

void callBackFunction(TimeSpan elapsedTime); 

And at the end we have the Dispose function(the implementation of IDisposable interface).

At the Dispose function we calculate the elapsed time since the constructor has called till the class' object's disposal, then the created TimeSpan object will send to the callBackFunction.

 public void Dispose()
{
    // measuring time
    int tot = Environment.TickCount - startTick;

    if (callBackFunction != null)
        // calling target function
        callBackFunction(new TimeSpan(tot * 10000));
} 

About the used Lambda Expression

This Lambda Expression does a smart calculation to determine the best way to show the result depended on the running application type.

  • If the running program is a console program so for simply output the result on console
//  Here we test if this running project is a console App. or not.
if (Console.In != StreamReader.Null)
{
    // we simply throw our calculated elapsed time in console page.
        Console.WriteLine(String.Format("Estimated elapsed time : {0}", time));
} 
  • Otherwise the program create a temp batch file in Windows' Temp Folder and launches that batch file in order to indicate the elapsed time.
// in here we know that this Running App. type is not a console App. 
// so we trying to create a batch file in order to show the result in a 
// promissing way.
try
{
    // getting a tmpFile path and name.
    String tmpPath = Path.GetTempFileName() + ".bat";
    using (StreamWriter sw = new StreamWriter(
                                    new FileStream(
                                                    tmpPath, 
                                                    FileMode.Create, 
                                                    FileAccess.Write, 
                                                    FileShare.None
                                                    )
                                                )
            )
    {
        // writting a proper message in out batch file to show.
        sw.WriteLine(
                        String.Format("@echo off
                                        \r\n echo Estimated elapsed time : {0} 
                                        \r\n echo. 
                                        \r\n echo.
                                        \r\n pause", time));
    }
    // Launching created tmpFile and wait till its closed.
    Process.Start(tmpPath).WaitForExit();
    // Cleaning up
    File.Delete(tmpPath);
}
catch { }   

Using the code

This class calculates the elapse time since the class' object has created till it's Disposal.

In order to take full advantage of this functionality any code blocks goes between the Measure's object creation till its Dispose() function call the performance will be measured.

This is a sample usage of the Measure class:

static class Test
{
    static void Main(string[] args)
    {
        using (new Measurment())
        {
           /*
            * Any code blocks here like the follow 
            */ 
            System.Threading.Thread.Sleep(2000);
        }
        Console.ReadKey(true);
    }
} 

This should calculate the time approximately 2 seconds(The sleep function does not sleep exactly the given time to sleep).

Points of Interest

This class uses the old school trick to measure the elapse time for executing code blocks in proper and in a handy way.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here