2010-02-24 24 views
8

Tengo una excepción de memoria insuficiente usando C# cuando se lee en un archivo masivoC# Aumentar Tamaño de pila - ¿Es posible

tengo que cambiar el código, pero por el momento puedo aumentar el tamaño del montón (como yo lo haría en Java) como una solución a corto plazo?

+1

¿Está leyendo el archivo de una vez? Es posible leer y tratar los datos poco a poco. – rerun

+0

Creo que .net ahora también tiene Memory Maps, http://blogs.msdn.com/b/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx –

Respuesta

6

.Net lo hace automáticamente.

Parece que ha llegado al límite de la memoria que un proceso .Net puede usar para sus objetos (en la máquina de 32 bits esto es 2 estándar o 3GB usando el interruptor de inicio/3GB. Créditos a Leppie & Eric Lippert para la información).

Repiense su algoritmo, o tal vez un cambio en una máquina de 64 bits podría ayudar.

+1

El límite de proceso es de 2 GB en 32 bits, a menos que use el modificador de inicio/3GB. – leppie

+0

Recuerdo vagamente que las aplicaciones .NET en sistemas de 32 bits están limitadas a 800 MB, o algo así. – OregonGhost

+2

@OregonGhost: Lo más probable es que si asigna un bloque continuo de 800 MB (como una matriz), no tendrá suficiente espacio virtual. – leppie

5

No, esto no es posible. Este problema puede ocurrir porque está ejecutando un sistema operativo de 32 bits y la memoria está demasiado fragmentada. Intente no cargar todo el archivo en la memoria (por ejemplo, procesando línea por línea) o, cuando realmente necesite cargarlo completamente, al cargarlo en varias partes más pequeñas.

+0

+1, ya que la fragmentación es una causa típica de OutOfMemoryException en .NET. – OregonGhost

+0

GvS tiene razón: .NET hace esto automáticamente. Hacer esto manualmente no es posible. – Steven

+0

Esto ha cambiado, y el límite se eliminó en .NET 4.5. Los procesos compilados de 64 bits pueden usar más de 2 GB. – ppumkin

2

Como ya se ha señalado, esto no es posible. El tiempo de ejecución de .NET maneja asignaciones de almacenamiento dinámico en nombre de la aplicación.

En mi experiencia, las aplicaciones .NET comúnmente sufren de OOM cuando debería haber suficiente memoria disponible (o al menos, eso parece). La razón de esto suele ser el uso de grandes colecciones como matrices, Lista (que utiliza una matriz para almacenar sus datos) o similar.

El problema es que estos tipos a veces crean picos en el uso de la memoria. Si no se pueden cumplir estas solicitudes pico, se lanzará una excepción OOM. P.ej. cuando List necesita aumentar su capacidad, lo hace asignando una nueva matriz del doble del tamaño actual y luego copia todas las referencias/valores de una matriz a la otra. De forma similar, operaciones como ToArray hacen una nueva copia de la matriz. También he visto problemas similares en grandes operaciones LINQ.

Cada matriz se almacena como memoria contigua, por lo que para evitar OOM, el tiempo de ejecución debe poder obtener una gran cantidad de memoria. Como el espacio de direcciones del proceso puede estar fragmentado debido a la carga DLL y al uso general para el almacenamiento dinámico, esto no siempre es posible, en cuyo caso se lanza una excepción OOM.

0

¿Con qué tipo de archivo está tratando?

Puede ser mejor que use un StreamReader y ceda devolver el resultado ReadLine, si es textual.

Seguro, mantendrá un puntero de archivo, pero el peor de los casos se reduce enormemente.

Existen métodos similares para archivos binarios, si está cargando un archivo a SQL, por ejemplo, puede leer un byte [] y usar la mecánica del puntero Sql para escribir el búfer al final de un blob.

Cuestiones relacionadas