We observed sluggish performance in some “proof of concept“ code yesterday; I pealed back the layers of the onion to find what optimizations I could make. Of course, measurement is a key to doing code optimization; it’s how you quantify any progress you’re making! I’ve had success with the Win32 API for QueryPerformanceCounter (this Microsoft KB article breaks basic usage of QueryPerformanceCounter down succinctly); you could try something with System.DateTime, but the resolution isn’t really there for accurate measurement unless you’re working with really slow code. If you’re serious about analyzing the duration code takes to execute, I’d get comfortable with QueryPerformanceCounter and consider wrapping it into a quick CodeTimer class for ease of reuse. Besides, you get to add those slick DllImports and Kernel32 calls to your code!
This particular sluggish code was easy to tune: I replaced inline SQL with parameterized stored procs and, where appropriate, combined SQL statements together to minimize the calls to the database. The result was much quicker and, incidentally, more secure and maintainable (stored procs are superior to inline sql in nearly every way!) — the standard sort of thing you do when turning proof-of-concept code into something more production-ready.
I should note that an optimization that didn’t improve the performance was switching foreach(x in y) blocks with standard for(i=0;i<n;i++) syntax; many sources will include this optimization as a slightly quicker way to iterate over your collections. In this case, the loop wasn’t executed enough times to factor into the bigger picture. Again, the only way I know this is because I had a quantifiable way to measure the duration of the executing code — just eye-balling it or casually observing my human perception of code performance is completely inadequate for the task.
This is just one tactic in the pursuit of fast executing .Net code. There are numerous other (and often more significant!) steps to take, including hardware monitoring, network traffic analysis, garbage collection inspection (John Robbins from Wintellect first turned me on to this — check out the Wintellect group blog for their latest insights), and many many more. There are whole books on the subject, in fact.
So, get comfortable with QueryPerformanceCounter to time your code, but don’t rely on it exclusively for optimizing your applications. Think of QueryPerformanceCounter as a screwdriver in the much bigger toolbox of improving .Net code perf — it’s a very useful tool but not the end-all-be-all of tools.