Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have been playing around with some improvements to some sort algorithms like Selection Sort and Merge Sort and I ended up needing some sort of measurement to check if my versions were any faster than the original algorithm form. I also had a need to implement some sort of time measurement before but never did it, so here came the chance. And so I ended up coding the following measurement method:

public static double Measure(Action action, bool print = true)
{
    Stopwatch watch = new Stopwatch();
    const int precision = 1; //estimated precision of 1 milisecond on my machine
    const int error = 1; //max error
    const int times = 10;
    double min = double.MaxValue;
    for (int i = 0; i < times; ++i)
    {
        int iterations = 0;
        watch.Restart();
        while (watch.Elapsed.Milliseconds < precision*(100-error))
        {
            action();
            ++iterations;
        }
        watch.Stop();
        min = Math.Min(min, watch.Elapsed.Milliseconds*1000.0/iterations);
    }

    if(print)
        Debug.WriteLine("The action takes {0:N4} nanos to complete", min);

    return min;
}

Is this a well conducted measurement algorithm? Any suggestions or improvements that I could apply?

share|improve this question
    
Can you explain what you are checking with watch.Elapsed.Milliseconds < precision*(100-error) condition? –  Sergey Berezovskiy Feb 14 at 12:56
    
I found that the stopWatch has a precision of about a milisecond. And so to only have a error of 1% i need to run a method at least during about 100 milliseconds, although this only applies to the methods that take only some nanoseconds to run. That's also why ChrisW suggested his approach. –  Bruno Costa Feb 14 at 13:49
    
So if my precision decreases (meaning that it would be bigger for example 2 milliseconds) I would need to test the method for about 200 milliseconds to have a 1% error. –  Bruno Costa Feb 14 at 15:32
add comment

1 Answer 1

up vote 6 down vote accepted

The thing you're timing is:

while (watch.Elapsed.Milliseconds < precision*(100-error))
{
    action();
    ++iterations;
}

The problem is that if action takes a very short time, then most of what you're timing is the time it takes to call the watch.Elapsed.Milliseconds property.

A more accurate timer would be something like:

int iterations = 1000;
watch.Restart();
while (iterations--)
{
    action();
}
watch.Stop();

You would then need to do something to ensure you pick a suitable number of iterations (e.g. try again with 10 times as many iterations if the measured time is too short to be accurate).

share|improve this answer
    
You made a point there. I think that I could mix my code with yours. So I would find the number of iterations on 100 milliseconds and than measure the time again using your way. Hopefully will save some precious nanoseconds in measurament. –  Bruno Costa Feb 14 at 2:26
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.