From e26f9e0d0f20b3d6f22e1d2fcc9f00e70d50dd10 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 10 Feb 2019 00:05:23 +0000 Subject: [PATCH 1/2] Use C#7.3's ReadOnlySpan optimization for static data --- .../src/Internal/Http/Http1OutputProducer.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs index 297d79d13ee6..9df8a1cbdbef 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs @@ -5,7 +5,6 @@ using System.Buffers; using System.Diagnostics; using System.IO.Pipelines; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; @@ -16,10 +15,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { public class Http1OutputProducer : IHttpOutputProducer, IHttpOutputAborter, IDisposable { - private static readonly ReadOnlyMemory _continueBytes = new ReadOnlyMemory(Encoding.ASCII.GetBytes("HTTP/1.1 100 Continue\r\n\r\n")); - private static readonly byte[] _bytesHttpVersion11 = Encoding.ASCII.GetBytes("HTTP/1.1 "); - private static readonly byte[] _bytesEndHeaders = Encoding.ASCII.GetBytes("\r\n\r\n"); - private static readonly ReadOnlyMemory _endChunkedResponseBytes = new ReadOnlyMemory(Encoding.ASCII.GetBytes("0\r\n\r\n")); + // Use C#7.3's ReadOnlySpan optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ + private static ReadOnlySpan ContinueBytes => new byte[] { (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'1', (byte)'.', (byte)'1', (byte)' ', (byte)'1', (byte)'0', (byte)'0', (byte)' ', (byte)'C', (byte)'o', (byte)'n', (byte)'t', (byte)'i', (byte)'n', (byte)'u', (byte)'e', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + private static ReadOnlySpan HttpVersion11Bytes => new byte[] { (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'1', (byte)'.', (byte)'1', (byte)' ' }; + private static ReadOnlySpan EndHeadersBytes => new byte[] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + private static ReadOnlySpan EndChunkedResponseBytes => new byte[] { (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; private readonly string _connectionId; private readonly ConnectionContext _connectionContext; @@ -91,7 +91,7 @@ public ValueTask WriteDataToPipeAsync(ReadOnlySpan buffer, Ca public ValueTask WriteStreamSuffixAsync() { - return WriteAsync(_endChunkedResponseBytes.Span); + return WriteAsync(EndChunkedResponseBytes); } public ValueTask FlushAsync(CancellationToken cancellationToken = default) @@ -213,11 +213,11 @@ public void WriteResponseHeaders(int statusCode, string reasonPhrase, HttpRespon var buffer = _pipeWriter; var writer = new BufferWriter(buffer); - writer.Write(_bytesHttpVersion11); + writer.Write(HttpVersion11Bytes); var statusBytes = ReasonPhrases.ToStatusBytes(statusCode, reasonPhrase); writer.Write(statusBytes); responseHeaders.CopyTo(ref writer); - writer.Write(_bytesEndHeaders); + writer.Write(EndHeadersBytes); writer.Commit(); @@ -279,7 +279,7 @@ public void Complete() public ValueTask Write100ContinueAsync() { - return WriteAsync(_continueBytes.Span); + return WriteAsync(ContinueBytes); } private ValueTask WriteAsync( From 60561ce9b6241e497f0e57cade2216eacbb4239d Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 11 Feb 2019 00:58:43 +0000 Subject: [PATCH 2/2] Add text in comment --- .../Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs index 9df8a1cbdbef..fcc733143f14 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs @@ -16,9 +16,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http public class Http1OutputProducer : IHttpOutputProducer, IHttpOutputAborter, IDisposable { // Use C#7.3's ReadOnlySpan optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ + // "HTTP/1.1 100 Continue\r\n\r\n" private static ReadOnlySpan ContinueBytes => new byte[] { (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'1', (byte)'.', (byte)'1', (byte)' ', (byte)'1', (byte)'0', (byte)'0', (byte)' ', (byte)'C', (byte)'o', (byte)'n', (byte)'t', (byte)'i', (byte)'n', (byte)'u', (byte)'e', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + // "HTTP/1.1 " private static ReadOnlySpan HttpVersion11Bytes => new byte[] { (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'1', (byte)'.', (byte)'1', (byte)' ' }; + // "\r\n\r\n" private static ReadOnlySpan EndHeadersBytes => new byte[] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + // "0\r\n\r\n" private static ReadOnlySpan EndChunkedResponseBytes => new byte[] { (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; private readonly string _connectionId;