MemoryPoolIterator fast paths

This commit is contained in:
Ben Adams 2016-11-09 09:57:59 -08:00
parent 8bcbfb9971
commit 53f361160e
1 changed files with 57 additions and 15 deletions

View File

@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
public bool IsEnd public bool IsEnd
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get get
{ {
if (_block == null) if (_block == null)
@ -51,24 +52,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
else else
{ {
var block = _block.Next; return IsEndMultiBlock();
while (block != null)
{
if (block.Start < block.End)
{
return false; // subsequent block has data - IsEnd is false
}
block = block.Next;
}
return true;
} }
} }
} }
private bool IsEndMultiBlock()
{
var block = _block.Next;
while (block != null)
{
if (block.Start < block.End)
{
return false; // subsequent block has data - IsEnd is false
}
block = block.Next;
}
return true;
}
public MemoryPoolBlock Block => _block; public MemoryPoolBlock Block => _block;
public int Index => _index; public int Index => _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Take() public int Take()
{ {
var block = _block; var block = _block;
@ -78,7 +85,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
var index = _index; var index = _index;
var wasLastBlock = block.Next == null;
if (index < block.End) if (index < block.End)
{ {
@ -86,6 +92,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return block.Array[index]; return block.Array[index];
} }
return TakeMultiBlock(block, index);
}
private int TakeMultiBlock(MemoryPoolBlock block, int index)
{
var wasLastBlock = block.Next == null;
do do
{ {
if (wasLastBlock) if (wasLastBlock)
@ -109,6 +121,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} while (true); } while (true);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Skip(int bytesToSkip) public void Skip(int bytesToSkip)
{ {
if (_block == null) if (_block == null)
@ -116,7 +129,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return; return;
} }
var wasLastBlock = _block.Next == null;
var following = _block.End - _index; var following = _block.End - _index;
if (following >= bytesToSkip) if (following >= bytesToSkip)
@ -125,6 +137,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return; return;
} }
SkipMultiBlock(bytesToSkip, following);
}
private void SkipMultiBlock(int bytesToSkip, int following)
{
var wasLastBlock = _block.Next == null;
var block = _block; var block = _block;
var index = _index; var index = _index;
while (true) while (true)
@ -152,6 +170,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Peek() public int Peek()
{ {
var block = _block; var block = _block;
@ -160,7 +179,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return -1; return -1;
} }
var wasLastBlock = _block.Next == null;
var index = _index; var index = _index;
if (index < block.End) if (index < block.End)
@ -168,6 +186,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return block.Array[index]; return block.Array[index];
} }
return PeekMultiBlock(block, index);
}
private static int PeekMultiBlock(MemoryPoolBlock block, int index)
{
var wasLastBlock = block.Next == null;
do do
{ {
if (wasLastBlock) if (wasLastBlock)
@ -190,6 +214,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
// NOTE: Little-endian only! // NOTE: Little-endian only!
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe bool TryPeekLong(out ulong longValue) public unsafe bool TryPeekLong(out ulong longValue)
{ {
longValue = 0; longValue = 0;
@ -199,7 +224,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return false; return false;
} }
var wasLastBlock = _block.Next == null;
var blockBytes = _block.End - _index; var blockBytes = _block.End - _index;
if (blockBytes >= sizeof(ulong)) if (blockBytes >= sizeof(ulong))
@ -207,7 +231,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
longValue = *(ulong*)(_block.DataFixedPtr + _index); longValue = *(ulong*)(_block.DataFixedPtr + _index);
return true; return true;
} }
else if (wasLastBlock)
return TryPeekLongMultiBlock(ref longValue, blockBytes);
}
private unsafe bool TryPeekLongMultiBlock(ref ulong longValue, int blockBytes)
{
var wasLastBlock = _block.Next == null;
if (wasLastBlock)
{ {
return false; return false;
} }
@ -778,6 +809,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetLength(MemoryPoolIterator end) public int GetLength(MemoryPoolIterator end)
{ {
if (IsDefault || end.IsDefault) if (IsDefault || end.IsDefault)
@ -785,6 +817,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return -1; return -1;
} }
if (_block == end._block)
{
return end._index - _index;
}
return GetLengthMultiBlock(end);
}
public int GetLengthMultiBlock(MemoryPoolIterator end)
{
var block = _block; var block = _block;
var index = _index; var index = _index;
var length = 0; var length = 0;