-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unittests around memory allocation (#29)
- Loading branch information
1 parent
4a70af7
commit dbad06b
Showing
12 changed files
with
262 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
test/Mediator.MemAllocationTests/Mediator.MemAllocationTests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
|
||
<IsPackable>false</IsPackable> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> | ||
<!--<ReportAnalyzer>true</ReportAnalyzer>--> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="Xunit" /> | ||
<Using Include="System.Runtime.CompilerServices" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(DotNetVersion)" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" /> | ||
<PackageReference Include="xunit" Version="2.4.1" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="coverlet.collector" Version="3.1.2"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="JetBrains.DotMemoryUnit" Version="3.1.20200127.214830" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Mediator.SourceGenerator.Implementation\Mediator.SourceGenerator.Implementation.csproj" OutputItemType="Analyzer" /> | ||
<ProjectReference Include="..\..\src\Mediator.SourceGenerator.Roslyn40\Mediator.SourceGenerator.Roslyn40.csproj" OutputItemType="Analyzer" /> | ||
<ProjectReference Include="..\..\src\Mediator\Mediator.csproj" /> | ||
<ProjectReference Include="..\Mediator.Tests.Common\Mediator.Tests.Common.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
6 changes: 6 additions & 0 deletions
6
test/Mediator.MemAllocationTests/NonParallelCollectionDefinitionClass.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Mediator.Tests; | ||
|
||
[CollectionDefinition("Non-Parallel", DisableParallelization = true)] | ||
public class NonParallelCollectionDefinitionClass | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using Mediator.Tests.Common; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Mediator.MemAllocationTests; | ||
|
||
[Collection("Non-Parallel")] | ||
public class NotificationTests | ||
{ | ||
[Fact] | ||
public void Test_Notification_Handler() | ||
{ | ||
var services = new ServiceCollection(); | ||
|
||
services.AddMediator(); | ||
|
||
using var sp = services.BuildServiceProvider(validateScopes: true); | ||
var mediator = sp.GetRequiredService<IMediator>(); | ||
|
||
var id = Guid.NewGuid(); | ||
var notification = new SomeNotificationMemAllocTracking(id); | ||
|
||
// Ensure everything is cached | ||
mediator.Publish(notification); // Everything returns sync | ||
|
||
var beforeBytes = Allocations.GetCurrentThreadAllocatedBytes(); | ||
mediator.Publish(notification); // Everything returns sync | ||
var afterBytes = Allocations.GetCurrentThreadAllocatedBytes(); | ||
|
||
// TODO: why 40? benchmarkdotnet reports 0 alloc for this case | ||
Assert.Equal(40, afterBytes - beforeBytes); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using JetBrains.dotMemoryUnit; | ||
using JetBrains.dotMemoryUnit.Kernel; | ||
using Mediator.Tests.Common; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Xunit.Abstractions; | ||
|
||
namespace Mediator.MemAllocationTests; | ||
|
||
[Collection("Non-Parallel")] | ||
public class RequestTests | ||
{ | ||
private readonly ITestOutputHelper _output; | ||
|
||
public RequestTests(ITestOutputHelper output) | ||
{ | ||
_output = output; | ||
DotMemoryUnitTestOutput.SetOutputMethod(output.WriteLine); | ||
} | ||
|
||
/// <summary> | ||
/// To run these tests | ||
/// dotMemoryUnit.exe "$((Get-Command dotnet.exe).Path)" -- test "./test/Mediator.MemAllocationTests/" | ||
/// TODO: find a way to filter out dotMemoryUnit's own mem allocations from report... | ||
/// </summary> | ||
/// <returns></returns> | ||
[DotMemoryUnit(CollectAllocations = true)] | ||
[Fact] | ||
public async Task Test_Request_Handler_dotMemory() | ||
{ | ||
if (!dotMemoryApi.IsEnabled) | ||
return; | ||
|
||
var services = new ServiceCollection(); | ||
|
||
services.AddMediator(); | ||
|
||
await using var sp = services.BuildServiceProvider(validateScopes: true); | ||
var mediator = sp.GetRequiredService<Mediator>(); | ||
|
||
var id = Guid.NewGuid(); | ||
var request = new SomeRequestMemAllocTracking(id); | ||
|
||
// Ensure everything is cached | ||
await mediator.Send(request); | ||
GC.Collect(); | ||
GC.WaitForPendingFinalizers(); | ||
GC.WaitForFullGCComplete(); | ||
GC.Collect(); | ||
|
||
var checkpoint = dotMemory.Check(); | ||
var beforeBytes = GC.GetAllocatedBytesForCurrentThread(); | ||
await mediator.Send(request); | ||
var afterBytes = GC.GetAllocatedBytesForCurrentThread(); | ||
|
||
Assert.Equal(0, afterBytes - beforeBytes); | ||
dotMemory.Check(memory => | ||
{ | ||
var traffic = memory.GetDifference(checkpoint); | ||
var newObjects = traffic.GetNewObjects(); | ||
foreach (var obj in newObjects.GroupByType()) | ||
_output.WriteLine($"Allocations for {obj.TypeFullyQualifiedName}: {obj.SizeInBytes} bytes"); | ||
|
||
//_output.WriteLine($"Allocated: {traffic.AllocatedMemory.SizeInBytes}"); | ||
//foreach (var obj in traffic.GroupByType()) | ||
// _output.WriteLine($"Allocations for {obj.TypeFullyQualifiedName}: {obj.AllocatedMemoryInfo.SizeInBytes}"); | ||
|
||
Assert.Equal(0, traffic.GetNewObjects().ObjectsCount); | ||
}); | ||
} | ||
|
||
|
||
[Fact] | ||
public void Test_Request_Handler() | ||
{ | ||
var services = new ServiceCollection(); | ||
|
||
services.AddMediator(); | ||
|
||
using var sp = services.BuildServiceProvider(validateScopes: true); | ||
var mediator = sp.GetRequiredService<IMediator>(); | ||
|
||
var id = Guid.NewGuid(); | ||
var request = new SomeRequestMemAllocTracking(id); | ||
|
||
// Ensure everything is cached | ||
mediator.Send(request); // Everything returns sync | ||
|
||
var beforeBytes = Allocations.GetCurrentThreadAllocatedBytes(); | ||
mediator.Send(request); // Everything returns sync | ||
var afterBytes = Allocations.GetCurrentThreadAllocatedBytes(); | ||
|
||
Assert.Equal(0, afterBytes - beforeBytes); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
test/Mediator.MemAllocationTests/SomeNotificationMemAllocTracking.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Mediator.MemAllocationTests; | ||
|
||
public sealed record SomeNotificationMemAllocTracking(Guid Id) : INotification; | ||
|
||
public sealed class SomeNotificationMemAllocTrackingHandler : INotificationHandler<SomeNotificationMemAllocTracking> | ||
{ | ||
public ValueTask Handle(SomeNotificationMemAllocTracking notification, CancellationToken cancellationToken) => default; | ||
} |
8 changes: 8 additions & 0 deletions
8
test/Mediator.MemAllocationTests/SomeRequestMemAllocTracking.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Mediator.MemAllocationTests; | ||
|
||
public sealed record SomeRequestMemAllocTracking(Guid Id) : IRequest; | ||
|
||
public sealed class SomeRequestMemAllocTrackingHandler : IRequestHandler<SomeRequestMemAllocTracking> | ||
{ | ||
public ValueTask<Unit> Handle(SomeRequestMemAllocTracking request, CancellationToken cancellationToken) => default; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
namespace Mediator.Tests.Common; | ||
|
||
public static class Allocations | ||
{ | ||
public static long GetCurrentThreadAllocatedBytes() | ||
{ | ||
// Run before and after message sending to test allocations. | ||
// Stolen from https://github.com/dotnet/BenchmarkDotNet/blob/4bd433d85fff4fb6ba8c4f8df3e685ad669e2519/src/BenchmarkDotNet/Engines/GcStats.cs#L132 | ||
// There is a reason GC.Collect is run first | ||
GC.Collect(); | ||
return GC.GetAllocatedBytesForCurrentThread(); | ||
} | ||
|
||
public static long GetCurrentAllocatedBytes() | ||
{ | ||
// Run before and after message sending to test allocations. | ||
// Stolen from https://github.com/dotnet/BenchmarkDotNet/blob/4bd433d85fff4fb6ba8c4f8df3e685ad669e2519/src/BenchmarkDotNet/Engines/GcStats.cs#L132 | ||
// There is a reason GC.Collect is run first | ||
GC.Collect(); | ||
return GC.GetTotalAllocatedBytes(true); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(DotNetVersion)" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Mediator\Mediator.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Mediator.Tests; | ||
|
||
[CollectionDefinition("Non-Parallel", DisableParallelization = true)] | ||
public class NonParallelCollectionDefinitionClass | ||
{ | ||
} |