c# - Qué causa la fragmentación de la memoria en.NET
memory-management memory-leaks (3)
Estoy usando el analizador de memoria ANTS Red Gates para depurar una pérdida de memoria. Me sigue advirtiendo que:
La fragmentación de memoria puede estar causando que .NET guarde demasiada memoria libre.
o
La fragmentación de memoria está afectando el tamaño del objeto más grande que se puede asignar
Debido a que tengo TOC, este problema debe ser resuelto.
¿Cuáles son algunas prácticas de codificación estándar que ayudan a evitar la fragmentación de memoria? ¿Puedes desfragmentarlo a través de algunos métodos .NET? ¿Ayudaría?
.NET Framework 4.5.1 tiene la capacidad de compactar de forma explícita el gran montón de objetos (LOH) durante la recolección de elementos no utilizados.
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
Ver más información en GCSettings.LargeObjectHeapCompactionMode
El montón de GC trata las asignaciones de objetos grandes de forma diferente. No los compacta, sino que combina bloques libres adyacentes (como una memoria tradicional no administrada).
Más información aquí: http://msdn.microsoft.com/en-us/magazine/cc534993.aspx
Entonces, la mejor estrategia con objetos muy grandes es asignarlos una vez y luego conservarlos y reutilizarlos.
Ya sabes, dudo un poco del perfilador de memoria aquí. El sistema de administración de memoria en .NET realmente intenta desfragmentar el montón moviendo la memoria (es por eso que necesita fijar la memoria para que se comparta con una DLL externa).
Las grandes asignaciones de memoria tomadas durante períodos de tiempo más largos son propensas a una mayor fragmentación. Si bien es poco probable que las pequeñas solicitudes de memoria efímeras (cortas) causen fragmentación en .NET.
Aquí también hay algo en lo que vale la pena pensar. Con el GC actual de .NET, la memoria asignada cerca en el tiempo, típicamente está espaciada muy cerca en el espacio. Que es lo opuesto a la fragmentación. es decir, debe asignar memoria de la manera en que pretende acceder a ella.
¿Es solo un código administrado o contiene cosas como P / Invoke, memoria no administrada (Marshal.AllocHGlobal) o cosas como GCHandle.Alloc (obj, GCHandleType.Pinned)?