Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9db4f30
add iterations section for end-2-end config and set for microbenchmar…
VincentBu Apr 23, 2026
a730074
Merge branch 'dotnet:main' into average-microbenchmarks-iterations
VincentBu Apr 23, 2026
9802484
add json-trace map and implement AnalyzeForBenchmark
VincentBu Apr 24, 2026
f2318ac
Calculate comparison result by benchmark name, rename classes and adj…
VincentBu Apr 28, 2026
e34745b
present list of microbenchmarkresults
VincentBu May 1, 2026
e9594b3
rename iteration section to iterations for Run.yaml
VincentBu May 6, 2026
c3f4b45
Potential fix for pull request finding
VincentBu May 6, 2026
240ceb8
fix for microbencharmks comparison
VincentBu May 6, 2026
1b08bd0
fix bugs intrduced in previous commit
VincentBu May 6, 2026
434a17c
Add json-only comparison
VincentBu May 7, 2026
faca628
extract a shared helper for analyze command
VincentBu May 7, 2026
ab17bf3
take trace type into consideration
VincentBu May 7, 2026
70c7f16
move MicrobenchmarkResult to GC.Infrastructure.Core.Analysis.Microben…
VincentBu May 7, 2026
d9b160d
validate if run is null
VincentBu May 7, 2026
2ba9f6b
rename PauseDurationSeconds_SumWhereIsGen1 to PauseDurationMSec_SumWh…
VincentBu May 7, 2026
1dc65f5
assign value for PromotedMB_MeanWhereIsGen1
VincentBu May 7, 2026
6915009
add properties for microbenchmarks comparison
VincentBu May 9, 2026
2b51863
get value from StatsData if property is not found in GCTraceMetrics
VincentBu May 9, 2026
69ea04d
filtering to finite values
VincentBu May 9, 2026
30c9c91
check possible null references
VincentBu May 9, 2026
3b38059
add console output when analyzing results
VincentBu May 9, 2026
866e09d
Merge branch 'average-microbenchmarks-iterations' of https://github.c…
VincentBu May 9, 2026
f9c6d08
redesign microbenchmarks result
VincentBu May 12, 2026
3b78ca3
redesign microbenchmarkresult
VincentBu May 14, 2026
b7cb942
Merge pull request #1 from VincentBu/redesign-microbenchmark-result
VincentBu May 14, 2026
8096656
move presentation to analyze-command
VincentBu May 14, 2026
ec7b882
improve performance of analyzing stage
VincentBu May 15, 2026
6ba2219
includes int type properties
VincentBu May 15, 2026
cc59167
check key existence and set parallelism degree to 2 * cpu_count
VincentBu May 15, 2026
a7c1b2c
check if metricName is a key of StatsData
VincentBu May 15, 2026
357ce0a
Filter out null GCTraceMetrics instances before calling CompareGCTrac…
VincentBu May 15, 2026
3d1c330
update initialization of OtherMetrics for MicrobenchmarkComparisonResult
VincentBu May 15, 2026
eb9f7e3
comment out cpu_columns related code
VincentBu May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/benchmarks/gc/GC.Infrastructure/Configurations/Run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ coreruns:
environment_variables:
DOTNET_GCName: clrgc.dll

iterations:
gcperfsim: 1
microbenchmarks: 1

trace_configuration_type: gc # Choose between: none, gc, verbose, cpu, cpu_managed, threadtime, join.

# Optional fields: the contents of both the symbol_path and the source_path will be copied over to the output path.
Expand Down
24 changes: 24 additions & 0 deletions src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Statistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,29 @@ public static double StandardDeviation(this IEnumerable<double> doubleList)
double sumOfDerivationAverage = sumOfDerivation / (doubleList.Count() - 1);
return Math.Sqrt(sumOfDerivationAverage - (average * average));
}

public static IEnumerable<double> RemoveOutliers(IEnumerable<double> collection)
{
if (!collection.Any())
{
return Array.Empty<double>();
}
double[] validCollection = collection
.Where(x => !double.IsNaN(x) && !double.IsInfinity(x))
.ToArray();
// Calculate Q1 (25th percentile) and Q3 (75th percentile)
double q1 = GC.Analysis.API.Statistics.Percentile(validCollection, 0.25);
double q3 = GC.Analysis.API.Statistics.Percentile(validCollection, 0.75);

// Calculate IQR (Interquartile Range)
double iqr = q3 - q1;

// Calculate bounds: [Q1 - 1.5*IQR, Q3 + 1.5*IQR]
double lowerBound = q1 - 1.5 * iqr;
double upperBound = q3 + 1.5 * iqr;

// Filter out outliers
return GoodLinq.Where(collection, x => x >= lowerBound && x <= upperBound);
}
Comment thread
VincentBu marked this conversation as resolved.
}
}
Original file line number Diff line number Diff line change
@@ -1,103 +1,10 @@
using GC.Analysis.API;
using GC.Infrastructure.Core.Configurations.Microbenchmarks;
using GC.Infrastructure.Core.Presentation.GCPerfSim;
using Newtonsoft.Json;

namespace GC.Infrastructure.Core.Analysis
namespace GC.Infrastructure.Core.Analysis
{
public sealed class MicrobenchmarkResult
Comment thread
VincentBu marked this conversation as resolved.
{
public Statistics Statistics { get; set; }

[JsonIgnore]
public GCProcessData? GCData { get; set; }

public ResultItem ResultItem { get; set; }

[JsonIgnore]
public CPUProcessData? CPUData { get; set; }
public Run Parent { get; set; }
public string MicrobenchmarkName { get; set; }
public Dictionary<string, double?> OtherMetrics { get; set; } = new();

private static readonly IReadOnlyDictionary<string, Func<Statistics, double?>> _customStatisticsCalculationMap = new Dictionary<string, Func<Statistics, double?>>(StringComparer.OrdinalIgnoreCase)
{
{ "number of iterations", (Statistics stats) => stats.N },
{ "min", (Statistics stats) => stats.Min },
{ "max", (Statistics stats) => stats.Max },
{ "median", (Statistics stats) => stats.Median },
{ "q1", (Statistics stats) => stats.Q1 },
{ "q3", (Statistics stats) => stats.Q3 },
{ "variance", (Statistics stats) => stats.Variance },
{ "standard deviation", (Statistics stats) => stats.StandardDeviation },
{ "skewness", (Statistics stats) => stats.Skewness },
{ "kurtosis", (Statistics stats) => stats.Kurtosis },
{ "standard error", (Statistics stats) => stats.StandardError },
{ "standard error / mean", (Statistics stats) => stats.StandardError / stats.Mean },
};

public static double? LookupStatisticsCalculation(string columnName, MicrobenchmarkResult result)
{
if (string.IsNullOrEmpty(columnName))
{
return null;
}

if (!_customStatisticsCalculationMap.TryGetValue(columnName, out var val))
{
return null;
}

else
{
return val.Invoke(result.Statistics);
}
}
}

public sealed class Benchmark
{
public string DisplayInfo { get; set; }
public string Namespace { get; set; }
public string Type { get; set; }
public string Method { get; set; }
public string MethodTitle { get; set; }
public string Parameters { get; set; }
public string FullName { get; set; }
public Statistics Statistics { get; set; }
public Memory Memory { get; set; }
public List<Measurement> Measurements { get; set; }
public List<Metric> Metrics { get; set; }
}

public sealed class ChronometerFrequency
{
public int Hertz { get; set; }
}

public sealed class ConfidenceInterval
{
public int N { get; set; }
public double? Mean { get; set; }
public double? StandardError { get; set; }
public int? Level { get; set; }
public double? Margin { get; set; }
public double? Lower { get; set; }
public double? Upper { get; set; }
}

public sealed class Descriptor
{
public string Id { get; set; }
public string DisplayName { get; set; }
public string Legend { get; set; }
public string NumberFormat { get; set; }
public int UnitType { get; set; }
public string Unit { get; set; }
public bool TheGreaterTheBetter { get; set; }
public int PriorityInCategory { get; set; }
}

public sealed class HostEnvironmentInfo
{
public string BenchmarkDotNetCaption { get; set; }
Expand All @@ -117,6 +24,16 @@ public sealed class HostEnvironmentInfo
public string HardwareTimerKind { get; set; }
}


public sealed class Memory
{
public int Gen0Collections { get; set; }
public int Gen1Collections { get; set; }
public int Gen2Collections { get; set; }
public int TotalOperations { get; set; }
public long BytesAllocatedPerOperation { get; set; }
}

public sealed class Measurement
{
public string IterationMode { get; set; }
Expand All @@ -127,19 +44,27 @@ public sealed class Measurement
public long Nanoseconds { get; set; }
}

public sealed class Memory
public sealed class Descriptor
{
public int Gen0Collections { get; set; }
public int Gen1Collections { get; set; }
public int Gen2Collections { get; set; }
public int TotalOperations { get; set; }
public long BytesAllocatedPerOperation { get; set; }
public string Id { get; set; }
public string DisplayName { get; set; }
public string Legend { get; set; }
public string NumberFormat { get; set; }
public int UnitType { get; set; }
public string Unit { get; set; }
public bool TheGreaterTheBetter { get; set; }
public int PriorityInCategory { get; set; }
}

public sealed class Metric
public sealed class ConfidenceInterval
{
public double Value { get; set; }
public Descriptor Descriptor { get; set; }
public int N { get; set; }
public double Mean { get; set; }
public double StandardError { get; set; }
public int Level { get; set; }
public double Margin { get; set; }
public double Lower { get; set; }
public double Upper { get; set; }
}

public sealed class Percentiles
Expand All @@ -155,35 +80,56 @@ public sealed class Percentiles
public double P100 { get; set; }
}

public sealed class MicrobenchmarkResults
{
public string Title { get; set; }
public HostEnvironmentInfo HostEnvironmentInfo { get; set; }
public List<Benchmark> Benchmarks { get; set; }
}

public sealed class Statistics
{
public List<double> OriginalValues { get; set; }
public int N { get; set; }
public double? Min { get; set; }
public double? LowerFence { get; set; }
public double? Q1 { get; set; }
public double? Median { get; set; }
public double? Mean { get; set; }
public double? Q3 { get; set; }
public double? UpperFence { get; set; }
public double? Max { get; set; }
public double? InterquartileRange { get; set; }
public List<double?> LowerOutliers { get; set; }
public double Min { get; set; }
public double LowerFence { get; set; }
public double Q1 { get; set; }
public double Median { get; set; }
public double Mean { get; set; }
public double Q3 { get; set; }
public double UpperFence { get; set; }
public double Max { get; set; }
public double InterquartileRange { get; set; }
public List<double> LowerOutliers { get; set; }
public List<object> UpperOutliers { get; set; }
public List<double?> AllOutliers { get; set; }
public double? StandardError { get; set; }
public double? Variance { get; set; }
public double? StandardDeviation { get; set; }
public double? Skewness { get; set; }
public double? Kurtosis { get; set; }
public List<double> AllOutliers { get; set; }
public double StandardError { get; set; }
public double Variance { get; set; }
public double StandardDeviation { get; set; }
public double Skewness { get; set; }
public double Kurtosis { get; set; }
public ConfidenceInterval? ConfidenceInterval { get; set; }
public Percentiles Percentiles { get; set; }
}
}

public sealed class Metric
{
public double Value { get; set; }
public Descriptor Descriptor { get; set; }
}

public sealed class Benchmark
{
public string DisplayInfo { get; set; }
public string Namespace { get; set; }
public string Type { get; set; }
public string Method { get; set; }
public string MethodTitle { get; set; }
public string Parameters { get; set; }
public string FullName { get; set; }
public Statistics Statistics { get; set; }
public Memory Memory { get; set; }
public List<Measurement> Measurements { get; set; }
public List<Metric> Metrics { get; set; }
}

public sealed class BdnJsonResult
{
public string Title { get; set; }
public HostEnvironmentInfo HostEnvironmentInfo { get; set; }
public List<Benchmark> Benchmarks { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace GC.Infrastructure.Core.Analysis
{
public static class GCTraceMetricComparison
{
public static GCTraceMetricComparisonResult CompareGCTraceMetric(IEnumerable<GCTraceMetrics> baselines, IEnumerable<GCTraceMetrics> comparands,string nameOfMetric)
=> new GCTraceMetricComparisonResult(baselines, comparands, nameOfMetric);
}
}
Loading
Loading