Salida sin búfer muy lenta

Genero un archivo .csv muy grande de una base de datos usando el método descrito en

https://stackoverflow.com/a/13456219/141172

Funciona bien, hasta cierto punto. Cuando el archivo exportado es demasiado grande, obtengo una OutOfMemoryException .

Si apago el almacenamiento en búfer de salida modificando ese código de esta manera:

 protected override void WriteFile(System.Web.HttpResponseBase response) { response.BufferOutput = false; // <--- Added this this.Content(response.OutputStream); } 

la descarga del archivo se completa. Sin embargo, es varios órdenes de magnitud más lento que cuando se habilitó el almacenamiento en búfer de salida (medido para el mismo archivo con almacenamiento en búfer true / false, en localhost).

Entiendo que es más lento, pero ¿por qué desaceleraría a un rastreo relativo? ¿Hay algo que pueda hacer para mejorar la velocidad de procesamiento?

ACTUALIZAR

También sería una opción utilizar File (Stream stream, String contentType) como se sugiere en los comentarios. Sin embargo, no estoy seguro de cómo crear la stream . Los datos se ensamblan dinámicamente en base a una consulta DB, y un MemoryStream se quedaría sin memoria física contigua. Sugerencias son bienvenidas.

ACTUALIZACIÓN 2

Se sugirió en los comentarios que la lectura alterna de la base de datos y la escritura en la secuencia están causando una degradación. Modifiqué el código para realizar la escritura de flujo en un hilo separado (usando el patrón productor / consumidor). No hay una diferencia apreciable en el rendimiento.

No sé qué ASP.NET e IIS están haciendo exactamente con la transmisión de salida, pero tal vez se están utilizando fragmentos demasiado pequeños. Enganche en un BufferedStream con un buffer muy grande, como 4MB.

De acuerdo con tus comentarios, funcionó. Ahora, sintonice el tamaño del búfer para guardar la memoria y tener un conjunto de trabajo más pequeño. Bueno para el caché.

Como comentario subjetivo, estoy decepcionado de que esto sea necesario. IIS debería usar los búferes correctos automáticamente, lo que es extremadamente fácil con las conexiones TCP.

EDITAR DESDE OP

Aquí está el código derivado de esta respuesta

 public ActionResult Export() { // Domain specific stuff here return new FileGeneratingResult("MyFile.txt", "text/text", stream => this.StreamExport(stream), false); } private void StreamExport(Stream stream) { using (BufferedStream bs = new BufferedStream(stream, 256*1024)) using (StreamWriter sw = new StreamWriter(bs)) foreach (var stuff in MyData()) { sw.Write(stuff); } } 

En la última actualización de Eric, mencionó el uso de otro hilo. Yo también tuve este problema para implementar las exportaciones de bases de datos. Aquí hay un código de ejemplo para la solución que utilicé:

Manejo con secuencia de archivos temporales