Merge branch 'benaadams/more-block-collect-info' into dev

This commit is contained in:
Stephen Halter 2016-07-28 16:50:01 -07:00
commit 00a540dcb8
6 changed files with 58 additions and 10 deletions

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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);
}
}

View File

@ -317,6 +317,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
Assert.ThrowsAny<InvalidOperationException>(() => scan.Skip(8));
_pool.Return(block);
_pool.Return(nextBlock);
}
[Theory]