diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPool2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPool2.cs
index 2ee01c0d10..86561516c6 100644
--- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPool2.cs
+++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPool2.cs
@@ -74,24 +74,21 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
slab: null);
}
- while (true)
+ MemoryPoolBlock2 block;
+ if (_blocks.TryPop(out block))
{
- MemoryPoolBlock2 block;
- if (_blocks.TryPop(out block))
- {
- // block successfully taken from the stack - return it
- return block;
- }
- // no blocks available - grow the pool and try again
- AllocateSlab();
+ // block successfully taken from the stack - return it
+ return block;
}
+ // no blocks available - grow the pool
+ return AllocateSlab();
}
///
/// Internal method called when a block is requested and the pool is empty. It allocates one additional slab, creates all of the
/// block tracking objects, and adds them all to the pool.
///
- private void AllocateSlab()
+ private MemoryPoolBlock2 AllocateSlab()
{
var slab = MemoryPoolSlab2.Create(_slabLength);
_slabs.Push(slab);
@@ -99,8 +96,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
var basePtr = slab.ArrayPtr;
var firstOffset = (int)((_blockStride - 1) - ((ulong)(basePtr + _blockStride - 1) % _blockStride));
- for (var offset = firstOffset;
- offset + _blockLength <= _slabLength;
+ var poolAllocationLength = _slabLength - _blockStride;
+
+ var offset = firstOffset;
+ for (;
+ offset + _blockLength < poolAllocationLength;
offset += _blockStride)
{
var block = MemoryPoolBlock2.Create(
@@ -110,6 +110,15 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
slab);
Return(block);
}
+
+ // return last block rather than adding to pool
+ var newBlock = MemoryPoolBlock2.Create(
+ new ArraySegment(slab.Array, offset, _blockLength),
+ basePtr,
+ this,
+ slab);
+
+ return newBlock;
}
///