Filip's homepage

Friday, 07 March 2008

When Time is of the Essence

Tags: .NET Programming

I was reading this post today and, while I like the possibility to easily time specific parts of my code, I thought the solution given there was not accounting for a number of scenarios:

  • What if we want to call a method that has parameters, or one that has a return value ?
  • If an exception occurs in the method that's being timed, the timer breaks.
  • The code being timed is limit to a single method. Ofcourse, we can always refactor our code in this direction, but still.
  • Switching from a method call to passing method call as a delegate seems to change the semantics of the code. This might be a personal thing though.

I've used a similar solution in a number of my projects, which is based on a ctor/dispose-construct. Using it is as simple as placing a 'using'-construct around the code that you want to time:

using (new PerformanceTimer("Running MySlowMethod and MyOtherSlowMethod with parameters"))
{
   MySlowMethod(X);
   MyOtherSlowMethod(Y);
}

Running this will result in output being printed to the Log console telling us how long it took to execute the code. The code for the PerformanceTimer class is relatively simple:

public class PerformanceTimer : IDisposable
{
   private DateTime _start;
   private string _caption;

   public PerformanceTimer(string caption)
   {
      _caption = caption;
      _start = DateTime.Now;
   }

   public void Dispose() {
      Log.Info("{0}: {1}ms.", _caption, Passed.TotalMilliseconds);
   }

   public TimeSpan Passed { get { return DateTime.Now - _start; } }
}

What I'm currently interested in is a way of storing these timing results in a database without influencing the performance of the application itself. That way I am able to easily collect live performance data over longer periods of time.

Posted by Filip at 15:05.
There are 5 comments:
I apologise for the horrible formatting of this post. Trunk version of FDO has a decent code highlighter, I will upgrade to a new version here as soon as I'm somewhat sure of the stability :-) Posted by Filip Duyck on Friday, 07-Mar-2008 at 16:07.
Mate... you should use this [ http://code.google.com/p/syntaxhighlighter/ ] like I do... it's nice, and very practical. Cheers P.S. I'm loving the Refactoring book ;-) Posted by Bruno Alexandre (not verified) on Sunday, 09-Mar-2008 at 01:09.
Hey Filip, What you can do is post the result to a 'Statistics collector service' on a background thread (ThreadPool.QueueUserWorkItem). Then in your statistics service, you can keep statistics for a period of time then at specific interval, compute some results (slowest method, average method call times ...) and flush them to a file or a database. This is for runtime needs, if you really don't have another solution ... at development time, better use Jetbrains' dotTrace profiler ;o) Posted by Steve Degosserie (not verified) on Wednesday, 09-Apr-2008 at 10:25.
If you want to Log the perfomance couters you can try to use log4net, NLog or so. They provide very performant ways of doing it, even for the Database. There are options to collect logs in memory and then flush them once. It will be easy to disable logs at runtime if they affect performance or just are not needed. But if you really just want to find bottleneck in yuor code follow the suggestion from Steve Degosserie and use dotTrace, ANTS Profiler or whatever. Posted by Dmitriy Nagirnyak (not verified) on Tuesday, 29-Apr-2008 at 01:14.
@Dmitriy, @Steve: I'll definitely be checking out the option of keeping it in memory for a while before flushing it out to the DB, that sounds pretty interesting. I've toyed with dotTrace before and I like it alot, but what I'm looking for is really more of a runtime solution that will serve as a health monitor when the application is in production. Posted by Filip Duyck on Tuesday, 29-Apr-2008 at 13:46.