Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit 85c4efa

Browse files
committed
Consume Faster
1 parent 874726b commit 85c4efa

File tree

2 files changed

+55
-28
lines changed

2 files changed

+55
-28
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
910
using Microsoft.Extensions.Primitives;
1011

1112
namespace Microsoft.AspNet.Server.Kestrel.Http
@@ -38,35 +39,40 @@ protected MessageBody(FrameContext context)
3839
return result;
3940
}
4041

41-
public async Task Consume(CancellationToken cancellationToken = default(CancellationToken))
42+
public Task Consume(CancellationToken cancellationToken = default(CancellationToken))
4243
{
43-
Task<int> result;
44-
var send100checked = false;
45-
do
44+
var result = ReadAsyncImplementation(default(ArraySegment<byte>), cancellationToken);
45+
if (!result.IsCompleted)
4646
{
47-
result = ReadAsyncImplementation(default(ArraySegment<byte>), cancellationToken);
48-
if (!result.IsCompleted)
49-
{
50-
if (!send100checked)
51-
{
52-
if (Interlocked.Exchange(ref _send100Continue, 0) == 1)
53-
{
54-
_context.FrameControl.ProduceContinue();
55-
}
56-
send100checked = true;
57-
}
58-
}
59-
else if (result.GetAwaiter().GetResult() == 0)
60-
{
61-
// Completed Task, end of stream
62-
return;
63-
}
64-
else
47+
if (Interlocked.Exchange(ref _send100Continue, 0) == 1)
6548
{
66-
// Completed Task, get next Task rather than await
67-
continue;
49+
_context.FrameControl.ProduceContinue();
6850
}
69-
} while (await result != 0);
51+
52+
return ConsumeAwaited(result, cancellationToken);
53+
}
54+
else if (result.GetAwaiter().GetResult() == 0)
55+
{
56+
// Completed Task, end of stream
57+
return TaskUtilities.CompletedTask;
58+
}
59+
else
60+
{
61+
// Completed Task, but non-zero get next Task and await
62+
return ConsumeAwaited(ReadAsyncImplementation(default(ArraySegment<byte>), cancellationToken), cancellationToken);
63+
}
64+
}
65+
66+
private async Task ConsumeAwaited(Task<int> currentTask, CancellationToken cancellationToken)
67+
{
68+
var count = await currentTask;
69+
70+
if (count == 0) return;
71+
72+
while (await ReadAsyncImplementation(default(ArraySegment<byte>), cancellationToken) != 0)
73+
{
74+
// Consume until complete
75+
}
7076
}
7177

7278
public abstract Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken);
@@ -156,17 +162,37 @@ public ForContentLength(bool keepAlive, int contentLength, FrameContext context)
156162
_inputLength = _contentLength;
157163
}
158164

159-
public override async Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken)
165+
public override Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken)
160166
{
161167
var input = _context.SocketInput;
162168

163169
var limit = buffer.Array == null ? _inputLength : Math.Min(buffer.Count, _inputLength);
164170
if (limit == 0)
165171
{
166-
return 0;
172+
return TaskUtilities.ZeroTask;
173+
}
174+
175+
var task = _context.SocketInput.ReadAsync(buffer.Array, buffer.Offset, limit);
176+
177+
if (task.IsCompleted)
178+
{
179+
var actual = task.GetAwaiter().GetResult();
180+
if (actual == 0)
181+
{
182+
throw new InvalidDataException("Unexpected end of request content");
183+
}
184+
_inputLength -= actual;
185+
return task;
167186
}
187+
else
188+
{
189+
return ReadAsyncImplementationAwaited(task);
190+
}
191+
}
168192

169-
var actual = await _context.SocketInput.ReadAsync(buffer.Array, buffer.Offset, limit);
193+
private async Task<int> ReadAsyncImplementationAwaited(Task<int> currentTask)
194+
{
195+
var actual = await currentTask;
170196
_inputLength -= actual;
171197

172198
if (actual == 0)

src/Microsoft.AspNet.Server.Kestrel/Infrastructure/TaskUtilities.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ public static class TaskUtilities
1212
#else
1313
public static Task CompletedTask = Task.FromResult<object>(null);
1414
#endif
15+
public static Task<int> ZeroTask = Task.FromResult(0);
1516
}
1617
}

0 commit comments

Comments
 (0)