ASP.NET Performance Sin - Serving Images Dynamically (Or Another Reason To Love Fiddler)
Serving images dynamically may cause performance hit. Dynamically served images require more HTTP requests which violates Steve Souders' performance rule #1 - Make Fewer HTTP Requests. The latency is also caused by parallelism (or parallel downloading) limitations as described in detail here Performance Research, Part 4: Maximizing Parallel Downloads in the Carpool Lane
Static Images
Below are the series of images that served dynamically and static.
Static images displayed using GridView's ImageFiled column type. ImageField generates the following HTML mark-up:
<img src="IMAGES/Birds/icon-penguin.gif" style="border-width:0px;" />
Browser interprets it as a static image and is ready to cache it for further reuse.
Serving Images Dynamically
Below is the sample code that implements dynamic image serving. I witness in the field different variation but the pattern (I'd call it anti-pattern) remains the same. ASP.NET and HTML mark-up that is usually part of repeater control looks similar to the following:
<img src="ServeImage.ashx?FN = <%#DataBinder.GetPropertyValue(Container.DataItem, "Image")%>" />
ASHX file's code that actually serves the image looks similar to this:
public void ProcessRequest(HttpContext context)
{
string imageFileName = context.Request.MapPath(@"IMAGES\" + context.Request.QueryString["FN"]);
context.Response.ContentType = "image/jpeg";
context.Response.WriteFile(imageFileName);
context.Response.Flush();
context.Response.Close();
}
Network Analysis
Using one of my most favorite tools - Fiddler - it is easy to reveal browser's view on the traffic:
There is expiration attribute attached to static images while dynamically served images do not have such attribute.
Subsequent call the the same page that gets the same images reveals the following:
All dynamically served images are not cached and utilize the network on each request.
Further investigation shows, using Fiddler's P and C fantastic feature, that overall network utilization caused by these dynamically served images is about 350 KB, which could be saved by caching the images.
Recommendations
Avoid serving images dynamically. Follow best practices outlined at Exceptional Performance:
- Make Fewer HTTP Requests
- Reduce DNS Lookups
- Avoid Redirects
- Make Ajax Cacheable
- Post-load Components
- Preload Components
- Reduce the Number of DOM Elements
- Split Components Across Domains
- Minimize the Number of iframes
- No 404s
My relative posts
- Performance Sin - Chatty Database Access And Loops (Plus Another Free Performance Tool)
- Performance Sin - Using Exceptions To Control Flow
Comments
- Anonymous
May 02, 2008
You've been kicked (a good thing) - Trackback from DotNetKicks.com - Anonymous
May 02, 2008
I figured out how to fix this in PhotoRoomBetween your ContentType and WriteFile add://Caching - Set the caching headers for this image.context.Response.AddFileDependency(imageFileName );context.Response.Cache.SetETagFromFileDependencies();context.Response.Cache.SetLastModifiedFromFileDependencies();context.Response.Cache.SetCacheability(HttpCacheability.Public);context.Response.Cache.SetExpires(DateTime.Now.AddTicks(600)); //FromConfigcontext.Response.Cache.SetMaxAge(999); //FromConfigcontext.Response.Cache.SetSlidingExpiration(true);context.Response.Cache.SetValidUntilExpires(true);context.Response.Cache.VaryByParams["*"] = true;Chris - Anonymous
May 02, 2008
Chris!That is pure gold nugget.Thanks for sharing.alikl - Anonymous
June 01, 2008
The comment has been removed - Anonymous
June 01, 2008
you are absolutely right. - Anonymous
June 07, 2008
Serving images dynamically may cause performance hit. Dynamically served images require more HTTP requests which violates Steve Souders' performance rule #1 - Make Fewer HTTP Requests . The latency is also caused by parallelism (or parallel downloading - Anonymous
June 10, 2009
      This post is a quick overview of free performance tools available from Microsoft,