mirror of https://github.com/SixLabors/ImageSharp
2 changed files with 116 additions and 0 deletions
@ -0,0 +1,22 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Diagnostics |
|||
{ |
|||
public readonly struct MemoryInfo |
|||
{ |
|||
internal MemoryInfo(long totalUndisposedAllocationCount) |
|||
=> this.TotalUndisposedAllocationCount = totalUndisposedAllocationCount; |
|||
|
|||
public long TotalUndisposedAllocationCount { get; } |
|||
} |
|||
|
|||
public static class MemoryDiagnostics |
|||
{ |
|||
public static MemoryInfo GetMemoryInfo() => throw new NotImplementedException(); |
|||
|
|||
public static bool EnableStrictDisposeWatcher { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using System.Collections.Generic; |
|||
using System.Runtime.CompilerServices; |
|||
using Microsoft.DotNet.RemoteExecutor; |
|||
using SixLabors.ImageSharp.Diagnostics; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Memory.Allocators |
|||
{ |
|||
public class MemoryDiagnosticsTests |
|||
{ |
|||
private const int OneMb = 1 << 20; |
|||
|
|||
private static MemoryAllocator Allocator => Configuration.Default.MemoryAllocator; |
|||
|
|||
[Theory] |
|||
[InlineData(false)] |
|||
[InlineData(true)] |
|||
public void AllocateDispose_Maintains_TotalUndisposedLogicalAllocationCount(bool isGroupOuter) |
|||
{ |
|||
RemoteExecutor.Invoke(RunTest, isGroupOuter.ToString()).Dispose(); |
|||
|
|||
static void RunTest(string isGroupInner) |
|||
{ |
|||
bool isGroup = bool.Parse(isGroupInner); |
|||
List<IDisposable> buffers = new(); |
|||
|
|||
Assert.Equal(0, MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount); |
|||
for (int length = 1024; length <= 64 * OneMb; length *= 2) |
|||
{ |
|||
long cntBefore = MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount; |
|||
IDisposable buffer = isGroup ? |
|||
Allocator.AllocateGroup<byte>(length, 1024) : |
|||
Allocator.Allocate<byte>(length); |
|||
buffers.Add(buffer); |
|||
long cntAfter = MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount; |
|||
Assert.True(cntAfter > cntBefore); |
|||
} |
|||
|
|||
foreach (IDisposable buffer in buffers) |
|||
{ |
|||
long cntBefore = MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount; |
|||
buffer.Dispose(); |
|||
long cntAfter = MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount; |
|||
Assert.True(cntAfter < cntBefore); |
|||
} |
|||
|
|||
Assert.Equal(0, MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount); |
|||
} |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(false)] |
|||
[InlineData(true)] |
|||
public void BufferAndGroupFinalizer_DoesNotReduce_TotalUndisposedLogicalAllocationCount(bool isGroupOuter) |
|||
{ |
|||
RemoteExecutor.Invoke(RunTest, isGroupOuter.ToString()).Dispose(); |
|||
|
|||
static void RunTest(string isGroupInner) |
|||
{ |
|||
bool isGroup = bool.Parse(isGroupInner); |
|||
Assert.Equal(0, MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount); |
|||
for (int length = 1024; length <= 64 * OneMb; length *= 2) |
|||
{ |
|||
long cntBefore = MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount; |
|||
AllocateAndForget(length, isGroup); |
|||
GC.Collect(); |
|||
GC.WaitForPendingFinalizers(); |
|||
GC.Collect(); |
|||
long cntAfter = MemoryDiagnostics.GetMemoryInfo().TotalUndisposedAllocationCount; |
|||
Assert.True(cntAfter > cntBefore); |
|||
} |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.NoInlining)] |
|||
static void AllocateAndForget(int length, bool isGroup) |
|||
{ |
|||
if (isGroup) |
|||
{ |
|||
_ = Allocator.AllocateGroup<byte>(length, 1024); |
|||
} |
|||
else |
|||
{ |
|||
_ = Allocator.Allocate<byte>(length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue