2015-10-07 20 views
10

Chúng tôi đã chuyển một dự án từ WCF sang Web API (SelfHost) và trong quá trình chúng tôi nhận thấy một sự chậm lại lớn khi phục vụ một ứng dụng web. Bây giờ 40-50 giây so với 3 giây trước đó.ASP.NET Web API 2 - StreamContent cực kỳ chậm

tôi đã tái tạo các vấn đề trong một ứng dụng giao diện điều khiển đơn giản bằng cách thêm pacakges NuGet khác nhau cho AspNet.WebApi và OwinSelfHost với bộ điều khiển sau:

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; 

Như bạn có thể nhìn thấy từ mã khác biệt duy nhất là việc sử dụng StreamContent (slooooow) vs ByteArrayContent.

Ứng dụng được lưu trữ trên máy Win10 và được truy cập từ máy tính xách tay của tôi. Fiddler cho thấy rằng phải mất 14 giây để có được một tệp 1MB duy nhất từ ​​máy chủ đến máy tính xách tay của tôi bằng cách sử dụng StreamContent trong khi ByteArrayContent nhỏ hơn 1s.

Cũng lưu ý rằng tệp hoàn chỉnh được đọc vào bộ nhớ để chỉ ra rằng sự khác biệt duy nhất là lớp Nội dung được sử dụng.

Điều kỳ lạ là dường như bản thân quá trình truyền của nó chậm. Các máy chủ đáp ứng với các tiêu đề một cách nhanh chóng/ngay lập tức, nhưng dữ liệu mất nhiều thời gian đến như thể hiện bởi Fiddler thông tin thời gian:

GotResponseHeaders: 07:50:52.800 
ServerDoneResponse: 07:51:08.471 

Toàn bộ Thời gian Thông tin:

== 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 

Có ai biết những gì đang xảy trên mui xe có thể giải thích sự khác biệt trong hành vi?

+0

Xin chào, tôi đang gặp phải sự cố tương tự chính xác ở đây. bạn đã tìm thấy một giải pháp trong khi đó? – DanielG

+1

@DanielG: Tôi không sợ, nhưng tôi đã đăng một báo cáo lỗi tại đây: https://connect.microsoft.com/VisualStudio/feedback/details/1932717/asp-net-bug-issue. Nó sẽ là tốt nếu bạn bỏ phiếu trên nó và cũng nhấp vào liên kết "Tôi có thể quá" (bên cạnh Repros). – TommyN

+0

Ok, sẽ làm điều đó. Một câu hỏi: Tại sao bạn không chỉ sử dụng ByteArrayContent nếu bạn có dữ liệu đã có trong bộ nhớ? – DanielG

Trả lời

14

Giải pháp cho vấn đề của tôi đối với lưu trữ tự OWIN là kích thước bộ đệm StreamContent. Phương thức khởi tạo mặc định của StreamContent sử dụng giá trị mặc định là 0x1000, 4Kb. Trên mạng gigabit, việc truyền tệp 26Mb mất ~ 7 phút để hoàn thành với tốc độ ~ 60Kb/s.

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

Sửa đổi bộ đệmSize thành 1Mb bây giờ chỉ mất vài giây để hoàn tất quá trình tải xuống.

[EDIT] Trong StreamContent SerializeToStreamAsync có một StreamToStreamCopy, theo this link hiệu suất sẽ khác nhau. Giá trị phù hợp có thể là 80K.

0

Khi bạn tuân thủ các dự án, hãy thử thay đổi từ gỡ lỗi sang bản phát hành. đó là cảnh quay loong bởi sẽ làm tăng hiệu suất một chút.

+1

Không có sự khác biệt tôi sợ. – TommyN

3

Tôi đang đối mặt với cùng một vấn đề ở đây và tôi nghĩ nó liên quan đến việc lưu trữ Owin. Tôi vừa tạo ra một ứng dụng mẫu Asp.net và lưu trữ nó trên IIS. Trong trường hợp đó, nó hoạt động như mong đợi.

Các kết quả trên Testsystem của tôi trong khi tải một file 80 MB:

  • với Streamcontent và SelfHosting: ~ 20 phút
  • với ByteArrayContent và Selfhosting: < 30 giây
  • với Streamcontent và IIS Hosting: < 30 giây

Hoặc có cài đặt cấu hình trong ASP.net mà tôi thiếu trong chuyên gia tự lưu trữ của tôi ject, hoặc có một lỗi trong mã tự lưu trữ nợ tôi đoán.

Các vấn đề liên quan