What is the best way to measure how long code takes to execute?
I'm trying to determine which approach to removing a string is the fastest.
I simply get the start and end time and show the difference.
But the results are so varied, e.g. as shown below the same method can take from 60 ms to 231 ms.
What is a better method to get more accurate results?
alt text http://www.deviantsart.com/upload/1q4t3rl.png
using System;
using System.Collections;
using System.Collections.Generic;
namespace TestRemoveFast
{
class Program
{
static void Main(string[] args)
{
for (int j = 0; j < 10; j++)
{
string newone = "";
List<string> tests = new List<string>();
for (int i = 0; i < 100000; i++)
{
tests.Add("{http://company.com/Services/Types}ModifiedAt");
}
DateTime start = DateTime.Now;
foreach (var test in tests)
{
//newone = ((System.Xml.Linq.XName)"{http://company.com/Services/Types}ModifiedAt").LocalName;
newone = Clean(test);
}
Console.WriteLine(newone);
DateTime end = DateTime.Now;
TimeSpan duration = end - start;
Console.WriteLine(duration.ToString());
}
Console.ReadLine();
}
static string Clean(string line)
{
int pos = line.LastIndexOf('}');
if (pos > 0)
return line.Substring(pos + 1, line.Length - pos - 1);
//return line.Substring(pos + 1);
else
return line;
}
}
}
You should use System.Diagnostics.Stopwatch, and you might want to consider a large sample. For example, repeat this test something like 10,000 times and average the results. If you think about it scientifically, it makes sense. The larger the sample, the better. You can weed out a lot of edge cases this way and really see what the core performance is like.
Another thing to consider is that JIT compilation and object creation can definitely skew your results, so make sure that you start and stop your Stopwatch at the appropriate times, and call the methods you want to test at least once before you begin your tests. Try to segregate just the parts you want to test from the rest of your code as much as possible.
Three simple notes:
Use System.Diagnostics.Stopwatch.
Don't profile your code on the same input one million times. Try to find your expected distribution of inputs and profile on that. That is profile on real-world input, not laboratory input.
Run the
Clean
method once before entering the profiling loop to eliminate JITting time. Sometimes this is important.
Of these, notes 1. and 2. are by far the most important.
Your profiling results are meaningless if you are not using a high-resolution timer. Note that we don't time Usain Bolt using a water clock.
Your profiling results are meaningless if you are not testing on real-world input. Note that crash tests crash cars head on into other cars at 35 MPH, not into walls made of marshmellows at 5 MPH.
Thus:
// expectedInput is string[1000000]
// populate expectedInput with real-world input
Clean(expectedInput[0]);
Stopwatch sw = new Stopwatch();
sw.Restart(); //So you dont have to call sw.Reset()
for (int i = 0; i < 1000000; i++) {
string t = Clean(expectedInput[i]);
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
One complex note:
If you really need to do profiling, get a profiler like ANTS.
You can use the Stopwatch class.
The Stopwatch measures elapsed time by counting timer ticks in the underlying timer mechanism. If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time.
var sw = new Stopwatch();
sw.Start();
// ...
sw.Stop();
If you're only worried about testing it in your own code...use a System.Diagnostics.Stopwatch
I usually prefer breaking this kind of thing out of my code and using a true Profiler like RedGate's Performance Profiler