无缓冲输出非常慢

时间:2014-09-24 07:22:23

标签: asp.net-mvc asp.net-mvc-4

我使用

中概述的方法从数据库生成一个非常大的.csv文件

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

它工作正常,达到一定程度。当导出的文件太大时,我会得到OutOfMemoryException

如果我通过修改这样的代码来关闭输出缓冲:

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

文件下载完成。但是,与启用输出缓冲时相比,它的几个数量级更慢(在localhost上测量缓冲为真/假的同一文件)。

我明白这个速度较慢,但​​为什么它会慢慢相对爬行呢?我能做些什么来提高处理速度吗?

更新

如评论中所建议的,使用File(Stream stream, String contentType)也是一种选择。但是,我不确定如何创建stream。数据是基于数据库查询动态组合的,而MemoryStream将耗尽连续的物理内存。欢迎提出建议。

更新2

在评论中建议,交替从数据库中读取并写入流会导致性能下降。我修改了代码以在单独的线程中执行流写入(使用生产者/消费者模式)。性能没有明显差异。

2 个答案:

答案 0 :(得分:7)

我不知道ASP.NET和IIS在输出流方面做了什么,但可能正在使用太小的块。挂钩BufferedStream有一个非常大的缓冲区,比如4MB。

根据你的意见,它有效。现在,调低缓冲区大小以节省内存并使用较小的工作集。适合缓存。

作为主观评论,我很失望,这甚至是必要的。 IIS应该自动使用正确的缓冲区,这对于TCP连接非常容易。

从OP编辑

以下是从此回答中获得的代码

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

答案 1 :(得分:0)

在Eric的最新更新中,他提到使用另一个线程。我也有实现数据库导出的问题。以下是我使用的解决方案的一些示例代码:

Handling with temporary file stream