Небуферизованный вывод очень медленный

Я генерирую очень большой файл.csv из базы данных, используя метод, изложенный в

/questions/22769912/zapis-v-potok-vyivoda-iz-dejstviya/22769947#22769947

Работает нормально, до определенного момента. Когда экспортируемый файл слишком велик, я получаю OutOfMemoryException,

Если я отключу буферизацию вывода, изменив этот код следующим образом:

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

загрузка файла завершена. Однако он на несколько порядков медленнее, чем при включенной буферизации вывода (измерено для того же файла с буферизацией true / false на локальном хосте).

Я понимаю, что это медленнее, но почему это замедлится до относительного сканирования? Что я могу сделать, чтобы улучшить скорость обработки?

ОБНОВИТЬ

Также будет предложено использовать File(Stream stream, String contentType), как это предлагается в комментариях. Тем не менее, я не уверен, как создать stream, Данные динамически собираются на основе запроса к БД, и MemoryStream исчерпывает непрерывную физическую память. Предложения приветствуются.

ОБНОВЛЕНИЕ 2

В комментариях было высказано предположение, что поочередное чтение из базы данных и запись в поток приводит к ухудшению. Я изменил код для выполнения записи потока в отдельном потоке (используя шаблон производитель / потребитель). Там нет заметной разницы в производительности.

2 ответа

Решение

Я не знаю, что именно ASP.NET и IIS делают с потоковой передачей, но, возможно, используются слишком маленькие куски. Крюк в BufferedStream с очень большим буфером, как 4 МБ.

По вашим комментариям это сработало. Теперь уменьшите размер буфера, чтобы сэкономить память и иметь меньший рабочий набор. Хорошо для кеша.

В качестве субъективного комментария я разочарован тем, что это даже необходимо. IIS должен использовать правильные буферы автоматически, что очень просто для TCP-соединений.

РЕДАКТИРОВАТЬ ИЗ ОП

Вот код, полученный из этого ответа

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);
    }
}

В последнем обновлении Эрика он упомянул использование другого потока. У меня тоже была эта проблема для реализации экспорта базы данных. Вот пример кода для решения, которое я использовал:

Обработка с временным потоком файлов

Другие вопросы по тегам