Merge branch 'benaadams/more-block-collect-info' into dev
This commit is contained in:
commit
00a540dcb8
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
||||
{
|
||||
|
|
@ -64,16 +65,34 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
/// Called to take a block from the pool.
|
||||
/// </summary>
|
||||
/// <returns>The block that is reserved for the called. It must be passed to Return when it is no longer being used.</returns>
|
||||
#if DEBUG
|
||||
public MemoryPoolBlock Lease(
|
||||
[CallerMemberName] string memberName = "",
|
||||
[CallerFilePath] string sourceFilePath = "",
|
||||
[CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
Debug.Assert(!_disposedValue, "Block being leased from disposed pool!");
|
||||
#else
|
||||
public MemoryPoolBlock Lease()
|
||||
{
|
||||
#endif
|
||||
MemoryPoolBlock block;
|
||||
if (_blocks.TryDequeue(out block))
|
||||
{
|
||||
// block successfully taken from the stack - return it
|
||||
#if DEBUG
|
||||
block.Leaser = memberName + ", " + sourceFilePath + ", " + sourceLineNumber;
|
||||
block.IsLeased = true;
|
||||
#endif
|
||||
return block;
|
||||
}
|
||||
// no blocks available - grow the pool
|
||||
return AllocateSlab();
|
||||
block = AllocateSlab();
|
||||
#if DEBUG
|
||||
block.Leaser = memberName + ", " + sourceFilePath + ", " + sourceLineNumber;
|
||||
block.IsLeased = true;
|
||||
#endif
|
||||
return block;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -100,6 +119,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
basePtr,
|
||||
this,
|
||||
slab);
|
||||
#if DEBUG
|
||||
block.IsLeased = true;
|
||||
#endif
|
||||
Return(block);
|
||||
}
|
||||
|
||||
|
|
@ -123,19 +145,33 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
/// <param name="block">The block to return. It must have been acquired by calling Lease on the same memory pool instance.</param>
|
||||
public void Return(MemoryPoolBlock block)
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.Assert(block.Pool == this, "Returned block was not leased from this pool");
|
||||
Debug.Assert(block.IsLeased, $"Block being returned to pool twice: {block.Leaser}{Environment.NewLine}");
|
||||
block.IsLeased = false;
|
||||
#endif
|
||||
|
||||
if (block.Slab != null && block.Slab.IsActive)
|
||||
{
|
||||
block.Reset();
|
||||
_blocks.Enqueue(block);
|
||||
}
|
||||
else
|
||||
{
|
||||
GC.SuppressFinalize(block);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
_disposedValue = true;
|
||||
#if DEBUG
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
#endif
|
||||
if (disposing)
|
||||
{
|
||||
MemoryPoolSlab slab;
|
||||
|
|
@ -146,7 +182,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var block in _blocks)
|
||||
// Discard blocks in pool
|
||||
MemoryPoolBlock block;
|
||||
while (_blocks.TryDequeue(out block))
|
||||
{
|
||||
GC.SuppressFinalize(block);
|
||||
}
|
||||
|
|
@ -155,7 +193,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
|
||||
// N/A: set large fields to null.
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,10 +71,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
/// </summary>
|
||||
public MemoryPoolBlock Next;
|
||||
|
||||
#if DEBUG
|
||||
public bool IsLeased { get; set; }
|
||||
public string Leaser { get; set; }
|
||||
#endif
|
||||
|
||||
~MemoryPoolBlock()
|
||||
{
|
||||
Debug.Assert(Slab == null || !Slab.IsActive, "Block being garbage collected instead of returned to pool");
|
||||
|
||||
#if DEBUG
|
||||
Debug.Assert(Slab == null || !Slab.IsActive, $"{Environment.NewLine}{Environment.NewLine}*** Block being garbage collected instead of returned to pool: {Leaser} ***{Environment.NewLine}");
|
||||
#endif
|
||||
if (Slab != null && Slab.IsActive)
|
||||
{
|
||||
Pool.Return(new MemoryPoolBlock(DataArrayPtr)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
_disposedValue = true;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// N/A: dispose managed state (managed objects).
|
||||
|
|
@ -72,8 +74,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
|
||||
// set large fields to null.
|
||||
Array = null;
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
Task.WaitAll(Threads.Select(thread => thread.StopAsync(TimeSpan.FromSeconds(2.5))).ToArray());
|
||||
|
||||
Threads.Clear();
|
||||
#if DEBUG
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
#endif
|
||||
}
|
||||
|
||||
public IDisposable CreateServer(ServerAddress address)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
var end = GetIterator(begin, byteRange.Length);
|
||||
|
||||
Assert.Throws<BadHttpRequestException>(() => begin.GetAsciiString(end));
|
||||
|
||||
pool.Return(mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,9 +154,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
block = block.Next;
|
||||
pool.Return(returnBlock);
|
||||
}
|
||||
|
||||
pool.Return(mem0);
|
||||
pool.Return(mem1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -317,6 +317,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
Assert.ThrowsAny<InvalidOperationException>(() => scan.Skip(8));
|
||||
|
||||
_pool.Return(block);
|
||||
_pool.Return(nextBlock);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
Loading…
Reference in New Issue