Return last block from SocketInput when data is fully consumed

- This reduces Kestrel's memory usage for idle connections.
This commit is contained in:
Stephen Halter 2016-08-09 14:49:03 -07:00
parent 375e8b7022
commit 0edf36bd21
1 changed files with 40 additions and 21 deletions

View File

@ -52,6 +52,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
}
public MemoryPoolBlock IncomingStart()
{
lock (_sync)
{
const int minimumSize = 2048;
@ -66,6 +68,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
return _pinned;
}
}
public void IncomingComplete(int count, Exception error)
{
@ -112,6 +115,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
{
Debug.Assert(_pinned != null);
lock (_sync)
{
if (_pinned != null)
{
if (_pinned != _tail)
@ -122,6 +127,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
_pinned = null;
}
}
}
private void Complete()
{
@ -172,18 +178,31 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
}
returnStart = _head;
var consumedAll = !consumed.IsDefault && consumed.IsEnd;
if (consumedAll && _pinned != _tail)
{
// Everything has been consumed and no data is being written to the
// _tail block, so return all blocks between _head and _tail inclusive.
returnEnd = null;
_head = null;
_tail = null;
}
else
{
returnEnd = consumed.Block;
_head = consumed.Block;
_head.Start = consumed.Index;
}
// Must call Subtract() after _head has been advanced, to avoid producer starting too early and growing
// buffer beyond max length.
_bufferSizeControl?.Subtract(lengthConsumed);
}
if (!examined.IsDefault &&
examined.IsEnd &&
ReadingInput)
// If _head is null, everything has been consumed and examined.
var examinedAll = (!examined.IsDefault && examined.IsEnd) || _head == null;
if (examinedAll && ReadingInput)
{
_manualResetEvent.Reset();