2011-04-17 9 views
16

Tengo una aplicación C# 4.0 (productor único/consumidor único) que transfiere gran cantidad de datos en fragmentos. Aunque no hay una nueva asignación de memoria, me quedo sin memoria después de un tiempo.Fragmentación del montón al usar matrices de bytes

I memoria perfilada utilizando el perfilador de memoria Redgate y hay una gran cantidad de memoria libre allí. Dice que la memoria libre no se puede usar debido a la fragmentación.

utilizo el bloqueo de una colección como las matrices de amortiguamiento y de bytes como los miembros:

BlockingCollection<byte[]> segments = new BlockingCollection<byte[]>(8); 
// producer: 
segments.Add(buffer); 
// consumer: 
byte[] buffer = _segments.Take(); 

¿Cómo puedo evitar la fragmentación de la memoria administrada?

Respuesta

10

Probablemente haya tropezado con el gran problema del montón de objetos: los objetos de más de 85,000 bytes se colocan en el gran montón de objetos que no está compactado, lo que puede provocar extrañas situaciones de falta de memoria. Aunque aparentemente el rendimiento en .NET 4 se ha mejorado, está lejos de ser perfecto. La solución es básicamente usar su propio grupo de búferes que contenga algunos fragmentos de memoria asignados estáticamente y reutilizarlos.
Hay un montón de preguntas al respecto en SO.

Actualización: Microsoft proporciona un buffer manager como parte de la pila de WCF. También hay one on codeproject.

+0

Chris tiene razón, la otra opción es usar objetos de menos de 85k para que no terminen asignados en el LOH. – Ian

+0

La solución de Microsoft es lo suficientemente buena para mi caso. Como es abstracto, debería implementar el mío. Entonces debería crear un administrador de buffer 'estático' para todas las instancias de transportadores de datos o un singleton o un miembro de instancia por transportador de datos (cada transportador de datos vive durante 2 a 3 horas y hay 1000 de ellos, cada uno usa 8x256 KB de memoria) – Xaqron

+0

La creación de un administrador de búfer para cada transportador suena como si simplemente moviera el problema de fragmentación del montón a un lugar diferente (asignando trozos más grandes de memoria y luego liberándola de nuevo). Podrías tener un grupo de administradores de búfer, pero yo iría primero con el singleton y veré si hay algún problema con él. Probablemente pueda diseñarlo para que esté escondido detrás de una interfaz y cada transportador tenga su propia referencia. Luego puede cambiar fácilmente la implementación entre singleton y por instancia o algo intermedio como lo desee. – ChrisWue

3

¿Cuánto dura su matriz byte []? ¿Caen en el pequeño objeto o montón de objetos grandes? Si experimentas fragmentación de memoria, diría que caen en LOH.

Por lo tanto, debe reutilizar las mismas matrices de bytes (usar un grupo) o usar fragmentos más pequeños. El LOH nunca se compacta, por lo que puede volverse bastante fragmentado. Lamentablemente no hay forma de evitar esto. (Además de conocer esta limitación y evitarla)

+0

Uso durante aproximadamente 2-3 horas y 8x256 KB, el generador de perfiles de memoria dice que es un gran montón de objetos. ¿Cómo puedo crear un grupo de arreglos de bytes? (enlace útil es apreciado) – Xaqron

Cuestiones relacionadas