2012-07-05 10 views
5

Recientemente he estado trabajando en un generador de imágenes dinámicas aspx en C# que, en su forma más básica, toma un valor de la cadena de consulta de "t" y escribe esa cadena en una imagen, y luego devuelve un JPG.C# Image Generator - Rendimiento lento

Funcionó impecablemente localmente, y en un servidor de prueba: las imágenes se devolvieron instantáneamente.

Pero en los servidores en tiempo real con carga equilibrada, a veces funciona bien. Pero más de las veces se agota el tiempo/toma hasta un minuto devolver la imagen.

Pensé que podría preguntar aquí si hay algo obvio en mi código que podría estar causando problemas, antes de recurrir a los operadores del servidor para preguntar por qué esto no funciona bien.

A continuación se muestra una versión muy simplificada del generador (que también tiene exactamente los mismos problemas de tiempo de espera)

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(); 
} 
+0

¿Está agotando el tiempo de espera en los servidores * debido a la carga pesada *? ¿El servidor es ligero? ¿Hizo hincapié en probar esto en su servidor local? –

+8

Además, envuelva todo lo que implemente 'IDisposable' en un bloque' using'. Si se lanza una excepción por alguna razón antes de llamar a '.Dispose()', se perderán recursos ... lo que sería especialmente malo en caso de carga. –

+2

No explica los tiempos de espera, pero usaría un HttpHandler simple para esto en lugar de usar una instancia de página, ya menos que esté haciendo algo inusual probablemente no necesite la llamada UnescapeDataString. – bmm6o

Respuesta

3

hay algunas cosas que voy a cambiar:

  • surrond los arroyos con el uso de la palabra clave using.
  • Use un controlador de ashx en su lugar. Parece que estás usando un archivo aspx. Para este tipo de escenarios, es mejor utilizar un controlador http, ya que tiene un ciclo de vida más pequeño. Lo he usado muchas veces para servir miniaturas de imágenes.
  • Usa algo de almacenamiento en caché. Tal vez pueda aprovechar las características de caché de asp.net, puede averiguar si hay valores repetidos para t, de modo que almacena la imagen resultante en el caché y evita la escritura y la creación de algunos vapores cada vez
  • Último pero no menos importante , intente comprobar si el servidor tiene las últimas actualizaciones y sp. Hay algunos casos en que la aplicación se comportará de manera extraña si hay ciertas actualizaciones perdidas,

También podría estar asociada a la propia granja de servidores web. Puede revisar los contadores de rendimiento del servidor para revisar si se informa alguna anomalía.

Espero que ayude.

1

usted podría ahorrar algo de memoria y, posiblemente, ganancia de rendimiento mediante el ahorro directamente en la corriente de salida en lugar de utilizar una secuencia de memoria:

createdImage.Save(Response.OutputStream, ImageFormat.Jpeg); 

Otro problema podría ser que su código está en la página .aspx. Puede ser recompilado con demasiada frecuencia. Sugeriría un manejador http:

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; } 
    } 
}