2011-07-09 13 views
5

Tengo una aplicación que funciona con grandes cantidades de datos, y estoy pensando que, a veces, se lanzará el OutOfMemoryException (durante medio año, no tengo ninguna excepción, pero solo quiero saber todo al respecto). Como he investigado, después de esta excepción no puedo continuar con la ejecución de mi programa.Patrón de diseño para el bloque try/catch para OutOfMemoryException en .NET

¿Hay algún buen patrón para manejar tales excepciones, especialmente para trabajar con clases IDisposable?

+3

Diseñar una aplicación para manejar una OutOfMemoryException es probablemente lo último que debe hacer.No como en "no lo hagas", pero hay otras cosas que debes hacer antes de eso. La memoria nunca es un recurso infinito, y una aplicación bien diseñada siempre debe poder funcionar, siempre y cuando se hayan cumplido algunos criterios mínimos, pero si la aplicación puede usar mucha memoria para acelerar las cosas, debe diseñarse de esa manera, en lugar de estar diseñado como "requiere mucha memoria". ¿Estás seguro de que has hecho lo suficiente para evitar la OutOfMemoryException en primer lugar? –

+0

@Lasse V. Karlsen Nunca tuve tal excepción con mi proyecto, solo tengo curiosidad, ¿hay algún indicio de que debería saberlo? – VMAtm

+0

@VMAtm, ejecute una herramienta de generación de perfiles de memoria para asegurarse de no tener pérdidas de memoria. Es lo más importante para hacer. –

Respuesta

4

En un escenario OOM genuino (más probablemente en x86 que x64) estás bastante condenado allí. Casi cualquier cosa podría causar una asignación, por lo que su mejor opción es morir lo más rápido y elegantemente posible, haciendo un daño mínimo.

Dado que no está sucediendo, no insistir demasiado, pero evitar es mejor que manejar aquí:

  • utilizando la transmisión de datos API en lugar de amortiguar todo en la memoria
  • buffers de reutilización etc.
  • evite enormes matrices/listas/etc. (en verdad, la forma más probable de causar un OOM es solicitar una matriz enorme (pero única) - por ejemplo, una matriz irregular escalas mejor que una matriz 2D (incluso en x64 hay un límite estricto en el tamaño máximo de una única matriz)
  • pensar en cómo manejar datos escasos
  • ¿Lee muchas cadenas de fuentes externas? Si es así, considere en torno a un interner personalizado, de modo que usted no tiene 20.000 diferentes copias de cadenas comunes (nombres de países, por ejemplo)
  • mantener un ojo en lo que se libera cuando
  • evitar prolonga la vida accidentalmente en objetos, especialmente a través de suscripciones de eventos (notorios para las extensiones accidentales a tiempos de vida)
+0

Tengo muy poco conocimiento sobre el tema, pero su 1er párrafo parece contradecir las respuestas a [¿Es "Sin memoria" un error recuperable?] (Http://stackoverflow.com/questions/333736/is-out-of- memory-a-recuperable-error). Si me perdí algo, ¿podría aclarar, por favor? –

4

No hay un buen patrón, OOM es una desagradable excepción que puede atacar en cualquier momento. Lo que hace que casi sea una excepción asincrónica. La única ventaja que tiene para manejarlo es cuando su código está estructurado para asignar grandes cantidades de memoria al mismo tiempo. Por lo tanto, tendrá algunas probabilidades de retroceder y desenrollar el estado del programa como si no hubiera pasado nada.

Necesita diseñar su programa para que nunca necesite asignar más de la mitad de toda la memoria virtual disponible, un gigabyte en una máquina de 32 bits. Los dragones viven más allá de esa cantidad, su programa fallará en una asignación de 90 MB o menos, incluso si hay otros 500 MB de memoria virtual sin usar. Un problema inducido por la fragmentación del espacio de direcciones. Si cruza rutinariamente este umbral, entonces necesita cambiar a un sistema operativo de 64 bits.

+0

Me he topado con errores de falta de memoria con mucho menos de una actuación asignada. Sospecho que el objeto del Diccionario COM puede asignar pequeñas cosas al Gran Montón de Objetos, lo que resulta en una desagradable fragmentación masiva. Estoy desconcertado por el razonamiento detrás del manejo de LOH por parte de Microsoft, pero es lo que es. – supercat

+0

La fragmentación del espacio de direcciones siempre está a punto de arruinar su día. Nunca puede asignar más de ~ 550 MB, inmediatamente después de iniciar el programa. Eso va muy rápido cuesta abajo desde allí. COM no asigna desde LOH, usa su propio montón. –

+0

Hubiera esperado que lo hiciera, pero por algún motivo, al ejecutar una DLL COM desde mi aplicación, la memoria se descontrolaba al cambiar esa DLL para usar Dictionary en lugar de Collection; cuando el archivo DLL se ejecuta como su propio proceso, el Administrador de Tareas combina el uso de memoria de la aplicación DLL + y termina siendo aproximadamente un tercio del uso de la aplicación cuando ambas se ejecutan juntas. – supercat

2

Las dos respuestas antes de la mina son correctos y buenos consejos,
pero hay una cosa que no han mencionado - que es la prueba de carga.
Si le preocupa que con cierta carga su aplicación se quede sin memoria, pruébela contra esa carga (y preferiblemente, cargas más grandes).

En mi trabajo anterior utilicé una herramienta de este tipo (HP's Performance Center) y resultó invaluable no solo para verificar errores y límites de nuestro sistema, sino también para identificar cuellos de botella y operaciones costosas.

Cuestiones relacionadas