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.
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))
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;
== TIMING INFO ============
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 15ms
HTTPS Handshake: 0ms
Overall Elapsed: 0:00:16.233
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);
Modifying the bufferSize to 1Mb now take only seconds to complete the download.
[EDIT] In StreamContent SerializeToStreamAsync does a StreamToStreamCopy, according to this link the performance will differ. A suitable value is probably 80K.