-7

I recently came across a pair of functions from js-land that I rather like:

console.time("CalcPrimes");
// Go calculate primes
console.timeEnd("CalcPrimes");
// Outputs something like > CalcPrimes: 2150ms

Behind the scenes it's a simple dictionary that records the starting timestamp and prints duration by subtracting start time from end time.

Compare this with .NET code:

var sw = new Stopwatch();
sw.Start();
// Go calculate primes
sw.Stop();
Trace.WriteLine("CalcPrimes:" + sw.ElapsedMilliseconds);

My naive code requires twice as many lines to do the same thing (Note: you can do it in just two). However, I still have to manually format output. When I have to inject non-core logic into my app, I want the least clutter possible. Mostly, I'm against the duplicate logic to format the output everywhere I might time something.


  1. Are there existing solutions in the .NET world for a less verbose timer/stopwatch?
  2. If not, what dangers should I be aware of in creating a similar solution to the js code? (or example, should I use a Dictionary<String, Stopwatch> instead of saving off Date.Now due to precision issues?
Community
  • 1
  • 1
Jeff B
  • 8,572
  • 17
  • 61
  • 140
  • 6
    You could refactor the object instantiation and `Start` invocation into a new method on a static helper class, and the `Stop` and `Trace` calls as well. But, really, is this so offensive? IMHO this is hardly *verbose*. – Yuck Dec 30 '13 at 20:58
  • 2
    FWIW, you could use `var sw = Stopwatch.StartNew()` and save a line. – dee-see Dec 30 '13 at 20:59
  • I agree with @Yuck. It wouldn't be hard to implement this yourself, but given the complexities of multithreading (which JS doesn't have), the C# way of doing things looks a lot better. – p.s.w.g Dec 30 '13 at 21:01
  • @Yuck From the answers/comments it looks like I can reduce the lines of code quite a bit. I think what I'm mostly opposed to is the duplication of output formatting logic. I'm seen a lot of inconsistency (and sometimes downright incorrect code) in apps I've worked on, so I'd really like to *just do in right, once*. A static helper method sounds like the right path to take here. – Jeff B Dec 30 '13 at 22:15

2 Answers2

4

How about writing an helper method like

long ElapsedMilliseconds(int n, Action action)
{
    action(); 
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < n; i++)
    {
        action();
    }
    return sw.ElapsedMilliseconds;
}

and call it

var duration = ElapsedMilliseconds(5, ()=>CalculatePrimes());
L.B
  • 114,136
  • 19
  • 178
  • 224
  • I like this, definitely some appeal to have a diagnostic method that accepts an arbitrary method. I'll add only that if you'd planning to do anything more complex than this it may be better to seek out a dedicated library. – Yuck Dec 30 '13 at 21:06
  • +1 for sure, I think I prefer `return sw.ElapsedMilliseconds/((double)n);` but that is just a variation. – Johan Larsson Dec 30 '13 at 21:13
3

What about this:

var sw = Stopwatch.StartNew();
// Go calculate primes
Trace.WriteLine("CalcPrimes: {0} ms", sw.ElapsedMilliseconds);

I have found this extension useful:

public static class StopwatchExt
{
    public static string GetTimeString(this Stopwatch stopwatch, int numberofDigits = 1)
    {
        double s = stopwatch.ElapsedTicks / (double)Stopwatch.Frequency;
        if (s > 1)
            return Math.Round(s, numberofDigits) + " s";
        if (s > 1e-3)
            return Math.Round(1e3 * s, numberofDigits) + " ms";
        if (s > 1e-6)
            return Math.Round(1e6 * s, numberofDigits) + " µs";
        if (s > 1e-9)
            return Math.Round(1e9 * s, numberofDigits) + " ns";
        return stopwatch.ElapsedTicks + " ticks";
    }
}
Johan Larsson
  • 17,112
  • 9
  • 74
  • 88