Skip to content

Commit d1e9269

Browse files
authored
Platform benchmarks optimizations (#1470)
Create writer once per request, reduce the number of calls to .GetSpan and .Advance
1 parent 86bcea7 commit d1e9269

File tree

4 files changed

+43
-48
lines changed

4 files changed

+43
-48
lines changed

src/BenchmarksApps/Kestrel/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,41 +41,50 @@ private async Task ProcessRequestsAsync()
4141
{
4242
while (true)
4343
{
44-
var task = Reader.ReadAsync();
45-
46-
if (!task.IsCompleted)
44+
var readResult = await Reader.ReadAsync();
45+
46+
if (!HandleRequest(readResult))
4747
{
48-
// No more data in the input
49-
await OnReadCompletedAsync();
48+
return;
5049
}
5150

52-
var result = await task;
53-
var buffer = result.Buffer;
54-
while (true)
51+
await Writer.FlushAsync();
52+
}
53+
}
54+
55+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
56+
private bool HandleRequest(in ReadResult result)
57+
{
58+
var buffer = result.Buffer;
59+
var writer = GetWriter(Writer);
60+
61+
while (true)
62+
{
63+
if (!ParseHttpRequest(ref buffer, result.IsCompleted, out var examined))
5564
{
56-
if (!ParseHttpRequest(ref buffer, result.IsCompleted, out var examined))
57-
{
58-
return;
59-
}
65+
return false;
66+
}
6067

61-
if (_state == State.Body)
62-
{
63-
ProcessRequest();
68+
if (_state == State.Body)
69+
{
70+
ProcessRequest(ref writer);
6471

65-
_state = State.StartLine;
72+
_state = State.StartLine;
6673

67-
if (!buffer.IsEmpty)
68-
{
69-
// More input data to parse
70-
continue;
71-
}
74+
if (!buffer.IsEmpty)
75+
{
76+
// More input data to parse
77+
continue;
7278
}
73-
74-
// No more input or incomplete data, Advance the Reader
75-
Reader.AdvanceTo(buffer.Start, examined);
76-
break;
7779
}
80+
81+
// No more input or incomplete data, Advance the Reader
82+
Reader.AdvanceTo(buffer.Start, examined);
83+
break;
7884
}
85+
86+
writer.Commit();
87+
return true;
7988
}
8089

8190
private bool ParseHttpRequest(ref ReadOnlySequence<byte> buffer, bool isCompleted, out SequencePosition examined)
@@ -157,11 +166,6 @@ public void OnHeadersComplete()
157166
}
158167
#endif
159168

160-
public async ValueTask OnReadCompletedAsync()
161-
{
162-
await Writer.FlushAsync();
163-
}
164-
165169
private static void ThrowUnexpectedEndOfData()
166170
{
167171
throw new InvalidOperationException("Unexpected end of data!");

src/BenchmarksApps/Kestrel/PlatformBenchmarks/BenchmarkApplication.cs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,24 @@ public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> targe
5454
_requestType = requestType;
5555
}
5656

57-
public void ProcessRequest()
57+
private void ProcessRequest(ref BufferWriter<WriterAdapter> writer)
5858
{
5959
if (_requestType == RequestType.PlainText)
6060
{
61-
PlainText(Writer);
61+
PlainText(ref writer);
6262
}
6363
else if (_requestType == RequestType.Json)
6464
{
65-
Json(Writer);
65+
Json(ref writer);
6666
}
6767
else
6868
{
69-
Default(Writer);
69+
Default(ref writer);
7070
}
7171
}
7272

73-
private static void PlainText(PipeWriter pipeWriter)
73+
private static void PlainText(ref BufferWriter<WriterAdapter> writer)
7474
{
75-
var writer = GetWriter(pipeWriter);
76-
7775
// HTTP 1.1 OK
7876
writer.Write(_http11OK);
7977

@@ -95,13 +93,10 @@ private static void PlainText(PipeWriter pipeWriter)
9593

9694
// Body
9795
writer.Write(_plainTextBody);
98-
writer.Commit();
9996
}
10097

101-
private static void Json(PipeWriter pipeWriter)
98+
private static void Json(ref BufferWriter<WriterAdapter> writer)
10299
{
103-
var writer = GetWriter(pipeWriter);
104-
105100
// HTTP 1.1 OK
106101
writer.Write(_http11OK);
107102

@@ -124,13 +119,10 @@ private static void Json(PipeWriter pipeWriter)
124119

125120
// Body
126121
writer.Write(jsonPayload);
127-
writer.Commit();
128122
}
129123

130-
private static void Default(PipeWriter pipeWriter)
124+
private static void Default(ref BufferWriter<WriterAdapter> writer)
131125
{
132-
var writer = GetWriter(pipeWriter);
133-
134126
// HTTP 1.1 OK
135127
writer.Write(_http11OK);
136128

@@ -145,7 +137,6 @@ private static void Default(PipeWriter pipeWriter)
145137

146138
// End of headers
147139
writer.Write(_crlf);
148-
writer.Commit();
149140
}
150141

151142
private enum RequestType

src/BenchmarksApps/Kestrel/PlatformBenchmarks/BufferWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public BufferWriter(T output)
1717
{
1818
_buffered = 0;
1919
_output = output;
20-
_span = output.GetSpan();
20+
_span = output.GetSpan(sizeHint: 16 * 160);
2121
}
2222

2323
public Span<byte> Span => _span;

src/BenchmarksApps/Kestrel/PlatformBenchmarks/IHttpConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public interface IHttpConnection : IHttpHeadersHandler, IHttpRequestLineHandler
1111
{
1212
PipeReader Reader { get; set; }
1313
PipeWriter Writer { get; set; }
14+
1415
Task ExecuteAsync();
15-
ValueTask OnReadCompletedAsync();
1616
}
1717
}

0 commit comments

Comments
 (0)