Skip to content

Commit 1cbeab6

Browse files
committed
chore: moves models to a dedicated source file
chore: uses STJ attribute based serialization Signed-off-by: Vincent Biret <[email protected]>
1 parent 1c991f6 commit 1cbeab6

File tree

2 files changed

+44
-40
lines changed

2 files changed

+44
-40
lines changed

performance/resultsComparer/handlers/CompareCommandHandler.cs

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
using System.CommandLine;
33
using System.CommandLine.Invocation;
44
using System.Text.Json;
5+
using System.Text.Json.Serialization;
56
using Microsoft.Extensions.DependencyInjection;
67
using Microsoft.Extensions.Logging;
8+
using resultsComparer.Models;
79

810
namespace 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+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace resultsComparer.Models;
4+
internal sealed record BenchmarkReport
5+
{
6+
[JsonPropertyName("Benchmarks")]
7+
public Benchmark[] Benchmarks { get; init; } = [];
8+
}
9+
internal sealed record Benchmark
10+
{
11+
[JsonPropertyName("Method")]
12+
public string Method { get; init; } = string.Empty;
13+
14+
[JsonPropertyName("Memory")]
15+
public BenchmarkMemory Memory { get; init; } = new BenchmarkMemory();
16+
}
17+
internal sealed record BenchmarkMemory
18+
{
19+
[JsonPropertyName("BytesAllocatedPerOperation")]
20+
public long AllocatedBytes { get; init; }
21+
}

0 commit comments

Comments
 (0)