Caching image handler output strategies - asp.net

Firstly I appreciate that this question could be seen as subjective but I strongly believe that there should be and probably is a definitive answer to my question.
At work we are currently implementing a strategy for dynamically resizing and serving images using a generic handler and the question of caching has become something of a contentious issue.
In my original implementation the resized image is cached in memory with a cache dependency based on the original image.
e.g
using (MemoryStream ms = new MemoryStream())
{
imageEditor.Image.Save(ms, imageFormat);
// Add the file to the cache.
context.Cache.Insert(key,
ms.ToArray(),
new System.Web.Caching.CacheDependency(path)
);
imageEditor.Dispose();
// Set the context headers and serve.
SetHeaders(ms.GetHashCode(), context, responseType);
context.Response.BinaryWrite(ms.ToArray());
}
This has it's downsides though.
Every time the Application Pool Worker Process is recycled (every 1740 minutes by default) we'll lose anything that is in the cache.
If there are a lot of images we could be in danger of overloading the system memory and causing an out of memory exception. (Does IIS prevent this by recycling the App pool if the usage hits a certain level?)
One of my colleagues has suggested that we implement a file caching system instead that saves the resized file and instead serves that file on subsequent requests which should (I don't know the intricacies of operating system IO caching memory management) reduce memory usage. Whilst this would allow us to persist the resized image across recycles I see a few major problems with that approach:
We cannot track the original file any more so if someone uploads a
new image of the same name our resized images will be incorrect.
The fileserver becomes polluted over time with thousands of images
Reading a file is slow compared to reading from memory. Especially if you are reading multiple files.
What would be the best overall approach? Is there a standard defined somewhere by Microsoft? The sites we build are generally very busy so we'd really like to get this right and to the best possible standard.

We have a similar system on my website. Regarding your objections to the file caching system:
1,2) On my site I have a single class through which all file saving/loading passes. You could implement something similar, that clears all the cached,resized images whenever a user uploads a new image. If you name the files in a predictable manner this isn't hard to do. If storage space is a concern for you, you could implement something to remove all cached images with a last access date that is too old.
3) This depends on how your sites work. My site has a vast number of images, so it isn't feasible to store them all in memory. If your site has fewer images, it might be the better solution.

This is not a complete answer to your question but, you shouldn't be able to cause a system of out memory exception by putting to much stuff into the cache. If system memory should start running low the application cache will automatically start removing the unimportant and seldom used items in order to avoid causing any memory issues.

You may use ASP.NET Generated Image. Interesting article by Scott Hanselman - ASP.NET Futures - Generating Dynamic Images with HttpHandlers gets Easier.

Related

ASP.NET: are aspx/ascx files accessed from disk on every request?

I googled forever, and I couldn't find an answer to this; the answer is either obvious (and I need more training) or it's buried deep in documentation (or not documented). Somebody must know this.
I've been arguing with somebody who insisted on caching some static files on an ASP.NET site, where I thought it's not necessary for a simple fact that all other files that produce dynamic HTML are not cached (by default; let's ignore output caching for now; let's also ignore the caching mechanism that person had in mind [in-memory or out on network]). In other words, why cache some xml file (regardless on how frequently it's accessed) when all aspx files are read from disk on every request that map to them? If I'm right, by caching such static files very little would be gained (less disk-read operations), but more memory would be spent (if cached in memory) or more network operations would be caused (if cached on external machine). Does somebody know what in fact happens when an aspx file is [normally] requested? Thank you.
If I'm not mistaken ASPX files are compiled at run-time, on first access. After the page is compiled into an in-memory instance of a Page class, requests to the same resource (ASPX page) are serviced against the object in memory. So in essence, they are cached with respect to disk-access.
Obviously the dynamic content is generated for every request, unless otherwise cached using output caching mechanisms.
Regarding memory consumption vs disk access time, I have to say that from the performance stand point it makes sense to store objects in memory rather than reading them from disk every time if they are used often. Disk access is 2 orders of magnitude slower than access in RAM. Although inappropriate caching strategies could push frequently used objects out of memory to make room for seldom used objects which could hurt performance for obvious reasons. That being said, caching is really important for a high-performance website or web application.
As an update, consider this:
Typical DRAM access times are between 50 - 200 nano-seconds
Average disk-access times are in the range of 10 - 20 milliseconds
That means that without caching a hit against disk will be ~200 times slower than accessing RAM. Of course, the operating system, the hard-drive and possible other components in between may do some caching of their own so the slow-down may only occur on first hit if you only have a couple such files you're reading from.
Finally, the only way to be certain is to do some benchmarking. Stress-test both implementations and choose the version that works best in your case!
IIS does a large amount of caching, so directly, no. But, IIS checks for ANY changes in the web directory and reloads any changed files as they get changed. Sometimes IIS gets borked and you have to restart it to detect changes, but usually it works pretty good.
P.S. The caching mechanisms may flush data frequently based on server usage, but the caching works for all files in the web directory. Any detected changes to source code causes IIS to flush the web applicaiton and re-compile/re-load as well.
I believe that the answer to your question depends on both the version of IIS you're using, and configuration settings.
But I believe that it's possible to configure some combinations of IIS/.Net to avoid checking the files - there's an option to pre-compile sites, so no code actually needs to be deployed to the web server.

Can you solve my odd Sharepoint CSS cache / customising problem?

I have a weird situation with my sharepoint css.
It is deployed as part of a .wsp solution and up until now everything has been fine.
The farm it deploys too has a couple of webfront ends and a single apps server and SQL box.
The symptom is that if I deploy the solution, then use a webbrowser to view the page it has no styles, and if I access the .css directly I see the first 100 or so bytes of the .css.
However if I go into sharepoint designer and look at the file it is looks fine, and if I check it out and publish it (customising the file but not actually changing anything in it) then the website works fine and the css downloads completely.
There is some fairly complex caching on the servers Disk based and object caches. as far as I can tell I have cleared these (and an issreset should clear them anyway... shouldn't it?)
I have used this tool to clear the blobcache from the whole farm http://blobcachefarmflush.codeplex.com/
The problem you're describing is one I've encountered before. Let me share what I know, what I suspect, and how I'd go about troubleshooting your scenario.
First off, it sounds like you suspect caching as a potential problem source. In the case of the MOSS publishing feature set, you really have three different cache mechanisms in operation: the object cache, the BLOB cache, and the page output cache. The only mechanism that should be in-play, assuming it's turned on with default settings, is the BLOB cache. Neither the object cache nor the page output cache should be touching stand-alone stylesheets like you have.
You've tried flushing the cache the flush using the farm-level BLOB cache flush feature, and that will instruct MOSS to dump all BLOB cache data. You can verify this by reviewing the file system to ensure that only the three .bin folders remain following a flush.
To your specific question regarding an IISRESET: no, and IISRESET actually won't clear the BLOB cache. The contents of the BLOB cache persist beyond the life of the application pool servicing the web application. You either need to use a feature to clear out the cache (as you have been), or perform a manual file delete. I don't recommend the latter unless you absolutely have no other course of action. If you do elect to go the manual route to try it, ensure that you shutdown the W3SVC service before deleting files out of the file system. If you don't, the actual file deletion process can get into a race condition with cache repopulation and lead to corruption. After you've deleted files with a stopped W3SVC, you can start the W3SVC back up again.
For more information on the internals of the BLOB cache and how it operates, I'll point you to a blog article of mine: http://sharepointinterface.com/2009/06/18/we-drift-deeper-into-the-sound-as-the-flush-comes/
To see if the BLOB cache is a factor in the behavior you're seeing, you can modify the web.config for your web application(s) and adjust the file pattern to remove CSS from the list of file types in the <BlobCache> element and then restart IIS (or at least recycle the app pool).
Another possibility, based on experience, is that you're seeing something other than BLOB cache abnormalities. The key observation for me comes in the form of you observing that a direct request for the CSS stylesheet returns only the first 100 bytes or so.
Do you, by any chance, have any intelligent network hardware (that is, intrusion detection hardware or anything that might be performing application/layer-7 filtering) between the WFE and you, the caller? Intrusion detection and IPS systems are the source of many of the types of problems you're seeing, and they're one of my first stops whenever I see "oddball" behavior like you're describing. In the case of one of my clients, I saw a problem meeting your description (CSS and JS files getting truncated) due to an intervening Juniper firewall with active IPS. Turning off IPS (to test) cleared things up immediately. After that, the networking team sought an update from Juniper to correct the issue to ensure that IPS could remain active.
Try turning off BLOB caching (or removing the CSS extension from the file pattern) to see if that makes a difference. If not, talk to your network team to see if something is happening to the response stream coming back to you. That's where I'd start; hopefully, one of those two things will do the trick for you.
Small side note: if you have a free moment and are up to it, I'd like to hear about your experience with the BlobCacheFarmFlush solution you pulled down from CodePlex. I authored it, and I'd love to hear your thoughts -- good or bad :-)
Sean (sean#sharepointinterface.com)

Can I use the ASP.NET 'OutputCache' control to cache images without a performance hit?

I have some ASP.NET MVC actions that generate images dynamically (although it could equally be an ASPX page).
I'm using [OutputCache] to cache these images. I'm just wondering if I need to worry about ASP.NET caching images in memory and taking up too many resources. These are product images of varying sizes for a shopping cart containing only a couple dozen products.
Will OutputCache use disk or just in memory? How intelligent is it? Or should I just save the images to disk myself and implement my own caching system (which is actually the current implementation) ?
For all intents and purposes, I believe that the output cache is completely in-memory - meaning that if the app pool is recycled, the image will need to be generated again.
I've had to do something similar in the past, and I actually implemented a two-tiered system that used the HTTP cache primarily, and used the filesystem as a fallback. If something didn't exist, I generated the image and saved it to disk AND put it in the cache. That way if it gets pushed out of the cache or the app pool recycles, I only have to load it off the disk (it appears you've done the same).
As far as "too much memory", if you explicitly use HttpContext.Cache instead of [OutputCache], you can control the priority of the item in the cache. You can then tweak the settings on your app pool to control how much memory it uses overall, but I'm not sure there's a whole lot to be done other than that. A couple images * 12 products doesn't seem like it would take up a whole lot of memory to me though.
Without knowing anything else about your application, it sounds to me like you could get away with just using the outputcache. However, if you need something more robust and scalable, I'd use the two-tiered system I described. Though, if you've already got that implemented and working, "if it ain't broke..."

Caching strategy, Output Cache vs Data Cache or both?

I'm working on an ASP.NET MVC project and I've come to the point where I want to start considering my caching strategy. I've tried to leave my framework as open as possible for the use in caching.
From what I heard during Scott Hanselman's podcast StackOverflow.com uses page output caching and zips that content and puts it into RAM. This sounds like this would be great for user-wide cache but for something like personalized pages you would have to cache a version for each user and that could get out of control very quickly.
So, for a caching strategy. Which should be used, Output Caching, Data Caching or combined? My first thoughts are both but as far as cache dependencies it sounds like it could get a bit complex.
We're doing API and Output caching on a large scale (3 milion visits a day) web site (news portal). The site is primarily used by anonymous users, but we do have authenticated users and we cache a complete site just for them, due to some personalized parts of the site, and I must admit that we had absolutely no problems with memory pressure.
So, my advice would be cache everything you can in API cache so your Output cache rebuilding is even faster.
Of course, pay close attention to your cache ratio values in the performance counters. You should see numbers >95% of cached hits.
Another thing to pay attention is cache invalidation, this is a big issue if you have a lot of related content. For example, you cache music stuff and information about one album or song might be displayed and cached on few hundred pages. If anything changes in that song, you have to invalidate all of these pages which can be problematic.
Bottom line, caching is one of the best features of ASP.NET, it's done superbly and you can rely on it.
Be careful about over-aggressive caching. Although caching is a tool for helping performance, when used incorrectly, it can actually make performance worse.
I can't answer whether output caching or data caching would work for you better without knowing more details about your project.
I can help provide a couple examples of when to use one over another.
If you have a specific data set which you would use often in many different views, you'd be better off using data caching. You'd use this if your data fetch operation was very common and expensive relative to your data rendering. If you had multiple views which used the same data, you would save your data fetching time.
If you had a view which used a very specific data set and the rendering of the view was complicated and this view was requested very often (for example, stack overflow's home page), then you would benefit a lot from output caching.
So in the end, it really depends on your needs and be careful about using caching incorrectly.

General tips and techniques for minimizing the size of Flex applications

I really like the Flex framework, however I routinely deal with SWF files that are ~ 500KB.
I don't know at what point a file considered to be "too big" to be served on the internet, but I would assume that a 500KB download just to use a web application would certainly annoy some users.
Are there any tips or techniques on reducing the size of compiled SWFS?
As a side note, the 500KB SWF file really isn't that big of application...
This might help you:
http://www.onflex.org/ted/2008/01/flex-3-framework-caching.php
Chances are the user has already encountered the packaged framework before, so it would be cached. At the very least they won't have to load it from your site again.
This answer is a little more general than you're probably looking for (it applies to all web apps, whether Flash/Flex-based or HTML/CSS/JS based or whatever), but...
It depends a lot on the use case for your application. Is it an application that will be loaded all day and pull in updates as necessary (like Gmail) or is it something that will be launched, used, then closed?
If the former, besides reducing resource size, you are probably alright here. It makes more sense to get the downloading all out of the way at once, rather than to expect the user to tolerate delays at every turn.
If the latter, you should lazy-load as much as possible. In other words, for example, instead of embedding all of the application's graphics into the SWF, load them with URLRequests or whatever method necessary when they are needed. A quicker launch will "feel" faster and more than make up for the increased HTTP requests over a short time.
I can think of two things to try.
First don't EMBED images, fonts, and other SWF files. This will cause them to be loaded at runtime instead, so this could affect performance when the page loads, but the SWF will be smaller.
Also try splitting the application into several Modules. I know this improves the performance of the initial load time, but I don't know if it reduces the size of the top-level SWF.

Resources