I've recently been working on an aspx dynamic image generator in C# that, at its most basic, takes a querystring value from "t" and writes that string to an image, and then returns a JPG.
It worked flawlessly locally, and on a test server - the images were returned instantly.
But when on load-balanced live servers, sometimes it works fine. But more than often it times out / takes up to a minute to return the image.
I thought I'd ask here if there's anything obvious in my code that would be causing issues, before I turn to the server operators to ask why this isn't working well.
Below is a very streamlined version of the generator (which also has the exact same timeout issues)
protected void Page_Load(object sender, EventArgs e)
{
// Set global stage dimensions
const int stageWidth = 500;
const int stageHeight = 200;
// Create Bitmap placeholder for new image
Bitmap createdImage = new Bitmap(stageWidth, stageHeight);
// Draw new blank image
Graphics imageCanvas = Graphics.FromImage(createdImage);
// Add text
if (!string.IsNullOrEmpty(Request.QueryString["t"]))
{
string imageText = Uri.UnescapeDataString(Request.QueryString["t"]).Trim();
Font font = new Font("Arial", 22);
imageCanvas.DrawString(imageText, font, Brushes.White, 0, 0);
}
// Save
MemoryStream memStream = new MemoryStream();
createdImage.Save(memStream, ImageFormat.Jpeg);
imageCanvas.Dispose();
createdImage.Dispose();
// Set filename / image format
Response.AppendHeader("content-disposition", "filename=MyImage");
Response.ContentType = "image/jpeg";
// Send output to client
memStream.WriteTo(Response.OutputStream);
memStream.Dispose();
Response.Flush();
}
There are some things that I will change:
using
.Also it could be associated to the web farm itself. You can review the performance counters of the server to review if there is some anomaly reported.
Hope it helps.
You could save some memory and possibly gain performance by saving directly into the output stream instead of using a memory stream:
createdImage.Save(Response.OutputStream, ImageFormat.Jpeg);
Another issue could be that your code is in the .aspx page. It might be recompiled too often. I would suggest an http-handler:
public class MyHttpHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// prepare image like you did
memStream.WriteTo(context.Response.OutputStream);
}
// Override the IsReusable property.
public bool IsReusable
{
get { return true; }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With