Measuring Code Execution Time in C Sharp
Occasionally, part of a programmers job, once the basic functionality of an app is up and running, is to consider code performance. One task in speeding up an app is to see which parts run slower than others. Whilst .NET does support performance counters, basic timing of code execution can be done with the .NET Stopwatch class.
Using the .NET Stopwatch to Measure Code Execution Time
In this example a .NET Stopwatch is used to time the sorting of a list of numbers. The example timing code provided in this tutorial is in a basic WinForms app. After starting a new WinForms project in Visual Studio, open the starting form. Then use System.Diagnostics to access the .NET Stopwatch:
using System.Diagnostics;
Create an instance of the Stopwatch for use in the program:
Stopwatch sw = new Stopwatch();
A list of integers is going to be generated and stored in a List
//Number of random numbers
const int NUMBER_OF_NUMBERS = 100;
//To store some random numbers
List<int> Integers = new List<int>(NUMBER_OF_NUMBERS);
//Store a backup for resetting
List<int> Backup;
In the forms constructor generate the numbers to sort, here using the Random class:
//Generate a list of numbers
//Random number generator
Random Rng = new Random();
for (int i = 0; i < NUMBER_OF_NUMBERS; i++)
Integers.Add(Rng.Next());
Rng = null;
Then backup the list for later list resetting:
Backup = new List<int>(Integers);
A ListBox is dropped onto the form to display the numbers:
listBox1.DataSource = Integers;
Drop a Button onto the form, when clicked it will do the sort and update the display:
private void button1_Click(object sender, EventArgs e)
{
Integers.Sort();
//Update display
listBox1.DataSource = null;
listBox1.DataSource = Integers;
}
To time the sort wrap the call in a Stopwatch Start() and Stop():
sw.Start();
Integers.Sort();
sw.Stop();
The ElapsedTicks of the Stopwatch gives a count of how many processor ticks occurred. The Frequency of the Stopwatch gives the number of ticks per second. Thus, the time is ElapsedTicks/Frequency, converted to double to avoid division issues:
double elapsedTime = (double)sw.ElapsedTicks / (double)Stopwatch.Frequency;
This will be a small number with our modern processors, therefore, convert it to microseconds by multiplying by 1,000,000 (or milliseconds by times 1,000), makes for easy reading:
string executionTime = (elapsedTime * 1000000).ToString("F2") + " microseconds";
Drop a ListBox onto the form to display the timings:
listBox2.Items.Add(executionTime);
Reset the Stopwatch ready for the next thing to time:
sw.Reset();
To run the sort several times, add another button to restore the original list to its initial starting condition:
private void button2_Click(object sender, EventArgs e)
{
//Reset to original random list
Integers = new List<int>(Backup);
listBox1.DataSource = Integers;
}
Here is the code's first run showing the unsorted numbers:
Here is the timing of the sort execution. The code was run on a PC with an i7-4770 3.4 GHz Intel CPU that produces 3,312,657 ticks per second (the number of ticks will vary by CPU). The timings list shows several runs of the sort (using the sort and reset buttons several times):
Notice that there is a variation in the time taken to execute the sort function, especially the first sort. Variation in code execution times is down to several factors. Those factors can include one or many of the following (though not all of the following applies in the simple example shown here):
- The data being processed
- Windows and .NET memory caching
- .NET JITing
- Garbage collection
- The Windows operating systems (OS) running other tasks (Windows is not a real-time operating system)
- Disk caching
- CPU caching
- Accessing system resources (disks, network, Internet, databases, etc.)
When looking to speed up code use the timings after the first pass has executed. If first run time is important then Ngen can be used to reduce the start time.
Full Timing Execution Example Code
Here is the full code for the form used to demonstrate the timing of executing code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Diagnostics;
namespace ExecutionTiming
{
public partial class Form1 : Form
{
Stopwatch sw = new Stopwatch();
//Number of random numbers
const int NUMBER_OF_NUMBERS = 100;
//To store some random numbers
List<int> Integers = new List<int>(NUMBER_OF_NUMBERS);
//Store a backup for resetting
List<int> Backup;
public Form1()
{
InitializeComponent();
//Generate a list of numbers
//Random number generator
Random Rng = new Random();
for (int i = 0; i < NUMBER_OF_NUMBERS; i++)
Integers.Add(Rng.Next());
Rng = null;
//Back up the unsorted list for reseting later
Backup = new List<int>(Integers);
//Display the list to sort
listBox1.DataSource = Integers;
}
//Sort the list and time the sort
private void button1_Click(object sender, EventArgs e)
{
sw.Start();
Integers.Sort();
sw.Stop();
//Calculate elapsed time
double elapsedTime = (double)sw.ElapsedTicks / (double)Stopwatch.Frequency;
//Convert to a string
string executionTime = (elapsedTime * 1000000).ToString("F2") + " microseconds";
//Show the execution time
listBox2.Items.Add(executionTime);
//Reset the stopwatch ready for next timing
sw.Reset();
//Update sort display
listBox1.DataSource = null;
listBox1.DataSource = Integers;
}
//Reset to the original unsorted list
private void button2_Click(object sender, EventArgs e)
{
//Reset to original random list
Integers = new List<int>(Backup);
//Show the unsorted list again
listBox1.DataSource = Integers;
}
}
}
See Also
- Timing with the Stopwatch demo in C# High Resolution Timer
- For a full list of the articles on Tek Eye see the website's index.
Author:Daniel S. Fowler Published: