ASP.NET Web API 2 - StreamContent 非常慢 [英] ASP.NET Web API 2 - StreamContent is extremely slow

查看:25
本文介绍了ASP.NET Web API 2 - StreamContent 非常慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们已将一个项目从 WCF 移植到 Web API (SelfHost),在此过程中,我们注意到在提供 Web 应用程序时速度明显减慢.现在是 40-50 秒,而之前是 3 秒.

We've ported a project from WCF to Web API (SelfHost) and during the process we noticed a huge slowdown when serving out a web application. Now 40-50 seconds vs 3 seconds previously.

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

I've reproduce the issue in a simple console application by adding the various Nuget pacakges for AspNet.WebApi and OwinSelfHost with the following controller:

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 的用法.

As you can see from the code the only difference is the usage of StreamContent (slooooow) vs ByteArrayContent.

该应用程序托管在一台 Win10 机器上,可从我的笔记本电脑访问.Fiddler 显示,使用 StreamContent 将单个 1MB 文件从服务器获取到我的笔记本电脑需要 14 秒,而 ByteArrayContent 不到 1 秒.

The application is hosted on a Win10 machine and accessed from my laptop. Fiddler shows that it takes 14 seconds to get a single 1MB file from the server to my laptop using StreamContent while ByteArrayContent is less than 1s.

另请注意,完整的文件被读入内存以表明唯一的区别是使用的 Content 类.

Also note that the complete file is read into memory to show that the only difference is the Content class used.

奇怪的是,传输本身似乎很慢.服务器快速/立即响应标头,但数据需要很长时间才能到达,如 Fiddler 计时信息所示:

The strange thing is that it seems that its the transfer itself that is slow. The server responds with the headers quickly/immediately, but the data takes a long time to arrive as shown by the Fiddler timing info:

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

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

Does anyone know what's going on under the hood that could explain the difference in behavior?

推荐答案

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

The solution to my problem for OWIN self hosting was the StreamContent buffer size. The default constructor of StreamContent uses a default value of 0x1000, 4Kb. On a gigabit network, transfer of 26Mb file takes ~7 minutes to complete at rate of ~60Kb/s.

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

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

Modifying the bufferSize to 1Mb now take only seconds to complete the download.

在 StreamContent SerializeToStreamAsync 中执行 StreamToStreamCopy,根据 此链接,性能会有所不同.一个合适的值大概是 80K.

In StreamContent SerializeToStreamAsync does a StreamToStreamCopy, according to this link the performance will differ. A suitable value is probably 80K.

这篇关于ASP.NET Web API 2 - StreamContent 非常慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆