< Browse > Home / Software Development / Blog article: Increasing Performance in Dot Net Web Applications by Caching Relatively Static Data.

| RSS

Increasing Performance in Dot Net Web Applications by Caching Relatively Static Data.

September 2nd, 2008 | No Comments | Posted in Software Development

Increasing performance in dot net web applications by caching static data.

Least effort maximum return method for increasing the performance of dot net web applications. Benefits of data caching and how to best implement data caching. Read more

All but the most trivial of web applications store their data within database tables. This data can generally be segmented into two broad categories:

1) Transactional data

2) Control data

To illustrate further lets take the example of a discussion forum which contains 100,000 forum posts.

Transactional Data.

Each post in itself is most likely stored in a separate table for forum posts. There is not much that can be done here. When a post is to be displayed no matter how we look at it this data record has to be retrieved from the database each time.

Control data.

Now consider the data structures such as the list of forums, the website menu structure etc… These data records need to be retrieved for each and every page that is displayed. However consider the fact that this data relatively few records and hardly ever changes.

What happens when requesting data from a database.

Each and every data fetch no matter how small incurs a latency of 15 to 20 milliseconds. This is caused by the fact that the data request has to be processed through many underlying layers within the data access stack before the data is available. A simplified view of these layers would be as follows:
1) Processing by objects within the dot net framework system.data namespace (eg dataset, connection)
2) Passing the request to the low level database driver
3) Serializing the request via tcp streams or named pipes to the database server itself
4) Processing of the sql syntaxt and retrieval of data by the database server
5) De-serializing the response via tcp streams or named pipes by the low level database driver
6) Returning the response to the dot net framework system.data namespace.

As you can see although fetching one record from the database might seem like a trivial task there is significant processing going on in the background.

The performance hit caused by database requests

Although IIS (and any other web server) provides multi-threaded execution of web applications this is for processing multiple web requests in parallel. A single web request from a web browser will be processed by a single web server thread. In this context if a web application 25 database request for a given web page this effectively guarantees an overhead of 375 to 500 milliseconds simply waiting for data. To further emphasize this point consider that the application code itself for most web application pages completes within less that 50 milliseconds.

While on a small site this may not be of any concern it adds up quite fast for large sites. If we look carefully at the life-cycle of any web application page we see that in general 40% to 70% of the data request are for control data. Control data which if could have been cached. In general retrieving cached data consumes such less time that it is not even measurable. Caching of control data means in general an average application page could processing in less than 150 milliseconds as opposed to 400 milliseconds. As you can see the performance gain is huge.

Caching control data

Naturally there are multiple ways of achieving this in Dot Net web applications.
1) App Domain caching
2) Caching via dedicated object caches such as those in the Microsoft Enterprise Library
3) Caching via static methods (Example implementation provided)

App Domain Caching:

IIS provides a fairly high performance caching mechanism. Take a look at the dot net framework help and MSDN references on System.Web.Caching examples and documentation of how to implement this.

Caching via dedicated caching libraries

Many flavors of these exist however is perhaps one of the easiest to implement
Further details can be found at the following two links
http://www.codeplex.com/entlib
http://msdn.microsoft.com/en-us/library/cc309502.aspx

Caching via static methods

Any static method defined within a dot net web application is global to the entire application. The only exception here is if a web farm or IIS process farm is used. In that instance the static method is global to all threads executing within a single IIS process (application pool process)

Thread synchronization locks shown are mandatory here because all threads across the entire application pool process will be sharing access to these static methods.

The following code snippet provides an example of how to implement this strategy with a reload performed every 5 minutes.

public class ForumName

{

// Example data object class for representing a top level forum

public ForumName(string ValName, string ValSummary)

{

m_Name = ValName;

m_Summary = ValSummary;

// And assign values for the rest of your database fields

}

private string m_Name;

public string Name { get { return m_Name; } }

private string m_Summary;

public string Summary { get { return m_Summary; } }

// And properties for the rest of your database fields

}

#region “property MyCachedMenu”

private static List m_MyCachedMenu;

private static bool m_MyCachedMenu_IsSet = false;

private static DateTime m_MyCachedMenu_LastLoaded = DateTime.MinValue;

private static object m_MyCachedMenu_SyncRoot = new object();

public static System.Collections.ObjectModel.ReadOnlyCollection MyCachedMenu

{

get

{

DateTime LastLoadTime;

if (!m_MyCachedMenu_IsSet)

{

m_MyCachedMenu = new List();

System.Threading.Monitor.Enter(m_MyCachedMenu_SyncRoot);

try

{

if (!m_MyCachedMenu_IsSet)

{

LoadMenuFromDatabase();

}

}

finally

{

System.Threading.Monitor.Exit(m_MyCachedMenu_SyncRoot);

}

m_MyCachedMenu_IsSet = true;

}

else

{

System.Threading.Monitor.Enter(m_MyCachedMenu_SyncRoot);

try

{

LastLoadTime = m_MyCachedMenu_LastLoaded;

}

finally

{

System.Threading.Monitor.Exit(m_MyCachedMenu_SyncRoot);

}

if (((TimeSpan)DateTime.Now.Subtract(LastLoadTime)).TotalMinutes > 5) // This means reload every 5 minutes

{

System.Threading.Monitor.Enter(m_MyCachedMenu_SyncRoot);

try

{

LoadMenuFromDatabase();

}

finally

{

System.Threading.Monitor.Exit(m_MyCachedMenu_SyncRoot);

}

}

}

return m_MyCachedMenu.AsReadOnly();

}

}

private static void LoadMenuFromDatabase()

{

m_MyCachedMenu_LastLoaded = DateTime.Now;

m_MyCachedMenu.Clear();

// Request data from database here

// For each of the databse records create a new data object and load it into m_MyCachedMenu

}

#endregion

Good luck with your application and remember with web applications whenever and wherever possible cache your read only data.

Leave a Reply 12218 views, 1 so far today |

Comments are closed.