|
@@ -5,7 +5,6 @@ using System;
|
|
using System.Buffers.Text;
|
|
using System.Buffers.Text;
|
|
using System.IO.Pipelines;
|
|
using System.IO.Pipelines;
|
|
using System.Text.Json;
|
|
using System.Text.Json;
|
|
-using System.Text.Json.Serialization;
|
|
|
|
using System.Threading.Tasks;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
|
|
|
|
|
@@ -19,17 +18,23 @@ namespace PlatformBenchmarks
|
|
private readonly static AsciiString _crlf = "\r\n";
|
|
private readonly static AsciiString _crlf = "\r\n";
|
|
private readonly static AsciiString _eoh = "\r\n\r\n"; // End Of Headers
|
|
private readonly static AsciiString _eoh = "\r\n\r\n"; // End Of Headers
|
|
private readonly static AsciiString _http11OK = "HTTP/1.1 200 OK\r\n";
|
|
private readonly static AsciiString _http11OK = "HTTP/1.1 200 OK\r\n";
|
|
- private readonly static AsciiString _headerServer = "Server: Custom";
|
|
|
|
|
|
+ private readonly static AsciiString _headerServer = "Server: K";
|
|
private readonly static AsciiString _headerContentLength = "Content-Length: ";
|
|
private readonly static AsciiString _headerContentLength = "Content-Length: ";
|
|
- private readonly static AsciiString _headerContentLengthZero = "Content-Length: 0\r\n";
|
|
|
|
- private readonly static AsciiString _headerContentTypeText = "Content-Type: text/plain\r\n";
|
|
|
|
- private readonly static AsciiString _headerContentTypeJson = "Content-Type: application/json\r\n";
|
|
|
|
- private readonly static AsciiString _headerContentTypeHtml = "Content-Type: text/html; charset=UTF-8\r\n";
|
|
|
|
|
|
+ private readonly static AsciiString _headerContentLengthZero = "Content-Length: 0";
|
|
|
|
+ private readonly static AsciiString _headerContentTypeText = "Content-Type: text/plain";
|
|
|
|
+ private readonly static AsciiString _headerContentTypeJson = "Content-Type: application/json";
|
|
|
|
+ private readonly static AsciiString _headerContentTypeHtml = "Content-Type: text/html; charset=UTF-8";
|
|
|
|
+
|
|
|
|
+ private readonly static AsciiString _dbPreamble =
|
|
|
|
+ _http11OK +
|
|
|
|
+ _headerServer + _crlf +
|
|
|
|
+ _headerContentTypeJson + _crlf +
|
|
|
|
+ _headerContentLength;
|
|
|
|
|
|
private readonly static AsciiString _plainTextBody = "Hello, World!";
|
|
private readonly static AsciiString _plainTextBody = "Hello, World!";
|
|
|
|
|
|
private static readonly JsonSerializerOptions SerializerOptions = new JsonSerializerOptions();
|
|
private static readonly JsonSerializerOptions SerializerOptions = new JsonSerializerOptions();
|
|
-
|
|
|
|
|
|
+
|
|
private readonly static AsciiString _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
|
|
private readonly static AsciiString _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
|
|
private readonly static AsciiString _fortunesRowStart = "<tr><td>";
|
|
private readonly static AsciiString _fortunesRowStart = "<tr><td>";
|
|
private readonly static AsciiString _fortunesColumn = "</td><td>";
|
|
private readonly static AsciiString _fortunesColumn = "</td><td>";
|
|
@@ -42,38 +47,44 @@ namespace PlatformBenchmarks
|
|
public static class Paths
|
|
public static class Paths
|
|
{
|
|
{
|
|
public readonly static AsciiString SingleQuery = "/db";
|
|
public readonly static AsciiString SingleQuery = "/db";
|
|
- public readonly static AsciiString Json = "/json";
|
|
|
|
|
|
+ public readonly static AsciiString Json = "/j";
|
|
public readonly static AsciiString Fortunes = "/fortunes";
|
|
public readonly static AsciiString Fortunes = "/fortunes";
|
|
- public readonly static AsciiString Plaintext = "/plaintext";
|
|
|
|
|
|
+ public readonly static AsciiString Plaintext = "/p";
|
|
public readonly static AsciiString Updates = "/updates/queries=";
|
|
public readonly static AsciiString Updates = "/updates/queries=";
|
|
public readonly static AsciiString MultipleQueries = "/queries/queries=";
|
|
public readonly static AsciiString MultipleQueries = "/queries/queries=";
|
|
}
|
|
}
|
|
|
|
|
|
private RequestType _requestType;
|
|
private RequestType _requestType;
|
|
|
|
+#if DATABASE
|
|
private int _queries;
|
|
private int _queries;
|
|
-
|
|
|
|
|
|
+#endif
|
|
public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
|
|
public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
|
|
{
|
|
{
|
|
var requestType = RequestType.NotRecognized;
|
|
var requestType = RequestType.NotRecognized;
|
|
if (method == HttpMethod.Get)
|
|
if (method == HttpMethod.Get)
|
|
{
|
|
{
|
|
|
|
+#if !DATABASE
|
|
|
|
+ if (path.Length >= 2 && path[0] == '/')
|
|
|
|
+ {
|
|
|
|
+ if (path[1] == 'j')
|
|
|
|
+ {
|
|
|
|
+ requestType = RequestType.Json;
|
|
|
|
+ }
|
|
|
|
+ else if (path[1] == 'p')
|
|
|
|
+ {
|
|
|
|
+ requestType = RequestType.PlainText;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#else
|
|
var pathLength = path.Length;
|
|
var pathLength = path.Length;
|
|
if (Paths.SingleQuery.Length <= pathLength && path.StartsWith(Paths.SingleQuery))
|
|
if (Paths.SingleQuery.Length <= pathLength && path.StartsWith(Paths.SingleQuery))
|
|
{
|
|
{
|
|
requestType = RequestType.SingleQuery;
|
|
requestType = RequestType.SingleQuery;
|
|
}
|
|
}
|
|
- else if (Paths.Json.Length <= pathLength && path.StartsWith(Paths.Json))
|
|
|
|
- {
|
|
|
|
- requestType = RequestType.Json;
|
|
|
|
- }
|
|
|
|
else if (Paths.Fortunes.Length <= pathLength && path.StartsWith(Paths.Fortunes))
|
|
else if (Paths.Fortunes.Length <= pathLength && path.StartsWith(Paths.Fortunes))
|
|
{
|
|
{
|
|
requestType = RequestType.Fortunes;
|
|
requestType = RequestType.Fortunes;
|
|
}
|
|
}
|
|
- else if (Paths.Plaintext.Length <= pathLength && path.StartsWith(Paths.Plaintext))
|
|
|
|
- {
|
|
|
|
- requestType = RequestType.PlainText;
|
|
|
|
- }
|
|
|
|
else if (Paths.Updates.Length <= pathLength && path.StartsWith(Paths.Updates))
|
|
else if (Paths.Updates.Length <= pathLength && path.StartsWith(Paths.Updates))
|
|
{
|
|
{
|
|
_queries = ParseQueries(path, Paths.Updates.Length);
|
|
_queries = ParseQueries(path, Paths.Updates.Length);
|
|
@@ -84,11 +95,30 @@ namespace PlatformBenchmarks
|
|
_queries = ParseQueries(path, Paths.MultipleQueries.Length);
|
|
_queries = ParseQueries(path, Paths.MultipleQueries.Length);
|
|
requestType = RequestType.MultipleQueries;
|
|
requestType = RequestType.MultipleQueries;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
|
|
_requestType = requestType;
|
|
_requestType = requestType;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+#if !DATABASE
|
|
|
|
+ private void ProcessRequest(ref BufferWriter<WriterAdapter> writer)
|
|
|
|
+ {
|
|
|
|
+ if (_requestType == RequestType.PlainText)
|
|
|
|
+ {
|
|
|
|
+ PlainText(ref writer);
|
|
|
|
+ }
|
|
|
|
+ else if (_requestType == RequestType.Json)
|
|
|
|
+ {
|
|
|
|
+ Json(ref writer);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ Default(ref writer);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#else
|
|
private static int ParseQueries(Span<byte> path, int pathLength)
|
|
private static int ParseQueries(Span<byte> path, int pathLength)
|
|
{
|
|
{
|
|
if (!Utf8Parser.TryParse(path.Slice(pathLength), out int queries, out _) || queries < 1)
|
|
if (!Utf8Parser.TryParse(path.Slice(pathLength), out int queries, out _) || queries < 1)
|
|
@@ -103,19 +133,11 @@ namespace PlatformBenchmarks
|
|
return queries;
|
|
return queries;
|
|
}
|
|
}
|
|
|
|
|
|
- public Task ProcessRequestAsync()
|
|
|
|
|
|
+ private Task ProcessRequestAsync()
|
|
{
|
|
{
|
|
|
|
+ Task task;
|
|
var requestType = _requestType;
|
|
var requestType = _requestType;
|
|
- var task = Task.CompletedTask;
|
|
|
|
- if (requestType == RequestType.PlainText)
|
|
|
|
- {
|
|
|
|
- PlainText(Writer);
|
|
|
|
- }
|
|
|
|
- else if (requestType == RequestType.Json)
|
|
|
|
- {
|
|
|
|
- Json(Writer);
|
|
|
|
- }
|
|
|
|
- else if (requestType == RequestType.Fortunes)
|
|
|
|
|
|
+ if (requestType == RequestType.Fortunes)
|
|
{
|
|
{
|
|
task = Fortunes(Writer);
|
|
task = Fortunes(Writer);
|
|
}
|
|
}
|
|
@@ -134,6 +156,7 @@ namespace PlatformBenchmarks
|
|
else
|
|
else
|
|
{
|
|
{
|
|
Default(Writer);
|
|
Default(Writer);
|
|
|
|
+ task = Task.CompletedTask;
|
|
}
|
|
}
|
|
|
|
|
|
return task;
|
|
return task;
|
|
@@ -142,22 +165,22 @@ namespace PlatformBenchmarks
|
|
private static void Default(PipeWriter pipeWriter)
|
|
private static void Default(PipeWriter pipeWriter)
|
|
{
|
|
{
|
|
var writer = GetWriter(pipeWriter);
|
|
var writer = GetWriter(pipeWriter);
|
|
-
|
|
|
|
- // HTTP 1.1 OK
|
|
|
|
- writer.Write(_http11OK);
|
|
|
|
-
|
|
|
|
- // Server headers
|
|
|
|
- writer.Write(_headerServer);
|
|
|
|
|
|
+ Default(ref writer);
|
|
|
|
+ writer.Commit();
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+ private readonly static AsciiString _defaultPreamble =
|
|
|
|
+ _http11OK +
|
|
|
|
+ _headerServer + _crlf +
|
|
|
|
+ _headerContentTypeText + _crlf +
|
|
|
|
+ _headerContentLengthZero;
|
|
|
|
+
|
|
|
|
+ private static void Default(ref BufferWriter<WriterAdapter> writer)
|
|
|
|
+ {
|
|
|
|
+ writer.Write(_defaultPreamble);
|
|
|
|
|
|
// Date header
|
|
// Date header
|
|
writer.Write(DateHeader.HeaderBytes);
|
|
writer.Write(DateHeader.HeaderBytes);
|
|
-
|
|
|
|
- // Content-Length 0
|
|
|
|
- writer.Write(_headerContentLengthZero);
|
|
|
|
-
|
|
|
|
- // End of headers
|
|
|
|
- writer.Write(_crlf);
|
|
|
|
- writer.Commit();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private enum RequestType
|
|
private enum RequestType
|