C# ASP.NET Web API 2-StreamContent非常慢
我们已经将一个项目从WCF移植到Web API(SelfHost),在这个过程中,我们注意到在提供Web应用程序时速度大大减慢。现在是40-50秒,而之前是3秒 我在一个简单的控制台应用程序中重现了这个问题,为AspNet.WebApi和OwinSelfHost添加了各种Nuget包,其中包含以下控制器:C# ASP.NET Web API 2-StreamContent非常慢,c#,asp.net,asp.net-web-api,C#,Asp.net,Asp.net Web Api,我们已经将一个项目从WCF移植到Web API(SelfHost),在这个过程中,我们注意到在提供Web应用程序时速度大大减慢。现在是40-50秒,而之前是3秒 我在一个简单的控制台应用程序中重现了这个问题,为AspNet.WebApi和OwinSelfHost添加了各种Nuget包,其中包含以下控制器: var stream = new MemoryStream(); using (var file = File.OpenRead(filename)) { file.CopyTo(st
var stream = new MemoryStream();
using (var file = File.OpenRead(filename))
{
file.CopyTo(stream);
}
stream.Position = 0;
var response = Request.CreateResponse(System.Net.HttpStatusCode.OK);
/// THIS IS FAST
response.Content = new ByteArrayContent(stream.ToArray());
/// THIS IS SLOW
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue(System.Web.MimeMapping.GetMimeMapping(filename));
response.Content.Headers.ContentLength = stream.Length;
从代码中可以看出,唯一的区别是StreamContent(slooow)与ByteArrayContent的用法
该应用程序托管在Win10机器上,并可从我的笔记本电脑访问。
Fiddler显示,使用StreamContent将一个1MB的文件从服务器发送到我的笔记本电脑需要14秒,而ByteArrayContent则不到1秒
还要注意,完整的文件被读入内存,以表明唯一的区别是所使用的内容类
奇怪的是,传输本身似乎很慢。服务器会快速/立即响应标题,但数据需要很长时间才能到达,如Fiddler计时信息所示:
GotResponseHeaders: 07:50:52.800
ServerDoneResponse: 07:51:08.471
完整的时间信息:
== TIMING INFO ============
ClientConnected: 07:50:52.238
ClientBeginRequest: 07:50:52.238
GotRequestHeaders: 07:50:52.238
ClientDoneRequest: 07:50:52.238
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 15ms
HTTPS Handshake: 0ms
ServerConnected: 07:50:52.253
FiddlerBeginRequest:07:50:52.253
ServerGotRequest: 07:50:52.253
ServerBeginResponse:07:50:52.800
GotResponseHeaders: 07:50:52.800
ServerDoneResponse: 07:51:08.471
ClientBeginResponse:07:51:08.471
ClientDoneResponse: 07:51:08.471
Overall Elapsed: 0:00:16.233
有人知道幕后发生了什么可以解释行为上的差异吗?编译项目时,请尝试从调试更改为发布。这是一个长镜头,但肯定会提高性能一点。我在这里面临同样的问题,我认为这与Owin自托管有关。我刚刚创建了一个Asp.net示例应用程序,并将其托管在IIS上。在那种情况下,它按预期工作 下载80 MB文件时在我的测试系统上的结果:
- 使用Streamcontent和自托管:~20分钟
- 使用ByteArrayContent和自托管:<30秒
- 使用Streamcontent和IIS托管:<30秒
要么是ASP.net中有一个配置设置,而我的自托管项目中缺少该设置,要么是owin自托管代码中有一个bug。解决owin自托管问题的方法是StreamContent缓冲区大小。StreamContent的默认构造函数使用默认值0x1000,4Kb。在千兆网络上,以约60Kb/s的速率传输26Mb文件需要约7分钟才能完成
const int BufferSize = 1024 * 1024;
responseMessage = new HttpResponseMessage();
responseMessage.Content = new StreamContent(fileStream, BufferSize);
现在将bufferSize修改为1Mb只需几秒钟即可完成下载
[EDIT]在StreamContent SerializeToStreamAsync中,根据性能的不同,执行StreamToStreamCopy。一个合适的值可能是80K。恐怕没有什么区别。嗨,我在这里面临着完全相同的问题。你同时找到解决方案了吗?@DanielG:恐怕没有,但我在这里发布了一个bug报告:。如果你投票并点击“我也可以”链接(在“复制”旁边),那就太好了。好的,我会这么做的。一个问题:如果内存中已经有数据,为什么不直接使用ByteArrayContent?请尝试调整StreamContent缓冲区大小()。默认值只有4kb,这将导致许多写入操作。@hiFI我使用Fiddler。。。但是数据需要很长时间才能到达,如Fiddler计时信息所示