Last post Oct 26, 2011 04:25 PM by desertfoxaz
Jun 20, 2011 04:20 PM|desertfoxaz|LINK
I'm inspecting some code another developer wrote some time ago. He created an asynchronous HttpHandler to retreive an image file. The "IsReusable" property is set to false. The handler inherits from a class that inherits from System.Web.UI.Page for reasons
only he knows and he doesn't work here anymore.
If I don't inherit from Page, how much of a performance boost will I get? Our users complain that the handler is too slow to retrieve images and I read recently that there's a lot of unnecessary overhead if you use a subclass of Page when there are no UI
Jun 21, 2011 05:11 AMemail@example.com|LINK
I've worked extensively with image handlers and httpmodules. (i'm the author of the http://imageresizing.net/ library)
While Page does slow things down significantly, the largest speed gains are probably to be found elsewhere.
Typically, http handlers do not implement non-modified support, properly use disk caching, or buffer data properly. And if the System.Drawing classes are used, there is a
series of pitfalls to avoid. Without proper memory management, buffering, caching, and full HTTP support, the requests will be very slow no matter whether you are using Page or IHttpHandler.
If you'd like me to look for problem points, e-mail the source code to me at firstname.lastname@example.org.
Jun 21, 2011 12:25 PM|desertfoxaz|LINK
There's a lot more going on behind the scenes here. The Handler calls a web service which then goes to the database and determines the location of the image, loads it, and sends it back as a byte array. Under some circumstances, the images are resized
to the dimensions they'll be displayed on the page. However, we've added some tracing and it seems that 95% of the time, retreiving an image takes 0.5 seconds. However, 5% of the time, it takes longer than 2 seconds (sometimes considerably longer). The
code is complex so there is no easy fix.
I'll read your article and see if I can get any ideas from it. Thanks
Jun 21, 2011 12:31 PMemail@example.com|LINK
.5 seconds is a long time... I consider .04 seconds long for most image sizes.
Is the image stored on the filesystem or in a byte array? Is the web service under your control?
Is the web service transmitting the binary image data?
Do you have any kind of caching system?
Jun 21, 2011 01:41 PM|desertfoxaz|LINK
The image is stored on the file system. A database lookup is performed to get the path. The web service is also under out control. This is an ASMX web service that returns the data as a byte array. No caching is used.
I figure if we switched the web service to use WCF we could do some optimizations but I don't know how to do that and I've been told by others that it isn't worth the effort, even though I don't know if I should believe that.
Jun 21, 2011 01:56 PMfirstname.lastname@example.org|LINK
Well, the fact that you're using a web service to tranmit binary data is probably the slowest part of the process. Encoding, decoding, ram usage, etc are probably killing you.
The web service should be communicating directly with the client if possible, eliminating the high latency, CPU, and RAM use. (when served directly from disk, IIS uses nearly no ram to process a request)
From a performance standpoint, the image URLs should point directly to the web service, and the web service should perform all processing. The results should be cached. Even better, the page should generate URLs that already include the filename, so only
1 SQL call will be made instead of one for each image.
I'm quite confident I could replace your imaging code with 3 pages of code using the imageresizing.net library (it supports SQL and disk caching).
The result would put far less load on both servers, and should bring your request down to under 50ms for most images.
I'm available on skype (nathanaeldjones) for the next half-hour if you want to talk.
Jun 21, 2011 02:03 PM|desertfoxaz|LINK
I'm pretty much booked all day with meetings, so I can't do much today. The path lookup is done once, as part of the rest of the data to be displayed on the page so I don't have any need to optimize that.
I'll try to find time to look at your stuff sometime this week.
Oct 26, 2011 04:25 PM|desertfoxaz|LINK
I had a couple of other posts regarding this issue. The actual resizing of the images is quite fast; I was able to determine this by using the System.Diagnostics.Stopwatch and doing some logging of execution times.
The problem was actually that the poorly-performing handlers were implementing IRequiresSessionState. When you use this interface the runtime will not allow multiple threads to access the same code, since writing to session needs to be thread safe. However,
I am only reading from session, not writing to it. If I switch to IReadOnlySessionState (which implements IRequiresSessionState), the performance increased dramatically as all four threads were able to execute in parallel.