ASP.NET Web API 2 - StreamContent非常慢

时间:2015-10-07 12:21:55

标签: c# asp.net asp.net-web-api

我们已经将一个项目从WCF移植到Web API(SelfHost),在此过程中我们注意到在提供Web应用程序时出现了巨大的减速。现在是40-50秒,而之前是3秒。

我通过使用以下控制器为AspNet.WebApi和OwinSelfHost添加各种Nuget pacakges,在一个简单的控制台应用程序中重现了这个问题:

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(slooooow)与ByteArrayContent的使用。

该应用程序托管在Win10机器上,可从我的笔记本电脑访问。 Fiddler表示,使用StreamContent从服务器到笔记本电脑的单个1MB文件需要14秒,而ByteArrayContent小于1秒。

另请注意,将完整文件读入内存以显示唯一的区别是使用的Content类。

奇怪的是,它的转移本身似乎很慢。服务器快速/立即响应标头,但数据需要很长时间才能到达,如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

有谁知道幕后发生了什么可以解释行为的差异?

3 个答案:

答案 0 :(得分:24)

我的OWIN自托管问题的解决方案是StreamContent缓冲区大小。 StreamContent的默认构造函数使用默认值0x1000,4Kb。在千兆网络上,传输26Mb文件大约需要7分钟才能完成,速率约为60Kb / s。

 const int BufferSize = 1024 * 1024;
 responseMessage = new HttpResponseMessage();
 responseMessage.Content = new StreamContent(fileStream, BufferSize);

现在将bufferSize修改为1Mb只需几秒钟即可完成下载。

[编辑]在StreamContent中,SerializeToStreamAsync执行StreamToStreamCopy,根据this link,性能会有所不同。合适的值可能是80K。

答案 1 :(得分:5)

我在这里遇到同样的问题,我认为这与Owin自托管相关。我刚刚创建了一个Asp.net示例应用程序并将其托管在IIS上。在那种情况下,它按预期工作。

下载80 MB文件时,我的Testsystem上的结果:

  • 使用Streamcontent和SelfHosting:约20分钟
  • with ByteArrayContent和Selfhosting:< 30秒
  • with Streamcontent和IIS Hosting:< 30秒

ASP.net中有一个配置设置,我在自托管项目中遗漏了这个设置,或者我认为owin自托管代码存在错误。

答案 2 :(得分:0)

编译项目时,请尝试从debug更改为release。这是一个很好的镜头,但肯定会提高性能。