From da0831712d2c3601d40a780643196ba2cbd78fc1 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 27 Feb 2020 11:49:06 +0100 Subject: [PATCH 1/6] Add SocketTransportOption to enable/disable WaitForData --- .../src/Client/SocketConnectionFactory.cs | 3 ++- .../src/Internal/SocketConnection.cs | 12 +++++++++--- .../src/SocketConnectionListener.cs | 3 ++- .../Transport.Sockets/src/SocketTransportOptions.cs | 8 ++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Servers/Kestrel/Transport.Sockets/src/Client/SocketConnectionFactory.cs b/src/Servers/Kestrel/Transport.Sockets/src/Client/SocketConnectionFactory.cs index dc860eb8f548..6f95d242a591 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/Client/SocketConnectionFactory.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/Client/SocketConnectionFactory.cs @@ -62,7 +62,8 @@ public async ValueTask ConnectAsync(EndPoint endpoint, Cancel PipeScheduler.ThreadPool, _trace, _options.MaxReadBufferSize, - _options.MaxWriteBufferSize); + _options.MaxWriteBufferSize, + _options.WaitForDataBeforeAllocatingBuffer); socketConnection.Start(); return socketConnection; diff --git a/src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs b/src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs index 807473945403..4088dab97871 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs @@ -33,13 +33,15 @@ internal sealed class SocketConnection : TransportConnection private Task _processingTask; private readonly TaskCompletionSource _waitForConnectionClosedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); private bool _connectionClosed; + private readonly bool _waitForData; internal SocketConnection(Socket socket, MemoryPool memoryPool, PipeScheduler scheduler, ISocketsTrace trace, long? maxReadBufferSize = null, - long? maxWriteBufferSize = null) + long? maxWriteBufferSize = null, + bool waitForData = true) { Debug.Assert(socket != null); Debug.Assert(memoryPool != null); @@ -48,6 +50,7 @@ internal SocketConnection(Socket socket, _socket = socket; MemoryPool = memoryPool; _trace = trace; + _waitForData = waitForData; LocalEndPoint = _socket.LocalEndPoint; RemoteEndPoint = _socket.RemoteEndPoint; @@ -186,8 +189,11 @@ private async Task ProcessReceives() var input = Input; while (true) { - // Wait for data before allocating a buffer. - await _receiver.WaitForDataAsync(); + if (_waitForData) + { + // Wait for data before allocating a buffer. + await _receiver.WaitForDataAsync(); + } // Ensure we have some reasonable amount of buffer space var buffer = input.GetMemory(MinAllocBufferSize); diff --git a/src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionListener.cs b/src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionListener.cs index f829ae5591d7..4c49a9023333 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionListener.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionListener.cs @@ -112,7 +112,8 @@ public async ValueTask AcceptAsync(CancellationToken cancella acceptSocket.NoDelay = _options.NoDelay; } - var connection = new SocketConnection(acceptSocket, _memoryPool, _schedulers[_schedulerIndex], _trace, _options.MaxReadBufferSize, _options.MaxWriteBufferSize); + var connection = new SocketConnection(acceptSocket, _memoryPool, _schedulers[_schedulerIndex], _trace, + _options.MaxReadBufferSize, _options.MaxWriteBufferSize, _options.WaitForDataBeforeAllocatingBuffer); connection.Start(); diff --git a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs index 424a4375ae8a..99628f744a96 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs @@ -16,6 +16,14 @@ public class SocketTransportOptions /// public int IOQueueCount { get; set; } = Math.Min(Environment.ProcessorCount, 16); + /// + /// Wait until there is data available to allocate a buffer. Set this to true to reduce memory used for idle connections. + /// + /// + /// Defaults to true. + /// + public bool WaitForDataBeforeAllocatingBuffer = true; + /// /// Set to false to enable Nagle's algorithm for all connections. /// From ac2db64d94329ace5caa8bc903dabbab34b60278 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 27 Feb 2020 16:54:28 +0100 Subject: [PATCH 2/6] make WaitForDataBeforeAllocatingBuffer a property Co-Authored-By: Adam Sitnik --- .../Kestrel/Transport.Sockets/src/SocketTransportOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs index 99628f744a96..73703bb046d5 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs @@ -22,7 +22,7 @@ public class SocketTransportOptions /// /// Defaults to true. /// - public bool WaitForDataBeforeAllocatingBuffer = true; + public bool WaitForDataBeforeAllocatingBuffer { get; set; } = true; /// /// Set to false to enable Nagle's algorithm for all connections. From d8812083d20f291e93a40e95bc533ff3651ab6cd Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 27 Feb 2020 18:40:57 +0100 Subject: [PATCH 3/6] Update comment --- .../Kestrel/Transport.Sockets/src/SocketTransportOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs index 73703bb046d5..957876ca5953 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs @@ -17,7 +17,7 @@ public class SocketTransportOptions public int IOQueueCount { get; set; } = Math.Min(Environment.ProcessorCount, 16); /// - /// Wait until there is data available to allocate a buffer. Set this to true to reduce memory used for idle connections. + /// Wait until there is data available to allocate a buffer. Setting this to false can increase throughput at the cost of increased memory usage. /// /// /// Defaults to true. From 556aff4f467698f94a8ecb317804f7dedffbb35d Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 27 Feb 2020 19:04:25 +0100 Subject: [PATCH 4/6] Update Reference Source --- ...oft.AspNetCore.Server.Kestrel.Transport.Sockets.netcoreapp.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Servers/Kestrel/Transport.Sockets/ref/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.netcoreapp.cs b/src/Servers/Kestrel/Transport.Sockets/ref/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.netcoreapp.cs index 622010aa631d..020e80124d33 100644 --- a/src/Servers/Kestrel/Transport.Sockets/ref/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.netcoreapp.cs +++ b/src/Servers/Kestrel/Transport.Sockets/ref/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.netcoreapp.cs @@ -31,5 +31,6 @@ public SocketTransportOptions() { } public long? MaxReadBufferSize { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public long? MaxWriteBufferSize { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool NoDelay { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public bool WaitForDataBeforeAllocatingBuffer { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } } From ab3e141683c4363ffb287c39d4c85c87b06f0aa7 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 27 Feb 2020 19:05:28 +0100 Subject: [PATCH 5/6] Change WaitForDataBeforeAllocatingBuffer default to false for benchmarking --- .../Kestrel/Transport.Sockets/src/SocketTransportOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs index 957876ca5953..efa370a6cf3f 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs @@ -22,7 +22,7 @@ public class SocketTransportOptions /// /// Defaults to true. /// - public bool WaitForDataBeforeAllocatingBuffer { get; set; } = true; + public bool WaitForDataBeforeAllocatingBuffer { get; set; } = false; /// /// Set to false to enable Nagle's algorithm for all connections. From 34ee3324fb4a8c8de4ebdee6a6c8ecdbe5891236 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 2 Mar 2020 09:56:37 +0100 Subject: [PATCH 6/6] Set default WaitForDataBeforeAllocatingBuffer --- .../Kestrel/Transport.Sockets/src/SocketTransportOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs index efa370a6cf3f..957876ca5953 100644 --- a/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs +++ b/src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs @@ -22,7 +22,7 @@ public class SocketTransportOptions /// /// Defaults to true. /// - public bool WaitForDataBeforeAllocatingBuffer { get; set; } = false; + public bool WaitForDataBeforeAllocatingBuffer { get; set; } = true; /// /// Set to false to enable Nagle's algorithm for all connections.