Welcome to AspAdvice Sign in | Join | Help

Real World Application Performance Tuning Example

Many of you know that I’m very much into high performance and scalability techniques.  One thing you need to remember when applying performance tweaks is that as your application changes, your performance optimizations may need to change and evolve with it.  Let me demonstrate this with a case in point.

On ASPAlliance.com, a fairly busy web site with about a thousand articles and tutorials on software development, each article displays its total views and its views in the last 10 days.  Now, perhaps the ideal design for this data, from a performance standpoint, would be to schedule a job to calculate these fields and store them in the database in the Article table, and then fetch them as simple data elements when the rest of the article data is fetched.  However, as this is a real-world application with some legacy baggage, the Views data was actually hacked into the display page with the requirement that the underlying Article table and object not be updated.  Not ideal, but a perfect example of a real world reality.

Now, in order to optimize the site to limit total database hits and ensure that the each Article page being shown caused the least possible load on the database, caching was used.  However, with hundreds of articles, it was clear that rather than caching every individual article’s total views, it would be far more efficient to fetch back a resultset holding all articles with their views, and then to simply use ADO.NET logic to fetch the particular row from the DataTable (from the Cache) for the article ID in question.

This did in fact work splendidly for several years.  Then, last week, the GetTotalViews method started to time out.  At first it was only once or twice a day, but by the weekend it was happening several times per hour (basically every time the cache expired).  The problem was that fetching the entire result set for all articles was taking too long, since the total number of articles had grown as had the total number of Views being counted.  It didn’t help that the web application is running on 3 servers in a (shared) cluster, so when the app would start up, typically all three would be requesting the result set at the same time.

The ideal solution, again, would be to aggregate the data using a scheduled job and store the aggregate results in the Article table.  However, in the interests of time, another band-aid was applied.  In this case, I chose to fall back to the somewhat less efficient approach of having every article grab just its own total views from the database, and caching each article’s total views individually.  Since implementing this fix, no timeouts have occurred.  Refactoring the application to use the proper technique will remain on the TODO list, however…

Published Monday, January 15, 2007 1:30 PM by ssmith
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Real World Application Performance Tuning Example

I've read your blog with great interest being myself tackling with similar perf/scalability problems. Thank you for several great insights I've got.

However, in this case I didn't quite get it. Are you saying that you held BOTH the articles AND their view count in the cache AND that it was updating that cache that took too long?

More interestingly, your saying "However, with hundreds of articles, it was clear that rather than caching every individual article’s total views, it would be far more efficient to fetch back a resultset holding all articles with their views [..clip..]" I'm not getting it, what's the problem here? How does this differ from the implementation you did later?

Thanks.

Tuesday, September 04, 2007 8:30 AM by Sasha

# re: Real World Application Performance Tuning Example

The article contents were and are being cached, but that wasn't the issue in this case.  The issue described here was that the view counts of the articles were being fetched with a single database query for the whole server (all articles) and then that result set was cached.  This was very efficient in that it only needed to hit the database one time per web server every N minutes (where N is the cache duration).  Unfortunately, as the site grew, the amount of time required to retrieve this data grew to the point where it was timing out (taking more than 15 seconds), and the timeouts were causing frequent problems with the site.  So instead, I still cache the view counts for N seconds, but instead of one giant collection of results, I have a lot of little results (one per article) and the query to fetch any single article's results is very fast.  A lot more chatter to the database, but no single query is so big that it times out.

Tuesday, September 04, 2007 11:48 AM by ssmith

# re: Real World Application Performance Tuning Example

Ok, now I got it. Thanks.

Keep on good work, I'm more than interested in these "real world perf tuning" examples -- and I believe I'm not the only one.

Such examples tend to be rare, though most likely there is a vast number of people tackling with problems like these.

Wednesday, September 05, 2007 3:51 AM by Sasha

Leave a Comment

(required) 
required 
(required) 
Enter the code you see below