From 2aa10a64a270eaef9c1324173717a437402fba69 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 30 Apr 2016 10:01:39 +0100 Subject: [PATCH] Remove noop pin+unpin w/ memory blocks + Only use pooled blocks in tests --- .../Http/Connection.cs | 2 +- .../Http/SocketOutput.cs | 3 - .../Infrastructure/MemoryPool.cs | 17 +----- .../Infrastructure/MemoryPoolBlock.cs | 61 +++---------------- .../Networking/UvWriteReq.cs | 3 +- 5 files changed, 10 insertions(+), 76 deletions(-) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Connection.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Connection.cs index 814da8143b..add23c4389 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Connection.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Connection.cs @@ -253,7 +253,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http var result = _rawSocketInput.IncomingStart(); return handle.Libuv.buf_init( - result.Pin() + result.End, + result.DataArrayPtr + result.End, result.Data.Offset + result.Data.Count - result.End); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs index f424a7531c..5db2fb3ebc 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs @@ -684,14 +684,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http var end = _lockedEnd.Block; if (block == end) { - end.Unpin(); return; } while (block.Next != end) { block = block.Next; - block.Unpin(); } block.Next = null; @@ -705,7 +703,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http var returnBlock = block; block = block.Next; - returnBlock.Unpin(); returnBlock.Pool.Return(returnBlock); } } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPool.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPool.cs index d5a4e59b7e..6fd37f8a9c 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPool.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPool.cs @@ -63,24 +63,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure /// /// Called to take a block from the pool. /// - /// 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. /// The block that is reserved for the called. It must be passed to Return when it is no longer being used. - 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(new byte[minimumSize]), - dataPtr: IntPtr.Zero, - pool: this, - slab: null); - } - MemoryPoolBlock block; if (_blocks.TryDequeue(out block)) { diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPoolBlock.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPoolBlock.cs index 25cab8c4f4..362165ee12 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPoolBlock.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/MemoryPoolBlock.cs @@ -11,18 +11,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure /// public class MemoryPoolBlock { - /// - /// 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. - /// - private GCHandle _pinHandle; - /// /// 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 - /// 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. /// - private IntPtr _dataArrayPtr; + public readonly IntPtr DataArrayPtr; /// /// 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 /// /// This object cannot be instantiated outside of the static Create method /// - protected MemoryPoolBlock() + protected MemoryPoolBlock(IntPtr dataArrayPtr) { + DataArrayPtr = dataArrayPtr; } /// @@ -76,20 +71,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure ~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"); - 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) { - Pool.Return(new MemoryPoolBlock + Pool.Return(new MemoryPoolBlock(DataArrayPtr) { - _dataArrayPtr = _dataArrayPtr, Data = Data, Pool = Pool, Slab = Slab, @@ -97,49 +84,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure } } - /// - /// 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. - /// - /// - 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( + internal static MemoryPoolBlock Create( ArraySegment data, IntPtr dataPtr, MemoryPool pool, MemoryPoolSlab slab) { - return new MemoryPoolBlock + return new MemoryPoolBlock(dataPtr) { Data = data, - _dataArrayPtr = dataPtr, Pool = pool, Slab = slab, Start = data.Offset, diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvWriteReq.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvWriteReq.cs index bf088950a5..bc776767a6 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvWriteReq.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvWriteReq.cs @@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking // create and pin each segment being written pBuffers[index] = Libuv.buf_init( - block.Pin() + blockStart, + block.DataArrayPtr + blockStart, blockEnd - blockStart); block = block.Next; @@ -89,7 +89,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking var block = start.Block; for (var index = 0; index < nBuffers; index++) { - block.Unpin(); block = block.Next; }