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.

image

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:

image

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:

image

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:

My relative posts

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
    &#160; &#160;&#160;&#160; This post is a quick overview of free performance tools available from Microsoft,