terraria solucion outofmemoryexception net increase asp c# asp.net memory out-of-memory

c# - solucion - OutOfMemoryException al rellenar MemoryStream: 256MB de asignación en un sistema de 16GB



system.outofmemoryexception c# solucion (2)

Estoy ejecutando el siguiente método en mi servidor IIS de desarrollo (de VS2010 IDE) en una máquina Windows 7 de 64 bits con 16GB de RAM instalada:

public static MemoryStream copyStreamIntoMemoryStream(Stream stream) { long uiLen = stream.Length; byte[] buff = new byte[0x8000]; int nSz; MemoryStream ms = new MemoryStream(); try { while ((nSz = stream.Read(buff, 0, buff.Length)) != 0) { ms.Write(buff, 0, nSz); } } finally { Debug.WriteLine("Alloc size=" + ms.Length); } return ms; }

y obtengo la System.OutOfMemoryException en esta línea:

ms.Write(buff, 0, nSz);

Se lanza cuando se asignan 268435456 bytes:

Tamaño de asignación = 268435456

que es 0x10000000 o 256 MB. ¿Entonces me pregunto si hay alguna configuración global que deba establecer para que funcione?

Aquí hay una captura de pantalla de los ajustes de configuración para el proyecto:


Si está utilizando el servidor de desarrollo VS predeterminado, está ejecutando el código en un proceso de x86 / 32 bits. Si está utilizando IIS completo, lo más probable es que, en particular, IIS, AppPool esté configurado para ejecutarse en x86 (modo de 32 bits) y, como resultado, tenga un espacio de direcciones muy limitado (2 GB a menos que haya marcado su aplicación como Large Address Aware).

En el caso de IIS, asegúrese de haber configurado las encuestas de aplicación para ejecutar x64 (no está seguro de cuál es el valor predeterminado). Asegúrese de que su código sea el objetivo establecido en AnyCPU o x64.

Para aplicaciones C # independientes, de forma predeterminada, están compiladas con x86 o AnyCPU / Preferir x86: cambian la plataforma de destino a x64.

Para obtener compatibilidad con x64 para IIS, puede instalar IIS completo o instalar IIS Express 8.0 (7.5 que viene con Windows 7 es solo de 32 bits) desde Descargar IIS 8.0 Express .

Notas al margen:


Respuesta corta : el servidor dev es un proceso de 32 bits.

Respuesta larga para "¿Por qué solo 256Mb?"

En primer lugar, vamos a entender cómo funciona.

MemoryStream tiene un byte interno [] buffer para guardar todos los datos. No puede predecir el tamaño exacto de este búfer, por lo que simplemente lo inicializa con un valor inicial.

Las propiedades de Posición y Longitud no reflejan el tamaño del búfer real, son valores lógicos que reflejan cuántos bytes se escriben y, fácilmente, pueden ser más pequeños que el tamaño del búfer físico real.

Cuando este búfer interno no puede ajustarse a todos los datos, debe "redimensionarse", pero en la vida real significa crear un búfer nuevo dos veces más grande que el anterior, y luego copiar los datos del búfer antiguo al búfer nuevo.

Entonces, si la longitud de su búfer es de 256Mb, y necesita escribir nuevos datos, esto significa que .Net necesita encontrar otro bloque de datos de 512Mb, teniendo todo el resto en su lugar, por lo que Heap debería tener al menos 768Mb en El momento de asignación de memoria cuando recibe OutOfMemory.

También tenga en cuenta que, de forma predeterminada, ningún objeto individual, incluidas las matrices, en .Net puede tener más de 2 Gb de tamaño.

Ok, así que aquí está la pieza de muestra que simula lo que está sucediendo:

byte[] buf = new byte[32768 - 10]; for (; ; ) { long newSize = (long)buf.Length * 2; Console.WriteLine(newSize); if (newSize > int.MaxValue) { Console.WriteLine("Now we reach the max 2Gb per single object, stopping"); break; } var newbuf = new byte[newSize]; Array.Copy(buf, newbuf, buf.Length); buf = newbuf; }

Si está integrado en x64 / AnyCPU y se ejecuta desde la consola, todo está bien.

Si se construyó en x86, falla en la consola.

Si lo pone para decir Page_Load, incorporado en x64, y se abre desde el servidor web de VS.Net, falla.

Si haces lo mismo con IIS, todo está bien.

Espero que esto ayude.