Remove noop pin+unpin w/ memory blocks
+ Only use pooled blocks in tests
This commit is contained in:
parent
a31d847719
commit
2aa10a64a2
|
|
@ -253,7 +253,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
var result = _rawSocketInput.IncomingStart();
|
var result = _rawSocketInput.IncomingStart();
|
||||||
|
|
||||||
return handle.Libuv.buf_init(
|
return handle.Libuv.buf_init(
|
||||||
result.Pin() + result.End,
|
result.DataArrayPtr + result.End,
|
||||||
result.Data.Offset + result.Data.Count - result.End);
|
result.Data.Offset + result.Data.Count - result.End);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -684,14 +684,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
var end = _lockedEnd.Block;
|
var end = _lockedEnd.Block;
|
||||||
if (block == end)
|
if (block == end)
|
||||||
{
|
{
|
||||||
end.Unpin();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (block.Next != end)
|
while (block.Next != end)
|
||||||
{
|
{
|
||||||
block = block.Next;
|
block = block.Next;
|
||||||
block.Unpin();
|
|
||||||
}
|
}
|
||||||
block.Next = null;
|
block.Next = null;
|
||||||
|
|
||||||
|
|
@ -705,7 +703,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
var returnBlock = block;
|
var returnBlock = block;
|
||||||
block = block.Next;
|
block = block.Next;
|
||||||
|
|
||||||
returnBlock.Unpin();
|
|
||||||
returnBlock.Pool.Return(returnBlock);
|
returnBlock.Pool.Return(returnBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,24 +63,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called to take a block from the pool.
|
/// Called to take a block from the pool.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="minimumSize">The block returned must be at least this size. It may be larger than this minimum size, and if so,
|
|
||||||
/// the caller may write to the block's entire size rather than being limited to the minumumSize requested.</param>
|
|
||||||
/// <returns>The block that is reserved for the called. It must be passed to Return when it is no longer being used.</returns>
|
/// <returns>The block that is reserved for the called. It must be passed to Return when it is no longer being used.</returns>
|
||||||
public MemoryPoolBlock Lease(int minimumSize = MaxPooledBlockLength)
|
public MemoryPoolBlock Lease()
|
||||||
{
|
{
|
||||||
if (minimumSize > _blockLength)
|
|
||||||
{
|
|
||||||
// The requested minimumSize is actually larger then the usable memory of a single block.
|
|
||||||
// Because this is the degenerate case, a one-time-use byte[] array and tracking object are allocated.
|
|
||||||
// When this block tracking object is returned it is not added to the pool - instead it will be
|
|
||||||
// allowed to be garbage collected normally.
|
|
||||||
return MemoryPoolBlock.Create(
|
|
||||||
new ArraySegment<byte>(new byte[minimumSize]),
|
|
||||||
dataPtr: IntPtr.Zero,
|
|
||||||
pool: this,
|
|
||||||
slab: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPoolBlock block;
|
MemoryPoolBlock block;
|
||||||
if (_blocks.TryDequeue(out block))
|
if (_blocks.TryDequeue(out block))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MemoryPoolBlock
|
public class MemoryPoolBlock
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// If this block represents a one-time-use memory object, this GCHandle will hold that memory object at a fixed address
|
|
||||||
/// so it can be used in native operations.
|
|
||||||
/// </summary>
|
|
||||||
private GCHandle _pinHandle;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Native address of the first byte of this block's Data memory. It is null for one-time-use memory, or copied from
|
/// Native address of the first byte of this block's Data memory. It is null for one-time-use memory, or copied from
|
||||||
/// the Slab's ArrayPtr for a slab-block segment. The byte it points to corresponds to Data.Array[0], and in practice you will always
|
/// the Slab's ArrayPtr for a slab-block segment. The byte it points to corresponds to Data.Array[0], and in practice you will always
|
||||||
/// use the _dataArrayPtr + Start or _dataArrayPtr + End, which point to the start of "active" bytes, or point to just after the "active" bytes.
|
/// use the DataArrayPtr + Start or DataArrayPtr + End, which point to the start of "active" bytes, or point to just after the "active" bytes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IntPtr _dataArrayPtr;
|
public readonly IntPtr DataArrayPtr;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The array segment describing the range of memory this block is tracking. The caller which has leased this block may only read and
|
/// The array segment describing the range of memory this block is tracking. The caller which has leased this block may only read and
|
||||||
|
|
@ -33,8 +27,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This object cannot be instantiated outside of the static Create method
|
/// This object cannot be instantiated outside of the static Create method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected MemoryPoolBlock()
|
protected MemoryPoolBlock(IntPtr dataArrayPtr)
|
||||||
{
|
{
|
||||||
|
DataArrayPtr = dataArrayPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -76,20 +71,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
|
||||||
|
|
||||||
~MemoryPoolBlock()
|
~MemoryPoolBlock()
|
||||||
{
|
{
|
||||||
Debug.Assert(!_pinHandle.IsAllocated, "Ad-hoc memory block wasn't unpinned");
|
|
||||||
Debug.Assert(Slab == null || !Slab.IsActive, "Block being garbage collected instead of returned to pool");
|
Debug.Assert(Slab == null || !Slab.IsActive, "Block being garbage collected instead of returned to pool");
|
||||||
|
|
||||||
if (_pinHandle.IsAllocated)
|
|
||||||
{
|
|
||||||
// if this is a one-time-use block, ensure that the GCHandle does not leak
|
|
||||||
_pinHandle.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Slab != null && Slab.IsActive)
|
if (Slab != null && Slab.IsActive)
|
||||||
{
|
{
|
||||||
Pool.Return(new MemoryPoolBlock
|
Pool.Return(new MemoryPoolBlock(DataArrayPtr)
|
||||||
{
|
{
|
||||||
_dataArrayPtr = _dataArrayPtr,
|
|
||||||
Data = Data,
|
Data = Data,
|
||||||
Pool = Pool,
|
Pool = Pool,
|
||||||
Slab = Slab,
|
Slab = Slab,
|
||||||
|
|
@ -97,49 +84,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal static MemoryPoolBlock Create(
|
||||||
/// Called to ensure that a block is pinned, and return the pointer to the native address
|
|
||||||
/// of the first byte of this block's Data memory. Arriving data is read into Pin() + End.
|
|
||||||
/// Outgoing data is read from Pin() + Start.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IntPtr Pin()
|
|
||||||
{
|
|
||||||
Debug.Assert(!_pinHandle.IsAllocated);
|
|
||||||
|
|
||||||
if (_dataArrayPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
// this is a slab managed block - use the native address of the slab which is always locked
|
|
||||||
return _dataArrayPtr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// this is one-time-use memory - lock the managed memory until Unpin is called
|
|
||||||
_pinHandle = GCHandle.Alloc(Data.Array, GCHandleType.Pinned);
|
|
||||||
return _pinHandle.AddrOfPinnedObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Unpin()
|
|
||||||
{
|
|
||||||
if (_dataArrayPtr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
// this is one-time-use memory - unlock the managed memory
|
|
||||||
Debug.Assert(_pinHandle.IsAllocated);
|
|
||||||
_pinHandle.Free();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MemoryPoolBlock Create(
|
|
||||||
ArraySegment<byte> data,
|
ArraySegment<byte> data,
|
||||||
IntPtr dataPtr,
|
IntPtr dataPtr,
|
||||||
MemoryPool pool,
|
MemoryPool pool,
|
||||||
MemoryPoolSlab slab)
|
MemoryPoolSlab slab)
|
||||||
{
|
{
|
||||||
return new MemoryPoolBlock
|
return new MemoryPoolBlock(dataPtr)
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
_dataArrayPtr = dataPtr,
|
|
||||||
Pool = pool,
|
Pool = pool,
|
||||||
Slab = slab,
|
Slab = slab,
|
||||||
Start = data.Offset,
|
Start = data.Offset,
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking
|
||||||
|
|
||||||
// create and pin each segment being written
|
// create and pin each segment being written
|
||||||
pBuffers[index] = Libuv.buf_init(
|
pBuffers[index] = Libuv.buf_init(
|
||||||
block.Pin() + blockStart,
|
block.DataArrayPtr + blockStart,
|
||||||
blockEnd - blockStart);
|
blockEnd - blockStart);
|
||||||
|
|
||||||
block = block.Next;
|
block = block.Next;
|
||||||
|
|
@ -89,7 +89,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking
|
||||||
var block = start.Block;
|
var block = start.Block;
|
||||||
for (var index = 0; index < nBuffers; index++)
|
for (var index = 0; index < nBuffers; index++)
|
||||||
{
|
{
|
||||||
block.Unpin();
|
|
||||||
block = block.Next;
|
block = block.Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue