-
Notifications
You must be signed in to change notification settings - Fork 523
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(); | ||
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); | ||
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? 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 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
ArraySegment
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.
Can't create an
ArraySegement
with a null buffer + specified length or it will throw an exception.However a consumption limit needs to be passed through to
CopyTo
else 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...