【发布时间】:2016-01-04 16:13:41
【问题描述】:
我们已将一个项目从 WCF 移植到 Web API (SelfHost),在此过程中,我们注意到在提供 Web 应用程序时速度大大降低。现在是 40-50 秒,而之前是 3 秒。
我通过使用以下控制器为 AspNet.WebApi 和 OwinSelfHost 添加各种 Nuget 包,在一个简单的控制台应用程序中重现了该问题:
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
有谁知道背后发生了什么可以解释行为差异的原因?
【问题讨论】:
-
嗨,我在这里遇到了完全相同的问题。同时你找到解决方案了吗?
-
@DanielG:恐怕不是,但我在这里发布了一个错误报告:connect.microsoft.com/VisualStudio/feedback/details/1932717/…。如果您对其进行投票并单击“我也可以”链接(在 Repros 旁边),那就太好了。
-
好的,会这样做。一个问题:如果数据已经在内存中,为什么不只使用 ByteArrayContent 呢?
-
尝试调整 StreamContent 缓冲区大小 (msdn.microsoft.com/en-us/library/hh193591(v=vs.118).aspx)。默认只有 4kb,这会导致很多写操作。
-
@hiFI 我使用 Fiddler。 ...但是数据需要很长时间才能到达,如 Fiddler 计时信息所示
标签: c# asp.net asp.net-web-api