Clarity, Technology, and Solving Problems | PracticeThis.com
WP7 App with Key Windows Azure resources – Slides, Videos, How-To’s, and T-shooting – for quick consumption on the go.
LinkedIn
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
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.
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")%>" />
<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(); }
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(); }
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.
Avoid serving images dynamically. Follow best practices outlined at Exceptional Performance:
You've been kicked (a good thing) - Trackback from DotNetKicks.com
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
Chris!
That is pure gold nugget.
Thanks for sharing.
alikl
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?
you are absolutely right.
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
      This post is a quick overview of free performance tools available from Microsoft,