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 (7)
  1. You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

  2. I figured out how to fix this in PhotoRoom

    Between 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));  //FromConfig

    context.Response.Cache.SetMaxAge(999);  //FromConfig

    context.Response.Cache.SetSlidingExpiration(true);

    context.Response.Cache.SetValidUntilExpires(true);

    context.Response.Cache.VaryByParams["*"] = true;

    Chris

  3. Alik Levin says:

    Chris!

    That is pure gold nugget.

    Thanks for sharing.

    alikl

  4. foo says:

    Correct me if I am wrong but isn’t this also a security issue if someone was to put "../../secretImageFolder/foo.jpg" as the request.querystring[‘fn’] param?

  5. Alik Levin says:

    you are absolutely right.

  6. 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

  7. Alik Levin's says:

    &#160; &#160;&#160;&#160; This post is a quick overview of free performance tools available from Microsoft,

Comments are closed.

Skip to main content