Pregunta

Tengo 10 hilos que escriben miles de pequeños tampones (16-30 bytes cada uno) a un enorme archivo en posiciones aleatorias. Algunos de los hilos tirar OutOfMemoryException en FileStream.Write opreation ().

¿Cuál es la causa del OutOfMemoryException? Lo que debe buscar?

Estoy usando el FileStream como esto (para cada artículo escrito - este código se ejecuta a partir de 10 hilos diferentes):

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}

Sospecho que todos los buffers asignados dentro de la FileStream no son liberados en el tiempo por el GC. Lo que no entiendo es por qué el CLR, en lugar de tirar, no se limita a ejecutar un ciclo de GC y liberar todos los tampones utilizados?

No hay solución correcta

Otros consejos

Si diez hilos están abriendo los archivos como el código de muestra, entonces usted tiene un máximo de diez objetos FileStream no vendida en un momento dado. Sí, FileStream hace tiene un buffer interno, cuyo tamaño se especifica con "BigBufferSizeInBytes" en su código. Podría, por favor divulgar el valor exacto? Si esto es lo suficientemente grande (por ejemplo ~ 100 MB), entonces podría muy bien ser el origen del problema.

Por defecto (es decir, cuando no se especifica un número en construcción), este buffer es 4kB y que es por lo general muy bien para la mayoría de aplicaciones. En general, si realmente se preocupan por el rendimiento de escritura en disco, entonces es posible aumentar esta uno a un par de 100 kB, pero no más.

Sin embargo, para su aplicación específica al hacerlo, no tendría mucho sentido, ya que dicho tampón no contendrá más de los 16-30 bytes se escriben en ella, antes de desechar () del objeto FileStream.

Para responder a su pregunta, una OutOfMemoryException se lanza solamente cuando la memoria solicitada no puede ser asignado después un GC se ha ejecutado. Una vez más, si el búfer es muy grande, entonces el sistema podría tener un montón de memoria disponible, pero no es un contigua trozo. Esto es porque el montón de objetos grandes no se compacta.

He recordado a la gente acerca de esto un par de veces, pero el montón de objetos grandes que puede lanzar una excepción bastante subtially, cuando aparentemente tiene una abundancia de memoria disponible o la aplicación se ejecuta en Aceptar.

Me he encontrado con este problema con bastante frecuencia cuando se hace casi exactally lo que su discribing aquí.

Es necesario publicar más de su código para responder a esta pregunta correctamente. Sin embargo, supongo que también podría estar relacionado con un problema potencial de Halloween (Spooky Dooky) .

Su memoria intermedia a la que está leyendo también puede ser el problema (de nuevo montón de objetos grandes relacionados) también de nuevo, tiene que aguantar más detalles acerca de lo que está pasando allí en el bucle. Acabo de clavado a cabo el último fallo que tuve que es prácticamente idéntico (estoy realizando muchos de hash paralelo actualización de la que todos requieren estado independiente que se mantiene a través de lectura del archivo de entrada) ....

POO! simplemente desplazado una y notado "BigBufferSizeInBytes", me estoy inclinando hacia objeto grande Montón de nuevo ...

Si fuera tú, (y esto es extremadamente difícil debido a la falta de contexto), me gustaría ofrecer una pequeña expedición "mbuf", en la que copió de entrada y salida en lugar de permitir que todos los de su hilo disperate de leer de forma individual a través de su gran variedad respaldo ... (es decir, es difícil no causar asignaciones insadential con la sintaxis de código muy sutil).

Buffers no se asignan generalmente dentro de la FileStream. Tal vez el problema es la línea de "escribir miles de pequeñas memorias intermedias" - es lo que realmente quiere decir eso? Normalmente se vuelva a utilizar un búfer muchas, muchas, muchas veces (es decir, en diferentes llamadas de lectura / escritura).

También - se trata de un solo archivo? Una sola FileStream no se garantiza que sea seguro para subprocesos ... así que si usted no está haciendo la sincronización, le espera el caos.

Es posible que surjan estas limitaciones del sistema operativo subyacente, y que el .NET Framework es impotente para superar este tipo de limitaciones.

Lo que no puedo deducir de su código de ejemplo es si usted abre una gran cantidad de estos objetos FileStream, al mismo tiempo, o abrir ellos muy rápido en secuencia. La utilización del 'utilizar' palabras clave se asegurará de que los archivos están cerrados después de la llamada fs.Write (). No hay ciclo de GC necesaria para cerrar el archivo.

La clase FileStream está muy orientado hacia el acceso de lectura / escritura secuencial de archivos. Si necesita escribir rápidamente a lugares al azar en un archivo grande, es posible que desee echar un vistazo a el uso de asignación de archivos virtual.

Actualización: Parece que la asignación del archivo virtual no será apoyado oficialmente en .NET hasta 4,0. Es posible que desee echar un vistazo a las implementaciones de terceros para esta funcionalidad.

David

Estoy experimentando algo similar y se preguntó si alguna vez inmovilizada la raíz de su problema?

Mi código hace un buen montón de copia entre archivos, pasando bastantes megas entre diferentes archivos de bytes. Me he dado cuenta de que, aunque el proceso de uso de la memoria se mantiene dentro de un rango razonable, la asignación de memoria del sistema se dispara demasiado alto durante la reproducción - mucho más que está siendo utilizado por mi proceso.

He rastreado el problema hasta el FileStream.Write () llamada - cuando esta línea se saca, el uso de memoria parece ir según lo esperado. Mis BigBufferSizeInBytes es el valor predeterminado (4k), y no se pueden ver en cualquier lugar donde éstos podrían ser coleccionar ...

Cualquier cosa que descubrió mientras busca en su problema sería recibida con gratitud!

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