Tracing & Instrumenting ASP.NET Application For Performance

 Alik Levin    Tracing or Instrumentation is invaluable, most effective, and efficient when dealing with performance problems in ASP.NET Applications. The problem is that it requires coding that too often cut or even never planned to be made.

Quick Resource Box

The other downside is some instrumentation implementations are based on heavyweight logging that introduces even more performance problems.

In this post I am sharing my simple techniques I was using for tracing ASP.NET applications without heavy weight coding and without affecting performance significantly. It produced results relatively quick – we were able to put our fingers on the root cause for slowly performing functions relatively quick.

Instrument with System.Diagnostics.Trace

I am using simple class to report function Entry and Exit using System.Diagnostics.Trace class similar to this [I am sure you can prettify it even more]:

namespace Instrumentation {     public class Tracing     {         public static void TraceFunctionEnter()         {             StackTrace st = new StackTrace();             System.Diagnostics.Trace.WriteLine(true, "TRC: ENTERING: " + st.GetFrame(1).GetMethod() + "USER:" + System.Web.HttpContext.Current.User.Identity.Name);         }         public static void TraceFunctionExit()         {             CheckAndFixDefaultListener();             StackTrace st = new StackTrace();             Trace.WriteLineIf(true, "TRC: EXITING: " + st.GetFrame(1).GetMethod() + "USER:" + System.Web.HttpContext.Current.User.Identity.Name);         }         public static void CheckAndFixDefaultListener()         {             DefaultTraceListener dtl = null;             TraceListenerCollection listeners = System.Diagnostics.Trace.Listeners;

            if (listeners.Count == 0)             {                 dtl = new DefaultTraceListener();                 Trace.Listeners.Add(dtl);                 return;             }             foreach (TraceListener listener in listeners)             {                 string listenerType = listener.ToString();                 if ((string.Compare(listenerType, "System.Diagnostics.DefaultTraceListener", true) == 0))                 {                     return;                 }             }             dtl = new DefaultTraceListener();             Trace.Listeners.Add(dtl);         }     } }

Next is simply calling on static methods when entering and exiting the functions:

protected void Button1_Click(object sender, EventArgs e) {     Instrumentation.Tracing.TraceFunctionEnter();     //DO STUFF     System.Threading.Thread.Sleep(3000);     Instrumentation.Tracing.TraceFunctionExit(); }

Collecting Instrumentation Information

Until recently I was using freely available Sysinternals DebugView. Here is how instrumented code would look in DebugView:


Even though I have not reported timestamps, DebugView have it’s own stop watch and shows the timestamps precisely.

Recently I discovered new and improved [freely available] Procmon that is able to capture System.Diagnostics.Trace events alongside with system events, so I next time I am on assignment I’d probably use Procmon :).

Conclusion and Recommendations

The techniques I have outlined in this post does not require heavy weight coding and do not affect performance itself significantly. These techniques also use readily available tools for collecting and parsing the results.

Related Books