Skip to content
This repository has been archived by the owner on Mar 19, 2019. It is now read-only.

New setting to enable Kernel response buffering #418

Closed
wants to merge 1 commit into from

Conversation

davidni
Copy link

@davidni davidni commented Nov 27, 2017

This PR introduces a new setting EnableKernelResponseBuffering that causes the ResponseStream to pass the HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA flag to Http.sys as appropriate when sending responses.

Non-scientific benchmarks show dramatic perf wins when the response stream is written to in small amounts at a time (e.g. as done by aspnet/proxy), especially for networks with long round trip times.

After this change, I can get consistently more than 18 MB/s when serving static files through a proxy (similar to aspnet/proxy), hosted on an Azure A4 VM.

@davidni
Copy link
Author

davidni commented Nov 27, 2017

Items to discuss:

  • Should this be configurable on a per-response basis? Right now it's a global flag and I'm not sure what a good way would be to expose this otherwise.
  • I made the change against 1.1.4 since this is what I'm currently using on my test project. I'm currently unable to try this on ASP.NET Core 2.
  • I'm not convinced the tests I added are exercising this enough. While they are both passing and simulating things E2E (I think), I'm open for suggestions on how to improve test coverage.

@Tratcher Tratcher self-requested a review November 27, 2017 17:49
Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this PR to the dev branch.

Writing functional tests for this is going to be hard as there's no behavioral difference, at best we turn it on and make sure nothing breaks. At least verify the four major code paths: Write, WriteAsync, BeginWrite, and SendFileAsync.

@@ -61,6 +61,15 @@ public ILogger Logger
/// </summary>
public bool ThrowWriteExceptions { get; set; }

/// <summary>
/// Gets or sets a value that indicates whether to enable buffering of data in the kernel on a per-response basis.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enable buffering of response data in the kernel.

/// Gets or sets a value that indicates whether to enable buffering of data in the kernel on a per-response basis.
/// It should be used by an application doing synchronous I/O or by an application doing asynchronous I/O with
/// no more than one outstanding send at a time.
/// Applications that use asynchronous I/O and that may have more than one send outstanding at a time should not use this flag.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one outstanding write

/// It should be used by an application doing synchronous I/O or by an application doing asynchronous I/O with
/// no more than one outstanding send at a time.
/// Applications that use asynchronous I/O and that may have more than one send outstanding at a time should not use this flag.
/// Enabling this can results in higher CPU and memory usage by Http.Sys.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and improve throughput over high latency connections

@Tratcher
Copy link
Member

As for configuring this on a per response basis, we have ways of doing that but I don't see an immediate need for it.

@Tratcher
Copy link
Member

Does Http.Sys have any auto-flush behavior when buffering? E.g. if I enable buffering, write 5 bytes and then wait, will those bytes eventually be flushed on their own? Or only when I write more and fill the buffer?

If not then this could break SignalR. Wasn't this flag already in use for WebSockets?

@dnfclas
Copy link

dnfclas commented Dec 4, 2017

CLA assistant check
All CLA requirements met.

@davidni davidni changed the base branch from rel/1.1.4 to dev December 4, 2017 09:21
@davidni
Copy link
Author

davidni commented Dec 4, 2017

Does Http.Sys have any auto-flush behavior when buffering?

Surely seems that way, because I see bytes flowing to the client before the final Write happens on the server. Also, since this is still disabled by default, it wouldn't break any scenarios unless someone opts in for this.

@Tratcher
Copy link
Member

Tratcher commented Dec 4, 2017

I meant does the buffer get auto-flushed if you pause writing in the middle? If not then we may need to make this a per-request feature so SignalR can disable it.

@Tratcher Tratcher added this to the 2.1.0-preview2 milestone Mar 7, 2018
@Tratcher
Copy link
Member

Sorry this got put on hold so long. A change like this needs benchmarks, wider functional testing, etc. and we don't have bandwidth to follow through on those right now. Closing this for now and using https://github.com/aspnet/HttpSysServer/issues/41 to track future work here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants