views:

200

answers:

2

Our website uses ASP.NET MVC for a part of the pages in it. These URLs typically have the form http://oursite/detail.mvc/12345/pictures/ In this URL, the 12345 is an ID in the database. We have several hundred thousands objects for which we show detail pages. Recently we noticed a rise in the memory use for the site, so I investigated a bit. We made a memory dump of the production site and found that a significant amount of the total memory use was cause by strings in Cache of the form "dmachine/webroot/1/site/detail.mvc/12345/pictures/" and "H:\site\detail.mvc\12345\pictures\".

Further investigation and heavy use of Reflector has showed that these strings are stored in the ASP.NET Cache in the form of a System.Web.CachedPathData object. This is created by ConfigurationManager when it reads information from the web.config file. It calls HttpContext.GetSection() --> HttpContext.GetConfigurationPathData() --> CachedPathData.GetVirtualPathData(). Eventually, in CachedPathData.GetConfigPathData, the virtual path is determined for the requested path and this is cached in the ASP.NET Cache without expiration.

Now the trouble is that we have millions of different URLs, and for each path the Configuration system stores a number of strings (configPath, virtual path, physical path) in cache. Over time, this information consumes several hundreds of MB, allmost all of the data in cache.

I assume that when memory gets scarce, these entries will be removed, but in operations they don't trust processes that grow and grow. It also seems very inefficient. Is there a way to tell the HttpContext not to cache this information for each unique URL? Or maybe we can map the request path to a simpler URL first and have that used to select the correct web.config?

+1  A: 

Well I thought it over (Teun and I work at the same company), and we have two options as far as I can tell:

  1. Do nothing. This article contains a comment from one asp.net team guy, and it shows a couple of ways to prevent the cache from growing and growing: http://forums.asp.net/p/985551/3297967.aspx#3297967, yet doesn't solve the problem of writing a cache entry for each possible route but guarantees that the cache won't throw some out of memory exception.

  2. Solve the problem with a workaround, use querystring parameters instead of fixed routes (/controller.mvc?action=X&params=Y instead of controller.mvc/action/params). This way only controller.mvc gets cached.

After all, I don't think this really is a problem.

Jan Jongboom
Option 2 seems rather lame, as it kills one of the nicest and most visible features of the ASP.NET mvc framework. In our case, it wouldn't matter as we have an ISAPI rewriting dll in place as well. But it still seems like a lame solution.
Teun D
A: 

Would caching just the data instead of the whole page? I guess it depends on the performance requirements and bottlenecks.

Usually most bottlenecks are in the database, and just using the http application cache to cache data helps a lot. You get a lot more control than caching just pages.

The problem might get easier to solve with .net 4.0 when you can write your own cache provider.

AndreasN
Point is, we are not doing any caching ourselves. It is ASP.NET itself. We just try to access config information in web.config. The ASP.NET implementation decides to cache the correct configuration path for each unique request path. This ends up using 98% of our Cache memory.
Teun D