22using System . CommandLine ;
33using System . CommandLine . Invocation ;
44using System . Text . Json ;
5+ using System . Text . Json . Serialization ;
56using Microsoft . Extensions . DependencyInjection ;
67using Microsoft . Extensions . Logging ;
8+ using resultsComparer . Models ;
79
810namespace resultsComparer . Handlers ;
911
@@ -23,7 +25,8 @@ public override Task<int> InvokeAsync(InvocationContext context)
2325 var logger = loggerFactory . CreateLogger < CompareCommandHandler > ( ) ;
2426 return CompareResultsAsync ( oldResultsPath , newResultsPath , logger , cancellationToken ) ;
2527 }
26- private static async Task < int > CompareResultsAsync ( string existingReportPath , string newReportPath , ILogger logger , CancellationToken cancellationToken = default ) {
28+ private static async Task < int > CompareResultsAsync ( string existingReportPath , string newReportPath , ILogger logger , CancellationToken cancellationToken = default )
29+ {
2730
2831 var existingBenchmark = await GetBenchmarksAllocatedBytes ( existingReportPath , cancellationToken ) ;
2932 if ( existingBenchmark is null )
@@ -41,7 +44,7 @@ private static async Task<int> CompareResultsAsync(string existingReportPath, st
4144 MemoryBenchmarkResultComparer . Instance
4245 ] ;
4346 var hasErrors = false ;
44- foreach ( var existingBenchmarkResult in existingBenchmark )
47+ foreach ( var existingBenchmarkResult in existingBenchmark )
4548 {
4649 if ( ! newBenchmark . TryGetValue ( existingBenchmarkResult . Key , out var newBenchmarkResult ) )
4750 {
@@ -71,66 +74,46 @@ private static async Task<int> CompareResultsAsync(string existingReportPath, st
7174 return hasErrors ? 1 : 0 ;
7275 }
7376
74- private static async Task < Dictionary < string , BenchmarkResult > ? > GetBenchmarksAllocatedBytes ( string targetPath , CancellationToken cancellationToken = default )
77+ private static async Task < Dictionary < string , BenchmarkMemory > ? > GetBenchmarksAllocatedBytes ( string targetPath , CancellationToken cancellationToken = default )
7578 {
7679 if ( ! File . Exists ( targetPath ) )
7780 {
7881 return null ;
7982 }
8083 using var stream = new FileStream ( targetPath , FileMode . Open , FileAccess . Read ) ;
81- using var document = await JsonDocument . ParseAsync ( stream , cancellationToken : cancellationToken ) ;
82- var rootElement = document . RootElement ;
83- if ( rootElement . ValueKind is not JsonValueKind . Object ||
84- ! rootElement . TryGetProperty ( "Benchmarks" , out var benchmarksNode ) ||
85- benchmarksNode . ValueKind is not JsonValueKind . Array )
86- {
87- return null ;
88- }
89- return benchmarksNode . EnumerateArray ( ) . Select ( benchmarkNode => {
90- if ( benchmarkNode . ValueKind is not JsonValueKind . Object )
91- {
92- return default ;
93- }
94- if ( ! benchmarkNode . TryGetProperty ( "Memory" , out var memoryNode ) ||
95- memoryNode . ValueKind is not JsonValueKind . Object ||
96- ! memoryNode . TryGetProperty ( "BytesAllocatedPerOperation" , out var allocatedBytesNode ) ||
97- allocatedBytesNode . ValueKind is not JsonValueKind . Number ||
98- ! allocatedBytesNode . TryGetInt64 ( out var allocatedBytes ) )
99- {
100- return default ;
101- }
102- if ( ! benchmarkNode . TryGetProperty ( "Method" , out var nameNode ) ||
103- nameNode . ValueKind is not JsonValueKind . String ||
104- nameNode . GetString ( ) is not string name )
105- {
106- return default ;
107- }
108- return ( name , new BenchmarkResult ( allocatedBytes ) ) ;
109- } )
110- . Where ( x => x . name is not null && x . Item2 is not null )
111- . ToDictionary ( x => x . name ! , x => x . Item2 ! , StringComparer . OrdinalIgnoreCase ) ;
84+ var report = ( await JsonSerializer . DeserializeAsync ( stream , serializationContext . BenchmarkReport , cancellationToken : cancellationToken ) )
85+ ?? throw new InvalidOperationException ( $ "Failed to deserialize { targetPath } .") ;
86+ return report . Benchmarks
87+ . Where ( x => x . Memory is not null && x . Method is not null )
88+ . ToDictionary ( x => x . Method ! , x => x . Memory ! , StringComparer . OrdinalIgnoreCase ) ;
11289 }
113- private sealed record BenchmarkResult ( long AllocatedBytes ) ;
114- private interface IBenchmarkComparisonPolicy : IEqualityComparer < BenchmarkResult >
90+ private static readonly BenchmarkSourceGenerationContext serializationContext = new ( ) ;
91+
92+ private interface IBenchmarkComparisonPolicy : IEqualityComparer < BenchmarkMemory >
11593 {
116- string GetErrorMessage ( BenchmarkResult ? x , BenchmarkResult ? y ) ;
94+ string GetErrorMessage ( BenchmarkMemory ? x , BenchmarkMemory ? y ) ;
11795 }
11896 private sealed class MemoryBenchmarkResultComparer : IBenchmarkComparisonPolicy
11997 {
12098 public static MemoryBenchmarkResultComparer Instance { get ; } = new MemoryBenchmarkResultComparer ( ) ;
121- public bool Equals ( BenchmarkResult ? x , BenchmarkResult ? y )
99+ public bool Equals ( BenchmarkMemory ? x , BenchmarkMemory ? y )
122100 {
123101 return x ? . AllocatedBytes == y ? . AllocatedBytes ;
124102 }
125103
126- public string GetErrorMessage ( BenchmarkResult ? x , BenchmarkResult ? y )
104+ public string GetErrorMessage ( BenchmarkMemory ? x , BenchmarkMemory ? y )
127105 {
128106 return $ "Allocated bytes differ: { x ? . AllocatedBytes } != { y ? . AllocatedBytes } ";
129107 }
130108
131- public int GetHashCode ( BenchmarkResult obj )
109+ public int GetHashCode ( BenchmarkMemory obj )
132110 {
133111 return obj . AllocatedBytes . GetHashCode ( ) ;
134112 }
135113 }
136114}
115+
116+ [ JsonSerializable ( typeof ( BenchmarkReport ) ) ]
117+ internal partial class BenchmarkSourceGenerationContext : JsonSerializerContext
118+ {
119+ }
0 commit comments