diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/MemoryPoolIterator.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/MemoryPoolIterator.cs
index 78f782d39e..f562c9ae02 100644
--- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/MemoryPoolIterator.cs
+++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/MemoryPoolIterator.cs
@@ -60,6 +60,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
}
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
private bool IsEndMultiBlock()
{
var block = _block.Next;
@@ -95,14 +96,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return block.Array[index];
}
- return TakeMultiBlock(block, index);
+ return TakeMultiBlock();
}
- private int TakeMultiBlock(MemoryPoolBlock block, int index)
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int TakeMultiBlock()
{
+ var block = _block;
var wasLastBlock = block.Next == null;
do
{
+ int index;
if (wasLastBlock)
{
return -1;
@@ -143,13 +147,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
SkipMultiBlock(bytesToSkip, following);
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
private void SkipMultiBlock(int bytesToSkip, int following)
{
var wasLastBlock = _block.Next == null;
var block = _block;
- var index = _index;
while (true)
{
+ int index;
if (wasLastBlock)
{
throw new InvalidOperationException("Attempted to skip more bytes than available.");
@@ -189,14 +194,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return block.Array[index];
}
- return PeekMultiBlock(block, index);
+ return PeekMultiBlock();
}
- private static int PeekMultiBlock(MemoryPoolBlock block, int index)
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int PeekMultiBlock()
{
+ var block = _block;
var wasLastBlock = block.Next == null;
do
{
+ int index;
if (wasLastBlock)
{
return -1;
@@ -238,6 +246,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return TryPeekLongMultiBlock(ref longValue, blockBytes);
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
private unsafe bool TryPeekLongMultiBlock(ref ulong longValue, int blockBytes)
{
var wasLastBlock = _block.Next == null;
@@ -780,6 +789,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
///
/// The byte to be saved.
/// true if the operation successes. false if can't find available space.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Put(byte data)
{
if (_block == null)
@@ -789,18 +799,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
var block = _block;
var index = _index;
- while (true)
- {
- var wasLastBlock = block.Next == null;
- if (index < block.End)
- {
- _block = block;
- _index = index + 1;
- block.Array[index] = data;
- return true;
- }
- else if (wasLastBlock)
+ if (index < block.End)
+ {
+ _index = index + 1;
+ block.Array[index] = data;
+ return true;
+ }
+
+ return PutMultiBlock(data);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private bool PutMultiBlock(byte data)
+ {
+ var block = _block;
+ var wasLastBlock = block.Next == null;
+ do
+ {
+ int index;
+ if (wasLastBlock)
{
return false;
}
@@ -809,7 +827,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
block = block.Next;
index = block.Start;
}
- }
+
+ wasLastBlock = block.Next == null;
+
+ if (index < block.End)
+ {
+ _block = block;
+ _index = index + 1;
+ block.Array[index] = data;
+ break;
+ }
+ } while (true);
+
+ return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -825,10 +855,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return end._index - _index;
}
- return GetLengthMultiBlock(end);
+ return GetLengthMultiBlock(ref end);
}
- public int GetLengthMultiBlock(MemoryPoolIterator end)
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public int GetLengthMultiBlock(ref MemoryPoolIterator end)
{
var block = _block;
var index = _index;
@@ -1179,6 +1210,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return GetArraySegmentMultiBlock(ref end);
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
private ArraySegment GetArraySegmentMultiBlock(ref MemoryPoolIterator end)
{
var length = GetLength(end);