Damon Armstrong

Caffeine Induced Tirades about .NET and Life
And don't forget to check out my latest Simple-Talk articles
Add to Technorati Favorites      Add to Google     

Simple Code Performance Testing

Published Friday, August 24, 2007 3:44 PM

After posting Performance: Caching vs. Reading from an In-Memory XML Document, there have been some questions about how I actually do the performance testing.  My approach to performance testing is really simple... I just write some code, run that code in a big for loop, and time how long it takes to run through all of those iterations.  Nothing too complicated.  Calculating the speed of the operation becomes a simple matter of (iterations / time).  I've packaged this testing routine into a class I call the PerformanceTimer class, which simplifies things even more.  The code for the class follows, and an example of how to use the class to test a routine follows even further down.


using System;

namespace Rebel.Performance
{
    
/// <summary>
    ///   Delegate to a testing method
    /// </summary>
    
public delegate void TestingMethodDelegate(int iterations);

    
/// <summary>
    ///   Executes a testing method and stores execution duration
    /// </summary>
    
public class PerformanceTimer
    {
        
/// <summary>
        ///   Property backer for the ExecutionSpan property
        /// </summary>
        
private TimeSpan _propExecutionSpan;
        
        
/// <summary>
        ///   Property backer for the Iterations property
        /// </summary>
        
private int _propIterations;

        
/// <summary>
        ///   Duration of testing method execution
        /// </summary>
        
public TimeSpan ExecutionSpan
        {
            get { 
return _propExecutionSpan}
            
private set { _propExecutionSpan value}
        }

        
/// <summary>
        ///   Number of iterations for the test
        /// </summary>
        
public int Iterations
        {
            get { 
return _propIterations}
            
private set { _propIterations value}
        }

        
/// <summary>
        ///   Executes testing method and determines execution duration
        /// </summary>
        /// <param name="testingMethod">Delegate to the testing method</param>
        
public void Run(int iterationsTestingMethodDelegate testingMethod)
        
{
            Iterations 
iterations;
            
long startTimeendTime;
            
startTime DateTime.Now.Ticks;
            
testingMethod.Invoke(Iterations);
            
endTime DateTime.Now.Ticks;
            
ExecutionSpan = new TimeSpan(endTime startTime);
        
}

        
/// <summary>
        ///   Number of iterations per second
        /// </summary>
        
public double IterationsPerSecond
        {
            get
            {
                
return (Iterations ExecutionSpan.TotalSeconds);
            
}
        }

        
/// <summary>
        ///   Number of iterations per millisecond
        /// </summary>
        
public double IterationsPerMillisecond
        {
            get
            {
                
return (Iterations ExecutionSpan.TotalMilliseconds);
            
}
        }

    } 
//class

//namespace


So that's the class, but how do you use it?  Here's a simple test application that uses the PerformanceTimer class to check the speed of concatenation operations.  You've always heard that using a StringBuilder to build a string is faster than repeatedly concatenating a string directly?  Here's a chance to actually prove it.   


using System;
using System.Text;
using Rebel.Performance;

namespace Rebel.PerformanceTest
{
    
/// <summary>
    ///   Console Application
    /// </summary>
    
class Program
    {

        
static void Main(string[] args)
        
{
            PerformanceTimer timer 
= new PerformanceTimer();
            
int iterations 100000;

            
//Run TestA
            
timer.Run(iterationsnew TestingMethodDelegate(TestMethodA));
            
Console.WriteLine(timer.IterationsPerMillisecond);
            
            
//Run TestB
            
timer.Run(iterationsnew TestingMethodDelegate(TestMethodB));
            
Console.WriteLine(timer.IterationsPerMillisecond);

            
Console.ReadLine();

        
}
        
        
/// <summary>
        ///   Concatenation using a StringBuilder
        /// </summary>
        
static void TestMethodA(int iterations)
        
{
            StringBuilder s 
= new StringBuilder();
            
for (int 0iterationsi++)
            
{
                s.Append
("A");
            
}
        }

        
/// <summary>
        ///   Direct concatenation
        /// </summary>
        
static void TestMethodB(int iterations)
        
{
            
string "";
            
for (int 0iterationsi++)
            
{
                s 
+"A";
            
}
        }

    } 
//class

//namespace
WARNING: You will want to use as large of an iteration count as possible when testing.  This performance testing approach does the "best" it can when calculating exact start and end times, so some fluctuations are bound to occur when capturing the start and end times.  When they do, the fluctuations throw off the calculations.  Larger iteration counts spread out the effect of the fluctuations and minimize the error.  Think of it this way:  if you are off by 1 in 10, then you have a 10% error.  If you are off by 1 in 10000, you have a 0.01% error.


On my machine, the StringBuilder operates at 14629 iterations / second and the direct concatenation approach runs at 13 iterations / second.  Pretty significant difference. 

by Damon
Filed Under:

Comments

No Comments
You need to sign in to comment on this blog

















<August 2007>
SuMoTuWeThFrSa
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678
Virtual Exchange Servers
 Microsoft now supports running Exchange Server 2007 in server virtualization environments, not just on... Read more...

Virtualizing Exchange: points for discussion
 With the increasing acceptance of the use of Virtualization as a means of providing server... Read more...

Encouraging .NET Reflector Add-ins
 Jason Haley is well-known for the resources he's provided to developers who wish to extend Reflector's... Read more...

Using .NET Reflector Add-ins
 .NET Reflector by itself is great, but it really comes into its own with the help of some add-ins. Here... Read more...

Unique Experiences!
 You'd have thought that a unique constraint was an easy concept - Not a bit of it; it can cause a lot... Read more...