我们已经将一个项目从WCF移植到Web API(SelfHost),并且在此过程中,我们发现在提供Web应用程序时出现了巨大的速度下降。现在是40-50秒,而之前是3秒。
我已经通过使用以下 Controller 为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显示,使用ByteArrayContent小于1s时,使用StreamContent从服务器将单个1MB文件获取到笔记本电脑需要14秒。
还要注意,将完整的文件读入内存以表明唯一的区别是所使用的Content类。
奇怪的是,它似乎传输本身很慢。服务器快速/立即响应 header ,但是数据要花很长时间才能到达,如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自托管问题的解决方案是StreamContent缓冲区大小。 StreamContent的默认构造函数使用默认值0x1000、4Kb。在千兆网络上,以〜60Kb/s的速度完成大约26分钟的26Mb文件传输。
const int BufferSize = 1024 * 1024;
responseMessage = new HttpResponseMessage();
responseMessage.Content = new StreamContent(fileStream, BufferSize);
现在将bufferSize修改为1Mb只需几秒钟即可完成下载。
[编辑]在StreamContent SerializeToStreamAsync中执行StreamToStreamCopy,根据this link,性能会有所不同。合适的值可能是80K。
关于c# - ASP.NET Web API 2-StreamContent非常慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32992081/