Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Image Generator - Slow Performance

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();
}
like image 540
Alkie Avatar asked Oct 07 '22 07:10

Alkie


2 Answers

There are some things that I will change:

  • Surrond the streams with the use of the keyword using.
  • Use an ashx handler instead. Seems like you are using an aspx file. For this kind of scenarios is better to use an http handler, since it has a smaller life cycle. I have used this a lot of times to serve thumbnails of images.
  • Use some caching. Maybe you can take advantage of asp.net cache features, you can find out if there are repeated values for t, so you store the resulting image on the cache and avoid the writing and creation of some steams everytime
  • Last but not least, try check if the server has the latest sp and updates. There are some cases that the app will behave strange if there are certain updates missings,

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.

like image 189
zaiboot Avatar answered Oct 13 '22 12:10

zaiboot


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; }
   }
}
like image 38
slfan Avatar answered Oct 13 '22 12:10

slfan