Last night, one of my clients assigned me a problem that I thought was going to require one solution, and in the end it was just poor programming. But the process reminded me of the need for good debugging skills. Just how do you know where the performance problem is?
Too many programmers I know approach performance issues from the front end. “I know there is going to be a performance problem if I do it this way, so I’m going to do it that way instead.”
But unless your theory was correct, you are very likely to spend extra time doing something you may not need to do. While solving problems is what makes programming fun for a lot of us, solving problems that don’t exist is a waste of time for the organizations we work for.
My motto is:
- Get the app working
- Get the app working right
- Get the app working fast
By following these steps, in this order, I very rarely even need to address step three.
So, what happens when there is a performance problem? How do you track it down?
Well, hopefully, you are addressing a visible performance problem. Something is taking more than a second to run. There are cases where you need to address performance problems that are less than a second and/or can’t really be measured with a stop watch. But the biggest hits are the easiest to solve. So all you need to do is set some break points in your app and count how long it takes to get from one to the other. This is where a good layered architecture helps a lot. Very rarely is the performance issue in the display code. So you can set a break point in the code that gets the data out of the database.
When I did this this morning, I found that there was a foreach loop in the BLL that was retrieving data that could just as easily be placed in the store procedure that we were calling right above the foreach loop.
That seemed to solve the problem until we put the code on stage. And, this is where the fun began. While the code was definitely faster, it was still too slow. What was perplexing was that the data seemed to be the same in our test database as it was on staging. Worse, we no longer had access to our debugger. So, how do you track a problem like this down?
This is where the tracing feature of .NET is of great value.
If you’ve never used this feature, you can read some other articles about it elsewhere (I’ll place links at the end) but for our purposes, we want to set up tracing a specific way.
- Place the following line in web.config
<trace enabled="true" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="false" />
This will enable tracing for your application but will not display the tracing information at the bottom of the page. Set localOnly to true if you can access the information from localhost–otherwise, you’ll need to set it to false.
- Put tracing statements in your code that you are trying to get timing information for.
Now, here’s the part many people don’t know. While it is pretty simple to send trace statements out from the codebehind file using:
You can also access the Trace object and emit trace statements from your BLL and DAL code using:
To access the trace output, run http://domaainstuff/applicationdirectory/trace.axd and select the round trip you want to examine.
Other places talking about ASP.NET Tracing:
Other places talking about ASP.NET performance:
Other post in ASP.NET
- ASP.NET GridView Edit All Rows At Once - October 30th, 2007
- Validating A WebForms Checkbox . . . - January 4th, 2008
- ListView and the DataPager - January 7th, 2008
- The case of the disappearing session variables - January 14th, 2008
- Storing a DataRow into a Session (server) variable - January 15th, 2008
- The point of a multi layer architecture - January 31st, 2008
- FormView Edit and Add - May 12th, 2008
- Virtual Files using HttpContext.RewritePath() - July 17th, 2008
- ASP.NET AJAX using JSON - Here's how. - August 4th, 2008
- SystemException: The trust relationship between the primary domain and the trusted domain failed - November 18th, 2008
- GridViews - Multiple Rows Per Record - December 17th, 2008
- Response.Redirect() executes too soon on the Server. - January 27th, 2009
- Tab Control ActiveTabIndex Lost on Postback - February 25th, 2009
- ASP.NET Application_Error Detecting 404's - March 2nd, 2009
- Infinite 302 Loop - How would you even know? - March 11th, 2009
- Unable to find connection...for object web.config - March 18th, 2009
- Dynamically Change class Attribute From ASP.NET - September 29th, 2009
- HttpContext.Items vs Session - October 12th, 2009
- Access a control by ID From Within a Databound Control - November 2nd, 2009
- GridView and Updating A Row Manually - November 4th, 2009
- Embedding Google Search Appliance Results in ASP.NET - November 5th, 2009
- ASP.NET Cross Domain Form Submission - November 11th, 2009
- ASP.NET Interview Questions For New College Graduates - November 12th, 2009
- ASP.NET Dynamic Validator - November 16th, 2009
- The Google Appliance and Forms Authentication - August 4th, 2010
- Prevent Postback on Buttons - October 11th, 2010
- Azure CDN Blob Storage Case Sensitive Issue - April 17th, 2012
- ASP.NET JSON and ViewState - September 25th, 2012
- Panel DefaultButton does not work - December 25th, 2012
- Why CSS ID selectors are Evil in ASP.NET Web Forms - February 26th, 2013
- Sorting the ListView in ASP.NET - March 5th, 2013
- Multi-Step Processing in ASP.NET - May 8th, 2013
- ASP.NET Web Design Software - May 15th, 2013
- Test Sending Email without a Server in ASP.NET - June 5th, 2013
- Tracking Down Performance Issues in ASP.NET - July 24th, 2013
- Unrecognized Tag Prefix or Device Filter ‘asp’ - July 31st, 2013
- WebServices – Error Handling - December 11th, 2013
- Converting a DataList to a ListView - December 25th, 2013
- What’s the Truth about Running ASP.NET WEBAPI Asynchronously? - November 15th, 2016