Pregunta

Escribí C ++ durante 10 años. Encontré problemas de memoria, pero podrían solucionarse con un esfuerzo razonable.

Durante los últimos años he estado escribiendo C #. Me parece que todavía tengo muchos problemas de memoria. Son difíciles de diagnosticar y corregir debido a la falta de determinación, y porque la filosofía de C # es que no debería tener que preocuparse por esas cosas cuando definitivamente lo hace.

Un problema particular que encuentro es que tengo que disponer explícitamente y limpiar todo en el código. Si no lo hago, entonces los perfiladores de memoria realmente no ayudan porque hay tanta paja flotando sobre usted que no puede encontrar una fuga en todos los datos que intentan mostrarle. Me pregunto si tengo una idea equivocada o si la herramienta que tengo no es la mejor.

¿Qué tipo de estrategias y herramientas son útiles para abordar las pérdidas de memoria en .NET?

¿Fue útil?

Solución

Utilizo MemProfiler de Scitech cuando sospecho que hay una pérdida de memoria.

Hasta ahora, he encontrado que es muy confiable y poderoso. Me ha salvado el tocino en al menos una ocasión.

El GC funciona muy bien en .NET IMO, pero al igual que cualquier otro lenguaje o plataforma, si escribe un código incorrecto, suceden cosas malas.

Otros consejos

Solo por el problema de olvidar deshacerse, intente el solución descrita en esta publicación de blog . Aquí está la esencia:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif

Hemos utilizado Ants Profiler Pro por el software Red Gate en nuestro proyecto. Funciona realmente bien para todas las aplicaciones basadas en lenguaje .NET.

Descubrimos que .NET Garbage Collector es muy "seguro". en su limpieza de objetos en memoria (como debe ser). Mantendría objetos alrededor solo porque podríamos usarlo en algún momento en el futuro. Esto significaba que teníamos que tener más cuidado con la cantidad de objetos que inflamos en la memoria. Al final, convertimos todos nuestros objetos de datos en un "inflar a pedido". (justo antes de solicitar un campo) para reducir la sobrecarga de memoria y aumentar el rendimiento.

EDITAR: Aquí hay una explicación más detallada de lo que quiero decir con "inflar bajo demanda". En nuestro modelo de objetos de nuestra base de datos, utilizamos las propiedades de un objeto primario para exponer los objetos secundarios. Por ejemplo, si tuviéramos algún registro que hiciera referencia a algún otro "detalle". o " buscar " grabar de forma individualizada lo estructuraríamos así:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

Descubrimos que el sistema anterior creó algunos problemas reales de memoria y rendimiento cuando había muchos registros en la memoria. Entonces cambiamos a un sistema donde los objetos se inflaban solo cuando se solicitaban, y las llamadas a la base de datos se realizaban solo cuando era necesario:

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

Esto resultó ser mucho más eficiente porque los objetos se mantuvieron fuera de la memoria hasta que se necesitaron (se accedió al método Get). Proporcionó un aumento de rendimiento muy grande al limitar las visitas a la base de datos y una gran ganancia en espacio de memoria.

Aún debe preocuparse por la memoria cuando escribe código administrado a menos que su aplicación sea trivial. Sugeriré dos cosas: primero, lea CLR a través de C # porque lo ayudará a comprender la administración de memoria en .NET. En segundo lugar, aprenda a utilizar una herramienta como CLRProfiler (Microsoft). Esto puede darle una idea de lo que está causando la pérdida de memoria (por ejemplo, puede echar un vistazo a la fragmentación del montón de objetos grandes)

¿Está utilizando código no administrado? Si no está utilizando código no administrado, según Microsoft, las pérdidas de memoria en el sentido tradicional no son posibles.

Sin embargo, es posible que la memoria utilizada por una aplicación no se libere, por lo que la asignación de memoria de una aplicación puede aumentar a lo largo de la vida útil de la aplicación.

  

De Cómo identificar pérdidas de memoria en el tiempo de ejecución del idioma común en Microsoft.com

     

Se puede producir una pérdida de memoria en un .NET   Aplicación de marco cuando se utiliza   código no administrado como parte de la   solicitud. Este código no administrado puede   pérdida de memoria y .NET Framework   el tiempo de ejecución no puede resolver ese problema.

     

Además, un proyecto solo puede   parece tener una pérdida de memoria. Esta   condición puede ocurrir si muchos grandes   objetos (como objetos DataTable)   se declaran y luego se agregan a un   colección (como un conjunto de datos). los   los recursos que poseen estos objetos pueden   nunca se dará a conocer, y los recursos   se dejan vivos para toda la carrera de   el programa. Esto parece ser un   fuga, pero en realidad es solo una   síntoma de la forma en que es la memoria   ser asignado en el programa.

Para tratar este tipo de problema, puede implementar IDisposable . Si desea ver algunas de las estrategias para lidiar con la administración de la memoria, sugeriría buscar IDisposable, XNA, memory management , ya que los desarrolladores de juegos necesitan tener una recolección de basura más predecible y, por lo tanto, deben obligar al GC a hacer lo suyo.

Un error común es no eliminar los controladores de eventos que se suscriben a un objeto. Una suscripción de controlador de eventos evitará que un objeto sea reciclado. También, eche un vistazo a la utilizando la declaración que le permite crear un alcance limitado para la vida útil de un recurso.

Este blog tiene algunos tutoriales realmente maravillosos que utilizan windbg y otras herramientas para rastrear pérdidas de memoria de todo tipo. Excelente lectura para desarrollar tus habilidades.

Acabo de tener una pérdida de memoria en un servicio de Windows, que arreglé.

Primero, probé MemProfiler . Me resultó muy difícil de usar y no es fácil de usar.

Luego, utilicé JustTrace , que es más fácil de usar y proporciona Más detalles sobre los objetos que no se eliminan correctamente.

Me permitió resolver la pérdida de memoria con mucha facilidad.

Si las fugas que está observando se deben a una implementación de caché fuera de control, este es un escenario en el que puede desear considerar el uso de WeakReference. Esto podría ayudar a garantizar que se libere memoria cuando sea necesario.

Sin embargo, en mi humilde opinión, sería mejor considerar una solución a medida: solo usted realmente sabe cuánto tiempo necesita mantener los objetos, por lo que diseñar el código de limpieza adecuado para su situación suele ser el mejor enfoque.

Big guns - Depuración Herramientas para Windows

Esta es una increíble colección de herramientas. Puede analizar tanto los montones administrados como los no administrados y puede hacerlo sin conexión. Esto fue muy útil para depurar una de nuestras aplicaciones ASP.NET que mantuvo el reciclaje debido al uso excesivo de la memoria. Solo tuve que crear un volcado de memoria completa del proceso vivo que se ejecuta en el servidor de producción, todo el análisis se realizó sin conexión en WinDbg. (Resultó que algunos desarrolladores estaban abusando del almacenamiento de sesión en memoria).

" Si está roto es ... " el blog es muy útil Artículos sobre el tema.

Lo mejor a tener en cuenta es realizar un seguimiento de las referencias a sus objetos. Es muy fácil terminar colgando referencias a objetos que ya no te importan. Si ya no va a usar algo, deshágase de él.

Familiarícese con el uso de un proveedor de caché con vencimientos deslizantes, de modo que si no se hace referencia a una ventana de tiempo deseada, se elimine la referencia y se limpie. Pero si se está accediendo mucho, dirá en la memoria.

Una de las mejores herramientas es utilizar Herramientas de depuración para Windows , y tomando un volcado de memoria del proceso usando adplus , luego use windbg y el complemento sos para Analice la memoria de proceso, los hilos y las pilas de llamadas.

También puede usar este método para identificar problemas en los servidores, después de instalar las herramientas, comparta el directorio, luego conéctese al recurso compartido desde el servidor utilizando (uso neto) y realice un bloqueo o cuelgue el proceso.

Luego analice sin conexión.

Después de una de mis correcciones para la aplicación administrada tuve la misma cosa, como cómo verificar que mi aplicación no tendrá la misma pérdida de memoria después de mi próximo cambio, por lo que escribí algo como el marco de Verificación de liberación de objetos, por favor, tome un vistazo al paquete NuGet ObjectReleaseVerification . Puede encontrar una muestra aquí https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample, e información sobre este ejemplo http://outcoldman.ru/en/blog/show/322

Prefiero dotmemory de Jetbrains

De Visual Studio 2015, considere utilizarlo de forma inmediata Herramienta de diagnóstico de uso de memoria para recopilar y analizar datos de uso de memoria.

La herramienta de uso de memoria le permite tomar una o más instantáneas del montón de memoria administrada y nativa para ayudar a comprender el impacto en el uso de la memoria de los tipos de objetos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top