【发布时间】:2014-09-24 07:22:23
【问题描述】:
我使用中概述的方法从数据库生成一个非常大的 .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);
}
文件下载完成。但是,它比启用输出缓冲时慢了几个数量级(在本地主机上针对具有缓冲真/假的同一文件测量)。
我知道这比较慢,但为什么它会慢到相对爬行?我可以做些什么来提高处理速度?
更新
按照 cmets 的建议,也可以选择使用 File(Stream stream, String contentType)。但是,我不确定如何创建stream。数据是基于 DB 查询动态组装的,MemoryStream 将耗尽连续的物理内存。欢迎提出建议。
更新 2
在 cmets 中建议交替从数据库读取和写入流会导致降级。我修改了代码以在单独的线程中执行流写入(使用生产者/消费者模式)。性能没有明显差异。
【问题讨论】:
-
我不明白你为什么需要那个链接的答案。从您的操作中简单地返回
File(myStream, "text/csv")有什么问题? msdn.microsoft.com/en-us/library/dd493017(v=vs.100).aspx -
我读错了吗?您将响应输出流作为输入传递给 Content?然后哪个再次写入响应输出流?您要覆盖哪个类的 WriteFile 方法?
-
@ta.speot.is:我不确定如何创建
myStream。数据是基于 DB 查询动态组装的,MemoryStream 将耗尽连续的物理内存。你能展示一个模式来创建一个可以传递给File(myStream, "text/csv")的myStream吗? -
@ErikFunkenbusch:被覆盖的方法来自 FileResult。 Content() 是一个
Action<Stream>,允许我提供一种以结构化方式写入response.OutputStream的方法。 msdn.microsoft.com/en-us/library/… -
嗯,它会很慢,因为在输出缓存打开的情况下,当服务器需要一个新块发送给客户端时,它会从缓存中获取它,这非常快。因此,如果发送一个块需要 100 毫秒,获取下一个块需要 1 毫秒,这是 101 毫秒 + 101 毫秒 +.. 等等。如果没有缓存,从数据库读取下一个块可能需要 100 毫秒,所以现在发送需要 100 毫秒块和 100 毫秒来获取下一个块,所以它是 200 毫秒 + 200 毫秒 + ......等等......输出缓存有效地让您使用“发送时间”提前读取,而未缓存它会阻塞并按需读取。跨度>