Skip to content

Commit 7e0e106

Browse files
committed
use events to track allocations
1 parent 935c4a9 commit 7e0e106

2 files changed

Lines changed: 45 additions & 38 deletions

File tree

tests/ImageSharp.Drawing.Tests/MemoryAllocatorValidator.cs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
5-
using System.Collections.Generic;
6-
using System.Diagnostics;
75
using System.Threading;
86
using SixLabors.ImageSharp.Diagnostics;
97
using Xunit;
@@ -12,53 +10,68 @@ namespace SixLabors.ImageSharp.Drawing.Tests
1210
{
1311
public static class MemoryAllocatorValidator
1412
{
15-
private static List<string> traces = new List<string>();
13+
private static readonly AsyncLocal<TestMemoryDiagnostics> LocalInstance = new();
1614

17-
public static void MonitorStackTraces() => MemoryDiagnostics.UndisposedAllocation += MemoryDiagnostics_UndisposedAllocation;
15+
public static bool MonitoringAllocations => LocalInstance.Value != null;
1816

19-
public static List<string> GetStackTraces()
17+
static MemoryAllocatorValidator()
2018
{
21-
GC.Collect();
22-
GC.WaitForPendingFinalizers();
23-
return traces;
19+
MemoryDiagnostics.MemoryAllocated += MemoryDiagnostics_MemoryAllocated;
20+
MemoryDiagnostics.MemoryReleased += MemoryDiagnostics_MemoryReleased;
2421
}
2522

26-
private static void MemoryDiagnostics_UndisposedAllocation(string allocationStackTrace)
23+
private static void MemoryDiagnostics_MemoryReleased()
2724
{
28-
lock (traces)
25+
TestMemoryDiagnostics backing = LocalInstance.Value;
26+
if (backing != null)
2927
{
30-
traces.Add(allocationStackTrace);
28+
backing.TotalRemainingAllocated--;
3129
}
3230
}
3331

34-
public static TestMemoryAllocatorDisposable MonitorAllocations()
32+
private static void MemoryDiagnostics_MemoryAllocated()
3533
{
36-
MemoryDiagnostics.Current = new();
37-
return new TestMemoryAllocatorDisposable();
34+
TestMemoryDiagnostics backing = LocalInstance.Value;
35+
if (backing != null)
36+
{
37+
backing.TotalAllocated++;
38+
backing.TotalRemainingAllocated++;
39+
}
40+
}
41+
42+
public static TestMemoryDiagnostics MonitorAllocations()
43+
{
44+
var diag = new TestMemoryDiagnostics();
45+
LocalInstance.Value = diag;
46+
return diag;
3847
}
3948

40-
public static void StopMonitoringAllocations() => MemoryDiagnostics.Current = null;
49+
public static void StopMonitoringAllocations() => LocalInstance.Value = null;
50+
51+
public static void ValidateAllocations(int expectedAllocationCount = 0)
52+
=> LocalInstance.Value?.Validate(expectedAllocationCount);
4153

42-
public static void ValidateAllocation(int max = 0)
54+
public class TestMemoryDiagnostics : IDisposable
4355
{
44-
var count = MemoryDiagnostics.TotalUndisposedAllocationCount;
56+
public int TotalAllocated { get; set; }
4557

46-
var pass = count <= max;
47-
Assert.True(pass, $"Expected a max of {max} undisposed buffers but found {count}");
58+
public int TotalRemainingAllocated { get; set; }
4859

49-
if (count > 0)
60+
public void Validate(int expectedAllocationCount)
5061
{
51-
Debug.WriteLine("We should have Zero undisposed memory allocations.");
62+
var count = this.TotalRemainingAllocated;
63+
var pass = expectedAllocationCount == count;
64+
Assert.True(pass, $"Expected a {expectedAllocationCount} undisposed buffers but found {count}");
5265
}
53-
}
5466

55-
public struct TestMemoryAllocatorDisposable : IDisposable
56-
{
5767
public void Dispose()
58-
=> StopMonitoringAllocations();
59-
60-
public void Validate(int maxAllocations = 0)
61-
=> ValidateAllocation(maxAllocations);
68+
{
69+
this.Validate(0);
70+
if (LocalInstance.Value == this)
71+
{
72+
StopMonitoringAllocations();
73+
}
74+
}
6275
}
6376
}
6477
}

tests/ImageSharp.Drawing.Tests/ValidateDisposedMemoryAllocationsAttribute.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,22 @@ namespace SixLabors.ImageSharp.Drawing.Tests
1111
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
1212
public class ValidateDisposedMemoryAllocationsAttribute : BeforeAfterTestAttribute
1313
{
14-
private readonly int max = 0;
14+
private readonly int expected = 0;
1515

1616
public ValidateDisposedMemoryAllocationsAttribute()
1717
: this(0)
1818
{
1919
}
2020

21-
public ValidateDisposedMemoryAllocationsAttribute(int max)
22-
{
23-
this.max = max;
24-
if (max > 0)
25-
{
26-
Debug.WriteLine("Needs fixing, we shoudl have Zero undisposed memory allocations.");
27-
}
28-
}
21+
public ValidateDisposedMemoryAllocationsAttribute(int expected)
22+
=> this.expected = expected;
2923

3024
public override void Before(MethodInfo methodUnderTest)
3125
=> MemoryAllocatorValidator.MonitorAllocations();
3226

3327
public override void After(MethodInfo methodUnderTest)
3428
{
35-
MemoryAllocatorValidator.ValidateAllocation(this.max);
29+
MemoryAllocatorValidator.ValidateAllocations(this.expected);
3630
MemoryAllocatorValidator.StopMonitoringAllocations();
3731
}
3832
}

0 commit comments

Comments
 (0)