-
Notifications
You must be signed in to change notification settings - Fork 514
Consume body without allocating or reading #335
Changes from all commits
f7bdc5a
f48e6ba
f089abd
1589b54
ecc4395
7691a7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -232,10 +232,8 @@ public async Task RequestProcessingAsync() | |
|
|
||
| await ProduceEnd(); | ||
|
|
||
| while (await RequestBody.ReadAsync(_nullBuffer, 0, _nullBuffer.Length) != 0) | ||
| { | ||
| // Finish reading the request body in case the app did not. | ||
| } | ||
| // Finish reading the request body in case the app did not. | ||
| await MessageBody.Consume(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💃 |
||
| } | ||
|
|
||
| terminated = !_keepAlive; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,37 @@ protected MessageBody(FrameContext context) | |
| return result; | ||
| } | ||
|
|
||
| public async Task Consume(CancellationToken cancellationToken = default(CancellationToken)) | ||
| { | ||
| Task<int> result; | ||
| var send100checked = false; | ||
| do | ||
| { | ||
| result = ReadAsyncImplementation(default(ArraySegment<byte>), cancellationToken); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not await here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was copying the function above. Following the logic of that function; the task hasn't completed because no data; check whether their is no data because the client is waiting for a Since we are doing the full loop here; if we pass over that condition; we know the task has already completed. If the result is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also |
||
| if (!result.IsCompleted) | ||
| { | ||
| if (!send100checked) | ||
| { | ||
| if (Interlocked.Exchange(ref _send100Continue, 0) == 1) | ||
| { | ||
| _context.FrameControl.ProduceContinue(); | ||
| } | ||
| send100checked = true; | ||
| } | ||
| } | ||
| else if (result.GetAwaiter().GetResult() == 0) | ||
| { | ||
| // Completed Task, end of stream | ||
| return; | ||
| } | ||
| else | ||
| { | ||
| // Completed Task, get next Task rather than await | ||
| continue; | ||
| } | ||
| } while (await result != 0); | ||
| } | ||
|
|
||
| public abstract Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken); | ||
|
|
||
| public static MessageBody For( | ||
|
|
@@ -108,7 +139,7 @@ public ForRemainingData(FrameContext context) | |
|
|
||
| public override Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken) | ||
| { | ||
| return _context.SocketInput.ReadAsync(buffer); | ||
| return _context.SocketInput.ReadAsync(buffer.Array, buffer.Offset, buffer.Array == null ? 8192 : buffer.Count); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -129,14 +160,13 @@ public override async Task<int> ReadAsyncImplementation(ArraySegment<byte> buffe | |
| { | ||
| var input = _context.SocketInput; | ||
|
|
||
| var limit = Math.Min(buffer.Count, _inputLength); | ||
| var limit = buffer.Array == null ? _inputLength : Math.Min(buffer.Count, _inputLength); | ||
| if (limit == 0) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| var limitedBuffer = new ArraySegment<byte>(buffer.Array, buffer.Offset, limit); | ||
| var actual = await _context.SocketInput.ReadAsync(limitedBuffer); | ||
| var actual = await _context.SocketInput.ReadAsync(buffer.Array, buffer.Offset, limit); | ||
| _inputLength -= actual; | ||
|
|
||
| if (actual == 0) | ||
|
|
@@ -189,7 +219,7 @@ public override async Task<int> ReadAsyncImplementation(ArraySegment<byte> buffe | |
| } | ||
| while (_mode == Mode.ChunkData) | ||
| { | ||
| var limit = Math.Min(buffer.Count, _inputLength); | ||
| var limit = buffer.Array == null ? _inputLength : Math.Min(buffer.Count, _inputLength); | ||
| if (limit != 0) | ||
| { | ||
| await input; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth just overloading this on
SocketInput? Notice a bunch of other methods here create an array segment to call this method.At least least, you could clean all of those up to avoid creating the
ArraySegmentThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't create an
ArraySegementwith a null buffer + specified length or it will throw an exception.However a consumption limit needs to be passed through to
CopyToelse it will consume the whole input rather than just the input related to the current request. Is a bit of abstraction leakiness to make the code reusable; rather than copy paste repeated...