Browse Source

Async local doesn't actually work for the finalizers, revert that piece.

pull/2082/head
Scott Williams 4 years ago
parent
commit
99d12664a2
  1. 96
      src/ImageSharp/Diagnostics/MemoryDiagnostics.cs

96
src/ImageSharp/Diagnostics/MemoryDiagnostics.cs

@ -17,6 +17,10 @@ namespace SixLabors.ImageSharp.Diagnostics
{
internal static readonly InteralMemoryDiagnostics Default = new();
private static AsyncLocal<InteralMemoryDiagnostics> localInstance = null;
// the async local end up out of scope during finalizers so putting into thte internal class is useless
private static UndisposedAllocationDelegate undisposedAllocation;
private static int undisposedAllocationSubscriptionCounter;
private static readonly object SyncRoot = new();
/// <summary>
@ -26,8 +30,23 @@ namespace SixLabors.ImageSharp.Diagnostics
/// </summary>
public static event UndisposedAllocationDelegate UndisposedAllocation
{
add => Current.UndisposedAllocation += value;
remove => Current.UndisposedAllocation -= value;
add
{
lock (SyncRoot)
{
undisposedAllocationSubscriptionCounter++;
undisposedAllocation += value;
}
}
remove
{
lock (SyncRoot)
{
undisposedAllocation -= value;
undisposedAllocationSubscriptionCounter--;
}
}
}
internal static InteralMemoryDiagnostics Current
@ -61,81 +80,46 @@ namespace SixLabors.ImageSharp.Diagnostics
/// </summary>
public static int TotalUndisposedAllocationCount => Current.TotalUndisposedAllocationCount;
internal static bool UndisposedAllocationSubscribed => Current.UndisposedAllocationSubscribed;
internal static bool UndisposedAllocationSubscribed => Volatile.Read(ref undisposedAllocationSubscriptionCounter) > 0;
internal static void IncrementTotalUndisposedAllocationCount() => Current.IncrementTotalUndisposedAllocationCount();
internal static void DecrementTotalUndisposedAllocationCount() => Current.DecrementTotalUndisposedAllocationCount();
internal static void RaiseUndisposedMemoryResource(string allocationStackTrace)
=> Current.RaiseUndisposedMemoryResource(allocationStackTrace);
{
if (undisposedAllocation is null)
{
return;
}
// Schedule on the ThreadPool, to avoid user callback messing up the finalizer thread.
#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER
ThreadPool.QueueUserWorkItem(
stackTrace => undisposedAllocation?.Invoke(stackTrace),
allocationStackTrace,
preferLocal: false);
#else
ThreadPool.QueueUserWorkItem(
stackTrace => undisposedAllocation?.Invoke((string)stackTrace),
allocationStackTrace);
#endif
}
internal class InteralMemoryDiagnostics
{
private int totalUndisposedAllocationCount;
private UndisposedAllocationDelegate undisposedAllocation;
private int undisposedAllocationSubscriptionCounter;
private readonly object syncRoot = new();
/// <summary>
/// Fires when an ImageSharp object's undisposed memory resource leaks to the finalizer.
/// The event brings significant overhead, and is intended to be used for troubleshooting only.
/// For production diagnostics, use <see cref="TotalUndisposedAllocationCount"/>.
/// </summary>
public event UndisposedAllocationDelegate UndisposedAllocation
{
add
{
lock (this.syncRoot)
{
this.undisposedAllocationSubscriptionCounter++;
this.undisposedAllocation += value;
}
}
remove
{
lock (this.syncRoot)
{
this.undisposedAllocation -= value;
this.undisposedAllocationSubscriptionCounter--;
}
}
}
/// <summary>
/// Gets a value indicating the total number of memory resource objects leaked to the finalizer.
/// </summary>
public int TotalUndisposedAllocationCount => this.totalUndisposedAllocationCount;
internal bool UndisposedAllocationSubscribed => Volatile.Read(ref this.undisposedAllocationSubscriptionCounter) > 0;
internal void IncrementTotalUndisposedAllocationCount() =>
Interlocked.Increment(ref this.totalUndisposedAllocationCount);
internal void DecrementTotalUndisposedAllocationCount() =>
Interlocked.Decrement(ref this.totalUndisposedAllocationCount);
internal void RaiseUndisposedMemoryResource(string allocationStackTrace)
{
if (this.undisposedAllocation is null)
{
return;
}
// Schedule on the ThreadPool, to avoid user callback messing up the finalizer thread.
#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER
ThreadPool.QueueUserWorkItem(
stackTrace => this.undisposedAllocation?.Invoke(stackTrace),
allocationStackTrace,
preferLocal: false);
#else
ThreadPool.QueueUserWorkItem(
stackTrace => this.undisposedAllocation?.Invoke((string)stackTrace),
allocationStackTrace);
#endif
}
}
}
}

Loading…
Cancel
Save