views:

630

answers:

3

Hi,

I use an HttpHandler to dynamically serve images in a ASP.Net web application. I am having a performance issue (Firfox/Firebug/YSlow reports there are too many HttpRequests)

I have between 50-100 images per page in some instances.. 3 treeviews (business units/categories/objects) with each node having its own image ;)

Each item's image url is set dynamically like so...

SomeImage.ImageUrl = "/image.axd?ImageId={0}";

Note: I only know at runtime which images will be required.

Additional: Images are located on the server file system, in a resource file and also in the database - users can upload their own images to associate with my system objects and the ImageHandler will determine each image location dynamically)

In the web.config the httphandler is configured and works as expected... add verb="GET" path="image.axd" type="Vision.OnsightManager.ImageHandler"

In the HttpHandler the raw image bytes are returned in response to each image request. So in the WriteResponse() method of the image handler the image bytes are returned, like so...

context.Response.BinaryWrite(bytes);

All images display correctly, but the app has performance problems as expected where many images are displayed...

Question:

What approach do you recommend, apart from reducing image count ;), for minimizing all the HttpRequests generated for each image? Maybe combining into a single Http request?

I have read articles on combining multiple css requests into a single request, using image mapping (single combined image with offsets) etc, but none seem to suit my particular scenario?

Much obliged!

+2  A: 

This doesn’t sound like a great way to handle images. In the first instance you should save your server some pain by putting the images as real images on the server rather than getting them via an ASP page.

Then you set the content expiry to some stage in the future. This will at least make subsequent requests simpler.

I would also try and rationalise the images a bit. Even if you have three tree views you can probably find many common elements.

Finally, though it would take some work to implement, you could combine the images server side so you are only returning one image for a tree, I would make sure you cache the result somewhere if you do this as it will put load on the server while it generates.

Jeremy French
+1  A: 

You could try increasing the number of worker threads in your asp.net config file.

More info can be found here:
http://williablog.net/williablog/post/2008/12/02/Increase-ASPNET-Scalability-Instantly.aspx http://msdn.microsoft.com/en-us/library/ms187024.aspx

I will also add that the HTTP standard restricts the number of simultanious connections to a single server to just 2 connections per client. IE certainly enforces this restriction, but Firefox I beleive limits itself to 4. These restrictions are client configurable I'm afraid (you can't change them from the server side).

Ady
+2  A: 

One way to reduce the preasure on the server on repeated requests is to use the page cacheability.

Add this before Response.Write in the HttpHandler:

// Set for how long you want the image to be cached.
context.Response.Cache.SetExpires(DateTime.Now.AddDays(1)); 
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetValidUntilExpires(true);
context.Response.Cache.VaryByParams["ImageId"] = true;

This will make the server to cache the result (depending on the ImageId param) but this will of course only help on repeated requests for the same image, not the first one, so it depends on where the actually problem is.

Without knowing very much about your application it sounds like you have to change several things to find a better solution...

bang
Wow. Thanks for all the great responses. Is there any way to also cater for the first request? The client cache approach only kicks in after the initial request which will be slow pre-client cache is utilized?
Konrad