From 2ae3cd58e10ed8329e8fbaf277ba7ca2da10d160 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Wed, 19 Jun 2024 07:39:20 -0700 Subject: [PATCH 1/7] dotnet-format --- .../GC.Analysis.API/Analyzer.cs | 12 +- .../GC.Analysis.API/AnalyzerManager.cs | 6 +- .../CPUAnalysis/CPUAnalysisExt.cs | 28 ++--- .../CPUAnalysis/CPUAnalyzer.cs | 36 +++--- .../GC.Analysis.API/CPUAnalysis/CPUInfo.cs | 4 +- .../GC.Analysis.API/CPUAnalysis/Charting.cs | 24 ++-- .../CPUAnalysis/SourceCodeAnalysis.cs | 2 +- .../GC.Analysis.API/CPUAnalysis/Tables.cs | 34 +++--- .../GC.Analysis.API/Common.cs | 50 ++++---- .../GCAnalysis/AffinitizedAnalysis.cs | 2 +- .../GC.Analysis.API/GCAnalysis/Charting.cs | 114 +++++++++--------- .../GCAnalysis/GCAnalysisExt.cs | 10 +- .../GCAnalysis/GCProcessData.cs | 10 +- .../GCAnalysis/GCSummarization.cs | 38 +++--- .../GCAnalysis/JoinAnalysis.cs | 38 +++--- .../GC.Analysis.API/Statistics.cs | 4 +- .../GC.Analysis.API/TraceSummarization.cs | 36 +++--- .../Presentation/MarkdownReportBuilder.cs | 4 +- .../Analysis/AnalyzeTrace.cs | 16 +-- .../Analysis/MetricResult.cs | 2 +- .../MicrobenchmarkComparisonResult.cs | 2 +- .../MicrobenchmarkComparisonResults.cs | 8 +- .../Microbenchmarks/MicrobenchmarkResults.cs | 6 +- .../MicrobenchmarkResultsAnalyzer.cs | 14 +-- .../Analysis/ProcessExecutionDetails.cs | 10 +- .../ASPNetBenchmarks.CommandBuilder.cs | 12 +- .../GCPerfSim.CommandBuilder.cs | 8 +- .../Microbenchmark.CommandBuilder.cs | 6 +- .../ASPNetBenchmark.Configuration.cs | 2 +- .../Configurations/Common.cs | 6 +- .../Configurations/GCPerfSim.Configuration.cs | 14 +-- .../GCPerfSimFunctional.Configuration.cs | 2 +- .../Configurations/InputConfiguration.cs | 6 +- .../Presentation/GCPerfSim/Markdown.cs | 2 +- .../Presentation/GCPerfSim/ResultItem.cs | 100 +++++++-------- .../GCPerfSim/ResultItemComparison.cs | 12 +- .../Presentation/MarkdownReportBuilder.cs | 12 +- .../Presentation/Microbenchmarks/Markdown.cs | 26 ++-- .../Microbenchmarks/Presentation.cs | 2 +- .../TraceCollection/TraceCollector.cs | 14 +-- .../GC.Infrastructure.Core/Utilities.cs | 12 +- .../AspNetBenchmarksAnalyzeCommand.cs | 12 +- .../AspNetBenchmarksCommand.cs | 30 ++--- .../GCPerfSim/GCPerfSimAnalyzeCommand.cs | 2 +- .../Commands/GCPerfSim/GCPerfSimCommand.cs | 16 +-- .../GCPerfSim/GCPerfSimFunctionalCommand.cs | 6 +- .../Microbenchmark/MicrobenchmarkCommand.cs | 8 +- .../Commands/RunCommand/CreateSuiteCommand.cs | 28 ++--- .../Commands/RunCommand/RunCommand.cs | 30 ++--- .../Commands/RunCommand/RunSuiteCommand.cs | 2 +- .../GC.Infrastructure/Program.cs | 2 +- 51 files changed, 441 insertions(+), 441 deletions(-) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Analyzer.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Analyzer.cs index 1e558be0e86..cd410118021 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Analyzer.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Analyzer.cs @@ -20,9 +20,9 @@ public Analyzer(string tracePath, HashSet processNames) TraceLog = Etlx.TraceLog.OpenOrConvert(tracePath); Dictionary> processIdToGCThreads = GetAllGCThreads(TraceLog.Events.GetSource(), processNames); - foreach(var p in TraceLog.GetAllProcesses()) + foreach (var p in TraceLog.GetAllProcesses()) { - if (!processNames.Contains(p.Name)) + if (!processNames.Contains(p.Name)) { continue; } @@ -79,7 +79,7 @@ public Analyzer(string tracePath) TraceLog = Etlx.TraceLog.OpenOrConvert(tracePath); Dictionary> processIdToGCThreads = GetAllGCThreads(TraceLog.Events.GetSource()); - foreach(var p in TraceLog.GetAllProcesses()) + foreach (var p in TraceLog.GetAllProcesses()) { TraceLoadedDotNetRuntime managedProcess = p.LoadedDotNetRuntime(); if (!IsInterestingGCProcess(managedProcess)) @@ -116,7 +116,7 @@ public Analyzer(string tracePath) if (!gcThreadsForAllProcesses.TryGetValue(markData.ProcessID, out var gcThreads)) { - gcThreadsForAllProcesses[markData.ProcessID] = gcThreads = new Dictionary(); + gcThreadsForAllProcesses[markData.ProcessID] = gcThreads = new Dictionary(); } gcThreads[markData.ThreadID] = markData.HeapNum; @@ -127,8 +127,8 @@ public Analyzer(string tracePath) } internal static Predicate IsInterestingGCProcess = (managedProcess) => - (managedProcess != null && // If the process in question is a managed process. - managedProcess.GC != null && // If the managed process has GCs. + (managedProcess != null && // If the process in question is a managed process. + managedProcess.GC != null && // If the managed process has GCs. managedProcess.GC.GCs != null && // " managedProcess.GC.GCs.Count > 0); // " private bool disposedValue; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/AnalyzerManager.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/AnalyzerManager.cs index 28f7e824b9d..59c5c3da676 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/AnalyzerManager.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/AnalyzerManager.cs @@ -9,7 +9,7 @@ public static class AnalyzerManager public static Dictionary GetAnalyzer(IEnumerable tracePaths) { Dictionary analyzers = new(); - foreach(var tracePath in tracePaths) + foreach (var tracePath in tracePaths) { Analyzer analyzer = new Analyzer(tracePath); analyzers[tracePath] = analyzer; @@ -34,7 +34,7 @@ public static class AnalyzerManager allFiles = Directory.EnumerateFiles(basePath, "*", SearchOption.AllDirectories); } - foreach(var file in allFiles) + foreach (var file in allFiles) { if (file.EndsWith("etl.zip")) { @@ -51,7 +51,7 @@ public static class AnalyzerManager analyzers[file] = analyzer; } } - + else if (file.EndsWith(".nettrace")) { Analyzer analyzer = new Analyzer(file); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalysisExt.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalysisExt.cs index 9d2545ed295..b2cc420a579 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalysisExt.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalysisExt.cs @@ -8,7 +8,7 @@ internal static List ConvertToCPUInfo(this CPUProcessData data, SortedD { List cpuInfos = new List(); GCProcessData gcData = data.Parent.Analyzer.GetProcessGCData(data.ProcessName).Single(g => g.ProcessID == data.ProcessID); - foreach(var gc in gcData.GCs) + foreach (var gc in gcData.GCs) { if (perGCCounts.TryGetValue(gc.Number, out float f)) { @@ -50,12 +50,12 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, throw new ArgumentException($"'{nameof(methodName)}' cannot be null or empty.", nameof(methodName)); } - SortedDictionary perGCCost = new(); + SortedDictionary perGCCost = new(); if (processData.PerGCData.TryGetValue(methodName, out var data)) { // For each GC, for each thread, sum up the counts. - foreach(var perGC in data) + foreach (var perGC in data) { int gcNumber = perGC.Key; if (!perGCCost.TryGetValue(gcNumber, out var value)) @@ -63,9 +63,9 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, perGCCost[gcNumber] = 0; } - foreach(var thread in perGC.Value) + foreach (var thread in perGC.Value) { - foreach(var c in thread.Value) + foreach (var c in thread.Value) { if (c.Callers.Any(gc => gc.Contains(caller))) { @@ -81,9 +81,9 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, { SortedDictionary perGCCostForPlanPhase = new(); var relocatePhase = GetPerGCMethodCost(processData, "gc_heap::relocate_phase", isInclusiveCount); - var compactPhase = GetPerGCMethodCost(processData, "gc_heap::compact_phase", isInclusiveCount); + var compactPhase = GetPerGCMethodCost(processData, "gc_heap::compact_phase", isInclusiveCount); - foreach(var gc in perGCCost) + foreach (var gc in perGCCost) { if (!perGCCostForPlanPhase.TryGetValue(gc.Key, out var planCount)) { @@ -126,7 +126,7 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, if (processData.OverallData.TryGetValue(methodName, out var data)) { // For each GC, for each thread, sum up the counts. - foreach(var perGC in data) + foreach (var perGC in data) { int gcNumber = perGC.Key; perGCCost[gcNumber] = isInclusiveCount ? perGC.Value.InclusiveCount : perGC.Value.ExclusiveCount; @@ -138,10 +138,10 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, { SortedDictionary perGCCostForPlanPhase = new(); var relocatePhase = GetPerGCMethodCost(processData, "gc_heap::relocate_phase", isInclusiveCount); - var compactPhase = GetPerGCMethodCost(processData, "gc_heap::compact_phase", isInclusiveCount); + var compactPhase = GetPerGCMethodCost(processData, "gc_heap::compact_phase", isInclusiveCount); var makeFreeListsPhase = GetPerGCMethodCost(processData, "gc_heap::make_free_lists", isInclusiveCount); - foreach(var gc in perGCCost) + foreach (var gc in perGCCost) { if (!perGCCostForPlanPhase.TryGetValue(gc.Key, out var planCount)) { @@ -173,7 +173,7 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, return processData.ConvertToCPUInfo(perGCCost); } - public static List GetPerGCMethodCost(this CPUProcessData processData, + public static List GetPerGCMethodCost(this CPUProcessData processData, string methodName, HashSet gcsToConsider, bool isInclusiveCount = true) @@ -192,7 +192,7 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, if (processData.OverallData.TryGetValue(methodName, out var data)) { - foreach(var perGC in data) + foreach (var perGC in data) { int gcNumber = perGC.Key; if (!gcsToConsider.Contains(gcNumber)) @@ -209,10 +209,10 @@ public static List GetPerGCMethodCost(this CPUProcessData processData, { SortedDictionary perGCCostForPlanPhase = new(); var relocatePhase = GetPerGCMethodCost(processData, "gc_heap::relocate_phase", isInclusiveCount); - var compactPhase = GetPerGCMethodCost(processData, "gc_heap::compact_phase", isInclusiveCount); + var compactPhase = GetPerGCMethodCost(processData, "gc_heap::compact_phase", isInclusiveCount); var makeFreeListsPhase = GetPerGCMethodCost(processData, "gc_heap::make_free_lists", isInclusiveCount); - foreach(var gc in perGCCost) + foreach (var gc in perGCCost) { if (!perGCCostForPlanPhase.TryGetValue(gc.Key, out var planCount)) { diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalyzer.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalyzer.cs index d5edb136d8a..96317389506 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalyzer.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUAnalyzer.cs @@ -13,7 +13,7 @@ namespace GC.Analysis.API { - public sealed class CPUProcessData + public sealed class CPUProcessData { public int ProcessID { get; set; } public string ProcessName { get; set; } @@ -28,8 +28,8 @@ public sealed class CPUProcessData [JsonIgnore] internal StackView StackView { get; set; } // Method Name -> GC # -> CPU Data - public Dictionary> OverallData{ get; set; } = new(); - public Dictionary> GCOverallData{ get; set; } = new(); + public Dictionary> OverallData { get; set; } = new(); + public Dictionary> GCOverallData { get; set; } = new(); public Dictionary MethodToData { get; set; } = new(); } @@ -48,9 +48,9 @@ public CPUAnalyzer(Analyzer analyzer, string yamlPath = "./DefaultMethods.yaml", .Build(); string configContents = File.ReadAllText(yamlPath); - Configuration = deserializer.Deserialize(configContents); + Configuration = deserializer.Deserialize(configContents); - _symbolWriter = TextWriter.Null; + _symbolWriter = TextWriter.Null; if (!string.IsNullOrEmpty(anaylsisLogFile)) { _symbolWriter = new StreamWriter(anaylsisLogFile); @@ -71,7 +71,7 @@ public CPUAnalyzer(Analyzer analyzer, string yamlPath = "./DefaultMethods.yaml", SymbolReader.SecurityCheck = path => true; // Resolve symbols. - foreach(var module in analyzer.TraceLog.ModuleFiles) + foreach (var module in analyzer.TraceLog.ModuleFiles) { if (module.Name.ToLower().Contains("clr") /* || module.Name.ToLower().Contains("ntoskrnl") */) { @@ -84,7 +84,7 @@ public CPUAnalyzer(Analyzer analyzer, string yamlPath = "./DefaultMethods.yaml", List allMethods = Configuration.gc_methods.ToList(); // TODO: Segregate the non-GC methods here. - CPUAnalyzers = GetAllCPUAnalyzers(analyzer, new HashSet(allMethods)); + CPUAnalyzers = GetAllCPUAnalyzers(analyzer, new HashSet(allMethods)); } internal static List FindNodesByName(string nodeNamePat, List byID) @@ -126,7 +126,7 @@ internal void DepthFirstSearch(CallTreeNode node, string method, int gcNumber, C Callers = new(), }; - var cpuThreads = GetCPUThreadNode(method: method, threadID: threadID, gcNumber: gcNumber, processData: processData); + var cpuThreads = GetCPUThreadNode(method: method, threadID: threadID, gcNumber: gcNumber, processData: processData); var cpuThreadsByGC = GetCPUThreadNodeByGCNumber(method, threadID, gcNumber, processData); CallTreeNode cursor = callee; @@ -165,7 +165,7 @@ internal static List GetCPUThreadNode(string method, int threadID return cpuData; } - internal static List GetCPUThreadNodeByGCNumber(string method, int threadID, int gcNumber, CPUProcessData processData) + internal static List GetCPUThreadNodeByGCNumber(string method, int threadID, int gcNumber, CPUProcessData processData) { if (!processData.PerGCData.TryGetValue(method, out var gcToThreadData)) { @@ -189,7 +189,7 @@ internal static List GetCPUThreadNodeByGCNumber(string method, in { Microsoft.Diagnostics.Tracing.Etlx.TraceLog traceLog = analyzer.TraceLog; Dictionary processIDMap = new(); - foreach(var process in traceLog.Processes) + foreach (var process in traceLog.Processes) { if (analyzer.AllGCProcessData.ContainsKey(process.Name)) { @@ -235,7 +235,7 @@ internal static List GetCPUThreadNodeByGCNumber(string method, in var allStackSource = CopyStackSource.Clone(traceStackSource); processData.StackView = new StackView(analyzer.TraceLog, allStackSource, SymbolReader, traceEvents); - foreach(var method in Configuration.gc_methods) + foreach (var method in Configuration.gc_methods) { CPUThreadData d = processData.MethodToData[method] = new CPUThreadData { @@ -255,7 +255,7 @@ internal static List GetCPUThreadNodeByGCNumber(string method, in return; } - foreach(var gc in process.GCs) + foreach (var gc in process.GCs) { if (gc.Type == Microsoft.Diagnostics.Tracing.Parsers.Clr.GCType.BackgroundGC) { @@ -270,12 +270,12 @@ internal static List GetCPUThreadNodeByGCNumber(string method, in new FilterStackSource(filterParams, allStackSource, ScalingPolicyKind.ScaleToData); StackView stackView = new(processData.Parent.Analyzer.TraceLog, timeFilteredStackSource, processData.Parent.SymbolReader, processData.StackView.TraceEvents); - foreach(var method in Configuration.gc_methods) + foreach (var method in Configuration.gc_methods) { if (!methodDict.TryGetValue(method, out var m)) { methodDict[method] = m = new CPUThreadData - { + { Method = method, Thread = "-1", }; @@ -299,10 +299,10 @@ internal static List GetCPUThreadNodeByGCNumber(string method, in } // For each gc. - foreach(var gc in processData.GCOverallData) + foreach (var gc in processData.GCOverallData) { // For each method in that gc. - foreach(var method in gc.Value) + foreach (var method in gc.Value) { if (!processData.OverallData.TryGetValue(method.Key, out var d)) { @@ -383,9 +383,9 @@ internal static List GetCPUThreadNodeByGCNumber(string method, in public Analyzer Analyzer { get; } public SymbolReader SymbolReader { get; } - public GCMethodsData Configuration { get; } + public GCMethodsData Configuration { get; } // Process Name -> CPU Process Data. - public Dictionary> CPUAnalyzers { get; } = new(); + public Dictionary> CPUAnalyzers { get; } = new(); } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUInfo.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUInfo.cs index 35683b68850..2681b42b7f7 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUInfo.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/CPUInfo.cs @@ -6,11 +6,11 @@ public sealed class CPUInfo { public CPUInfo(TraceGC gc, float count) { - GC = gc; + GC = gc; Count = count; } - public TraceGC GC { get; } + public TraceGC GC { get; } public float Count { get; } } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Charting.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Charting.cs index 9113bc40121..1eb118a8bb4 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Charting.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Charting.cs @@ -7,7 +7,7 @@ public static class CPUCharting private const string xAxisAsGCNumber = "GC #"; public static PlotlyChart ChartCountForGCMethod((string name, List gcsToCost) data, - string title, + string title, ChartInfo? chartInfo = null) { Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, fieldName: data.name, xAxis: xAxisAsGCNumber, chartInfo: chartInfo); @@ -47,7 +47,7 @@ public static class CPUCharting Scatter gcScatter = new Scatter { x = gcNumber, - y = other.gcData, + y = other.gcData, yaxis = "y2", showlegend = true, name = other.name, @@ -57,13 +57,13 @@ public static class CPUCharting } public static PlotlyChart ChartCountForGCMethods(IEnumerable<(string name, List gcsToCost)> data, - string title, + string title, ChartInfo? chartInfo = null) { Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, fieldName: "Inclusive Cost", xAxis: xAxisAsGCNumber, chartInfo: chartInfo); List scatters = new(); - foreach(var d in data) + foreach (var d in data) { List cost = d.gcsToCost.Select(gc => gc.Count); List gcNumber = d.gcsToCost.Select(gc => gc.GC.Number); @@ -83,7 +83,7 @@ public static class CPUCharting return Chart.Plot(scatters, layout); } - public static PlotlyChart ChartCountForGCMethod(this CPUProcessData cpuProcessData, + public static PlotlyChart ChartCountForGCMethod(this CPUProcessData cpuProcessData, string methodName, string title, string caller, @@ -92,7 +92,7 @@ public static class CPUCharting { string countType = isInclusiveCount ? "Inclusive Count" : "Exclusive Count"; Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, fieldName: countType, xAxis: xAxisAsGCNumber, chartInfo: chartInfo); - var data = cpuProcessData.GetPerGCMethodCost(methodName: methodName, caller: caller, isInclusiveCount : isInclusiveCount); + var data = cpuProcessData.GetPerGCMethodCost(methodName: methodName, caller: caller, isInclusiveCount: isInclusiveCount); List cost = data.Select(gc => gc.Count); List gcNumber = data.Select(gc => gc.GC.Number); @@ -116,7 +116,7 @@ public static class CPUCharting { string countType = isInclusiveCount ? "Inclusive Count" : "Exclusive Count"; Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, fieldName: countType, xAxis: xAxisAsGCNumber, chartInfo: chartInfo); - var data = cpuProcessData.GetPerGCMethodCost(methodName: methodName, isInclusiveCount : isInclusiveCount); + var data = cpuProcessData.GetPerGCMethodCost(methodName: methodName, isInclusiveCount: isInclusiveCount); List cost = data.Select(gc => gc.Count); List gcNumber = data.Select(gc => gc.GC.Number); @@ -132,10 +132,10 @@ public static class CPUCharting return Chart.Plot(scatter, layout); } - public static PlotlyChart ChartCountForGCMethods(this CPUProcessData cpuProcessData, - IEnumerable methodNames, - string title, - bool isInclusiveCount = true, + public static PlotlyChart ChartCountForGCMethods(this CPUProcessData cpuProcessData, + IEnumerable methodNames, + string title, + bool isInclusiveCount = true, ChartInfo? chartInfo = null) { string countType = isInclusiveCount ? "Inclusive Count" : "Exclusive Count"; @@ -145,7 +145,7 @@ public static class CPUCharting foreach (var methodName in methodNames) { - var data = cpuProcessData.GetPerGCMethodCost(methodName: methodName, isInclusiveCount : isInclusiveCount); + var data = cpuProcessData.GetPerGCMethodCost(methodName: methodName, isInclusiveCount: isInclusiveCount); List cost = data.Select(gc => gc.Count); List gcNumber = data.Select(gc => gc.GC.Number); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/SourceCodeAnalysis.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/SourceCodeAnalysis.cs index a94b406baee..09dbbd4643f 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/SourceCodeAnalysis.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/SourceCodeAnalysis.cs @@ -3,7 +3,7 @@ using Microsoft.Diagnostics.Tracing.Stacks; using System.Text.RegularExpressions; using Address = System.UInt64; -using EtlxNS = Microsoft.Diagnostics.Tracing.Etlx; +using EtlxNS = Microsoft.Diagnostics.Tracing.Etlx; namespace GC.Analysis.API.CPUAnalysis { diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Tables.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Tables.cs index 8e478fc54bc..5857d41022d 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Tables.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/CPUAnalysis/Tables.cs @@ -4,8 +4,8 @@ namespace GC.Analysis.API { public static class Tables { - internal static readonly IEnumerable phases = new List - { + internal static readonly IEnumerable phases = new List + { "gc_heap::mark_phase", "gc_heap::plan_phase", "gc_heap::relocate_phase", @@ -62,12 +62,12 @@ public static DataFrame GetPerPhaseSummary(this CPUProcessData cpuData, bool sho Dictionary phaseToCount = new(); double total = 0; - foreach(var phase in phases) + foreach (var phase in phases) { double sum = 0; if (cpuData.MethodToData.TryGetValue(phase, out var data)) { - sum += showInclusiveCount ? data.InclusiveCount : data.ExclusiveCount; + sum += showInclusiveCount ? data.InclusiveCount : data.ExclusiveCount; } phaseToCount[phase] = sum; total += sum; @@ -76,7 +76,7 @@ public static DataFrame GetPerPhaseSummary(this CPUProcessData cpuData, bool sho phaseToCount["gc_heap::plan_phase"] -= phaseToCount["gc_heap::relocate_phase"] + phaseToCount["gc_heap::compact_phase"]; total -= phaseToCount["gc_heap::relocate_phase"] + phaseToCount["gc_heap::compact_phase"]; - foreach(var phase in phaseToCount) + foreach (var phase in phaseToCount) { phaseName.Append(phase.Key); counts.Append(phase.Value); @@ -96,12 +96,12 @@ public static DataFrame Compare(this CPUProcessData cpuData, IEnumerable phaseToCount = new(); double total = 0; - foreach(var phase in phases) + foreach (var phase in phases) { double sum = 0; if (cpuData.MethodToData.TryGetValue(phase, out var data)) { - sum += showInclusiveCount ? data.InclusiveCount : data.ExclusiveCount; + sum += showInclusiveCount ? data.InclusiveCount : data.ExclusiveCount; } phaseToCount[phase] = sum; total += sum; @@ -110,7 +110,7 @@ public static DataFrame Compare(this CPUProcessData cpuData, IEnumerable otherColumns = new(); - foreach(var o in others) + foreach (var o in others) { DoubleDataFrameColumn otherCounts = new(showInclusiveCount ? $"Inclusive Count: {o.ProcessID}" : $"Exclusive Count: {o.ProcessID}"); DoubleDataFrameColumn otherDiffCount = new($"Diff: {o.ProcessID}"); @@ -131,12 +131,12 @@ public static DataFrame Compare(this CPUProcessData cpuData, IEnumerable otherPhaseToCount = new(); double otherTotal = 0; - foreach(var phase in phases) + foreach (var phase in phases) { double sum = 0; if (o.MethodToData.TryGetValue(phase, out var data)) { - sum += showInclusiveCount ? data.InclusiveCount : data.ExclusiveCount; + sum += showInclusiveCount ? data.InclusiveCount : data.ExclusiveCount; } otherPhaseToCount[phase] = sum; otherTotal += sum; @@ -145,7 +145,7 @@ public static DataFrame Compare(this CPUProcessData cpuData, IEnumerable p.ProcessID == cpuData.ProcessID); @@ -192,23 +192,23 @@ public static DataFrame Compare(this CPUProcessData cpuData, IEnumerable(gcProcessData.BGCs.Select(gc => gc.Number)); var gen2Blocking = new HashSet(gcProcessData.Gen2Blocking.Select(gc => gc.Number)); - foreach(var majorPhase in phases) + foreach (var majorPhase in phases) { var phase = majorPhase; double gen0CountData = 0; double gen1CountData = 0; double bgcCountData = 0; double gen2BlockingCountData = 0; - + if (cpuData.PerGCData.TryGetValue(phase, out var gcToData)) { - foreach(var gc in gcToData) + foreach (var gc in gcToData) { var count = gc.Value.Values.Sum(g => g.Sum(gc => gc.InclusiveCount)); if (gen0s.Contains(gc.Key)) { - gen0CountData += count; + gen0CountData += count; } else if (gen1s.Contains(gc.Key)) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Common.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Common.cs index 338c84ce70c..a3d2e342ec0 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Common.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Common.cs @@ -25,15 +25,15 @@ public sealed class ChartInfo { public string? YAxisLabel { get; set; } = null; public string? XAxisLabel { get; set; } = null; - public double? Width { get; set; } = null; - public double? Height { get; set; } = null; + public double? Width { get; set; } = null; + public double? Height { get; set; } = null; } public static class ChartingHelpers { - internal static Layout.Layout ConstructLayout(string title, - string fieldName, - string xAxis, + internal static Layout.Layout ConstructLayout(string title, + string fieldName, + string xAxis, ChartInfo? chartInfo) { var layout = new Layout.Layout @@ -45,12 +45,12 @@ public static class ChartingHelpers if (chartInfo != null) { - if (chartInfo.Width.HasValue) + if (chartInfo.Width.HasValue) { layout.width = chartInfo.Width.Value; } - if (chartInfo.Height.HasValue) + if (chartInfo.Height.HasValue) { layout.height = chartInfo.Height.Value; } @@ -59,9 +59,9 @@ public static class ChartingHelpers return layout; } - internal static Layout.Layout ConstructLayout(string title, - IEnumerable fieldNames, - string xAxis, + internal static Layout.Layout ConstructLayout(string title, + IEnumerable fieldNames, + string xAxis, ChartInfo? chartInfo) { var layout = new Layout.Layout @@ -73,12 +73,12 @@ public static class ChartingHelpers if (chartInfo != null) { - if (chartInfo.Width.HasValue) + if (chartInfo.Width.HasValue) { layout.width = chartInfo.Width.Value; } - if (chartInfo.Height.HasValue) + if (chartInfo.Height.HasValue) { layout.height = chartInfo.Height.Value; } @@ -118,12 +118,12 @@ public static List Where(this IEnumerable data, Func predicate public static double Sum(this IEnumerable data, Func map) { double sum = 0; - if (data == null || data.Count() == 0) + if (data == null || data.Count() == 0) { return sum; } - foreach(var sourceItem in data) + foreach (var sourceItem in data) { sum += (double)map(sourceItem); } @@ -134,13 +134,13 @@ public static double Sum(this IEnumerable data, Func(this IEnumerable data, Func map) { int count = data.Count(); - if (data == null || count == 0) + if (data == null || count == 0) { return double.NaN; } double sum = 0; - foreach(var sourceItem in data) + foreach (var sourceItem in data) { sum += (double)map(sourceItem); } @@ -154,7 +154,7 @@ public static class ReflectionHelpers public static List GetDoubleValueFromFieldForCustomObjects(IEnumerable customObjects, string fieldName) { List values = new(); - foreach(var customObject in customObjects) + foreach (var customObject in customObjects) { double? val = GetDoubleValueBasedOnField(customObject, fieldName); values.Add(val.Value); // Let this except and bubble up to the user in case the field isn't found. @@ -166,7 +166,7 @@ public static List GetDoubleValueFromFieldForCustomObjects(IEnumerable GetDoubleValueForGCField(IEnumerable gcs, string fieldName) { List values = new(); - foreach(var gc in gcs) + foreach (var gc in gcs) { double? val = GetDoubleValueBasedOnField(gc, fieldName); values.Add(val.Value); // Let this except and bubble up to the user in case the field isn't found. @@ -231,7 +231,7 @@ public static string CreateMarkdown(this DataFrame dataFrame) // Add the 2 header rows. sb.Append("|"); - foreach(var columnName in columnNames) + foreach (var columnName in columnNames) { sb.Append(columnName); sb.Append("|"); @@ -241,7 +241,7 @@ public static string CreateMarkdown(this DataFrame dataFrame) sb.Clear(); sb.Append("|"); - foreach(var columnName in columnNames) + foreach (var columnName in columnNames) { sb.Append("------"); sb.Append("|"); @@ -280,7 +280,7 @@ public static void ToMarkdown(this DataFrame dataFrame, string path) // Add the 2 header rows. sb.Append("|"); - foreach(var columnName in columnNames) + foreach (var columnName in columnNames) { sb.Append(columnName); sb.Append("|"); @@ -290,7 +290,7 @@ public static void ToMarkdown(this DataFrame dataFrame, string path) sb.Clear(); sb.Append("|"); - foreach(var columnName in columnNames) + foreach (var columnName in columnNames) { sb.Append("------"); sb.Append("|"); @@ -339,19 +339,19 @@ public static DataFrame ConstructDataFrameFromCustomArrayData(object data) FieldInfo[] fieldsInfo = type.GetFields(); Dictionary columnsData = new(); - foreach(var field in fieldsInfo) + foreach (var field in fieldsInfo) { StringDataFrameColumn column = new(field.Name); columnsData[field.Name] = new StringDataFrameColumn(field.Name); } // For all data points, go through all the fields and append the values to the columns. - foreach(var datum in dataArray) + foreach (var datum in dataArray) { FieldInfo[] fields = type.GetFields(); // For each field in fields, get the value. - foreach(var field in fields) + foreach (var field in fields) { object obtainedValue = field.GetValue(datum); string obtainedValueAsString = obtainedValue.ToString(); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/AffinitizedAnalysis.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/AffinitizedAnalysis.cs index 1e84d510890..831684d70db 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/AffinitizedAnalysis.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/AffinitizedAnalysis.cs @@ -48,7 +48,7 @@ public static class AffinitizedAnalysis } cpuData.NumberOfSamples++; - gcThreadProcessorNumbers.Add(sampledProfileTraceData.ProcessorNumber); + gcThreadProcessorNumbers.Add(sampledProfileTraceData.ProcessorNumber); } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/Charting.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/Charting.cs index 71de597700d..567cba3c69b 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/Charting.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/Charting.cs @@ -14,10 +14,10 @@ public static PlotlyChart ChartGCData(string title, AxisInfo axisInfo, ChartInfo var scatter = new Scatter { - x = axisInfo.XAxis, - y = axisInfo.YAxis, - name = axisInfo.Name, - mode = "lines+markers", + x = axisInfo.XAxis, + y = axisInfo.YAxis, + name = axisInfo.Name, + mode = "lines+markers", showlegend = true, }; @@ -32,14 +32,14 @@ public static PlotlyChart ChartGCData(string title, IEnumerable axisIn title = title, }; - foreach(var axis in axisInfo) + foreach (var axis in axisInfo) { var scatter = new Scatter { - x = axis.XAxis, - y = axis.YAxis, - name = axis.Name, - mode = "lines+markers", + x = axis.XAxis, + y = axis.YAxis, + name = axis.Name, + mode = "lines+markers", showlegend = true, }; @@ -51,29 +51,29 @@ public static PlotlyChart ChartGCData(string title, IEnumerable axisIn public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, ChartInfo? chartInfo = null) { - Layout.Layout layout = ChartingHelpers.ConstructLayout(title : title, - fieldName : "Count", - xAxis : "Count", - chartInfo : chartInfo); + Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, + fieldName: "Count", + xAxis: "Count", + chartInfo: chartInfo); layout.yaxis2 = new Yaxis { title = axisInfo.Name, side = "right", overlaying = "y" }; List scatters = new(); var scatter = new Scatter { x = axisInfo.XAxis, - y = axisInfo.YAxis1, + y = axisInfo.YAxis1, yaxis = "y2", - mode = "lines+markers", - name = axisInfo.Name, + mode = "lines+markers", + name = axisInfo.Name, showlegend = true, }; var other = new Scatter { - x = axisInfo.XAxis, - y = axisInfo.YAxis2, - name = axisInfo.Name, - mode = "lines+markers", + x = axisInfo.XAxis, + y = axisInfo.YAxis2, + name = axisInfo.Name, + mode = "lines+markers", showlegend = true, }; @@ -86,53 +86,53 @@ public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, Char public static PlotlyChart ChartGCData(IEnumerable gcs, string title, string fieldName, - string xAxis = nameof(TraceGC.Number), + string xAxis = nameof(TraceGC.Number), ChartInfo? chartInfo = null) { - Layout.Layout layout = ChartingHelpers.ConstructLayout(title : title, - fieldName : fieldName, - xAxis : xAxis, - chartInfo : chartInfo); + Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, + fieldName: fieldName, + xAxis: xAxis, + chartInfo: chartInfo); IEnumerable y = ReflectionHelpers.GetDoubleValueForGCField(gcs, fieldName); IEnumerable x = ReflectionHelpers.GetDoubleValueForGCField(gcs, xAxis); var scatter = new Scatter { - x = x, - y = y, - name = fieldName, - mode = "lines+markers", + x = x, + y = y, + name = fieldName, + mode = "lines+markers", showlegend = true, }; return Chart.Plot(scatter, layout); } - public static PlotlyChart ChartGCData(IEnumerable gcs, + public static PlotlyChart ChartGCData(IEnumerable gcs, string title, IEnumerable<(string scatterName, string fieldName)> fields, string xAxis = nameof(TraceGC.Number), ChartInfo? chartInfo = null) { - Layout.Layout layout = ChartingHelpers.ConstructLayout(title : title, - fieldNames : fields.Select(f => f.fieldName), - xAxis : xAxis, - chartInfo : chartInfo); + Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, + fieldNames: fields.Select(f => f.fieldName), + xAxis: xAxis, + chartInfo: chartInfo); List scatters = new(); - foreach(var fieldName in fields) + foreach (var fieldName in fields) { IEnumerable y = ReflectionHelpers.GetDoubleValueForGCField(gcs, fieldName.fieldName); IEnumerable x = ReflectionHelpers.GetDoubleValueForGCField(gcs, xAxis); var scatter = new Scatter { - x = x, - y = y, + x = x, + y = y, showlegend = true, mode = "lines+markers", - name = fieldName.scatterName, + name = fieldName.scatterName, }; scatters.Add(scatter); @@ -142,29 +142,29 @@ public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, Char } public static PlotlyChart ChartGCData(object gcData, // Really an enumerable - string title, - IEnumerable<(string scatterName, string fieldName)> fields, - string xAxis, + string title, + IEnumerable<(string scatterName, string fieldName)> fields, + string xAxis, ChartInfo? chartInfo = null) { Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, fieldNames: fields.Select(f => f.fieldName), xAxis: xAxis, chartInfo: chartInfo); List scatters = new List(); - var customData = gcData as object[]; + var customData = gcData as object[]; if (customData == null) { throw new ArgumentException($"The input {nameof(gcData)} should be an IEnumerable."); } - foreach(var field in fields) + foreach (var field in fields) { IEnumerable y = ReflectionHelpers.GetDoubleValueFromFieldForCustomObjects(customData, field.fieldName); IEnumerable x = ReflectionHelpers.GetDoubleValueFromFieldForCustomObjects(customData, xAxis); var scatter = new Scatter { - x = x, - y = y, + x = x, + y = y, showlegend = true, mode = "lines+markers", name = field.scatterName, @@ -191,12 +191,12 @@ public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, Char { if (xAxis == nameof(TraceGC.Number)) { - int maxNumberOfGCs = gcData.Max(gc => gc.gcs.Count); - relativeGCIndex = Enumerable.Range(0, maxNumberOfGCs).Select(r => (double)r); + int maxNumberOfGCs = gcData.Max(gc => gc.gcs.Count); + relativeGCIndex = Enumerable.Range(0, maxNumberOfGCs).Select(r => (double)r); } } - foreach(var gcs in gcData) + foreach (var gcs in gcData) { IEnumerable y = ReflectionHelpers.GetDoubleValueForGCField(gcs.gcs, fieldName); @@ -213,10 +213,10 @@ public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, Char var scatter = new Scatter { - x = x, - y = y, - name = gcs.scatterName, - mode = "lines+markers", + x = x, + y = y, + name = gcs.scatterName, + mode = "lines+markers", showlegend = true }; @@ -230,14 +230,14 @@ public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, Char string title, string fieldName, IEnumerable<(string scatterName, Func filter)> filters, - string xAxis = nameof(TraceGC.Number), + string xAxis = nameof(TraceGC.Number), ChartInfo? chartInfo = null) { Layout.Layout layout = ChartingHelpers.ConstructLayout(title: title, fieldName: fieldName, xAxis: xAxis, chartInfo: chartInfo); List scatters = new(); - foreach(var filter in filters) + foreach (var filter in filters) { var filtered = gcs.Where(gc => filter.filter(gc)); IEnumerable y = ReflectionHelpers.GetDoubleValueForGCField(filtered, fieldName); @@ -245,11 +245,11 @@ public static PlotlyChart ChartGCData(string title, MultiAxisInfo axisInfo, Char var scatter = new Scatter { - x = x, - y = y, + x = x, + y = y, showlegend = true, mode = "lines+markers", - name = filter.scatterName, + name = filter.scatterName, }; scatters.Add(scatter); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCAnalysisExt.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCAnalysisExt.cs index 92dde783f88..b0cfc8ee54e 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCAnalysisExt.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCAnalysisExt.cs @@ -10,7 +10,7 @@ public static List GetProcessGCData(this Analyzer analyzer, strin { if (!analyzer.AllGCProcessData.TryGetValue(processName, out var vals)) { - return new List(); + return new List(); } return vals; @@ -77,7 +77,7 @@ public static DataFrame Summarize(this GCProcessData processData, IEnumerable gc.HeapSizeBeforeMB)); @@ -135,7 +135,7 @@ void AddStr(string c, object val) AddStr("Gen1 Average Promoted (mb) / heap", gen1AvgPromotedPerHeap); AddStr("Gen0 Average Speed (mb/ms) / heap", gen0AvgSpeedPerHeap); - AddStr("Gen1 Average Speed (mb/ms) / heap", gen1AvgSpeedPerHeap); + AddStr("Gen1 Average Speed (mb/ms) / heap", gen1AvgSpeedPerHeap); return new DataFrame(criteria, value); } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCProcessData.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCProcessData.cs index a6eb3d32cfa..ab0113bb008 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCProcessData.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCProcessData.cs @@ -11,8 +11,8 @@ public sealed class GCProcessData { "gc count", (gc) => gc.Stats.Count }, { "non induced gc count", (gc) => gc.Stats.Count - gc.GCs.Count(g => g.Reason == GCReason.Induced)}, { "induced gc count", (gc) => gc.GCs.Count(g => g.Reason == GCReason.Induced)}, - { "total allocated (mb)", (gc) => gc.Stats.TotalAllocatedMB }, - { "max size peak (mb)", (gc) => gc.Stats.MaxSizePeakMB }, + { "total allocated (mb)", (gc) => gc.Stats.TotalAllocatedMB }, + { "max size peak (mb)", (gc) => gc.Stats.MaxSizePeakMB }, { "total pause time (msec)", (gc) => gc.Stats.TotalPauseTimeMSec }, { "gc pause time %", (gc) => gc.Stats.GetGCPauseTimePercentage() }, { "avg. heap size (mb)", (gc) => gc.GCs.Average(g => g.HeapSizeBeforeMB) }, @@ -21,13 +21,13 @@ public sealed class GCProcessData private readonly Lazy _joinAnalysis; - public GCProcessData(TraceProcess process, TraceLoadedDotNetRuntime managedProcess, Dictionary gcThreadsToHeapNumber, Analyzer parent, double durationMSec) + public GCProcessData(TraceProcess process, TraceLoadedDotNetRuntime managedProcess, Dictionary gcThreadsToHeapNumber, Analyzer parent, double durationMSec) { ProcessName = process.Name; ProcessID = process.ProcessID; CommandLine = process.CommandLine; GCs = managedProcess.GC.GCs; - DurationMSec = durationMSec; + DurationMSec = durationMSec; Stats = managedProcess.GC.Stats(); Generations = managedProcess.GC.Generations(); Gen2Blocking = GCs.Where(gc => gc.Generation == 2 && gc.Type != GCType.BackgroundGC); @@ -89,6 +89,6 @@ public GCProcessData(TraceProcess process, TraceLoadedDotNetRuntime managedProce } } - public JoinAnalysis GetJoinAnalysis() => _joinAnalysis.Value; + public JoinAnalysis GetJoinAnalysis() => _joinAnalysis.Value; } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCSummarization.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCSummarization.cs index 36ae392bb03..6c4e87d64b4 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCSummarization.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/GCSummarization.cs @@ -11,9 +11,9 @@ public static IEnumerable Summarize(this Analyzer analyzer, int topN, { List<(double value, DataFrame summary)> summaryData = new(); - foreach(var processes in analyzer.AllGCProcessData.Values) + foreach (var processes in analyzer.AllGCProcessData.Values) { - foreach(var process in processes) + foreach (var process in processes) { summaryData.Add((ReflectionHelpers.GetDoubleValueForGCStatsField(process.Stats, criteriaInGCStats), Summarize(analyzer, process.ProcessID))); } @@ -27,7 +27,7 @@ public static IEnumerable Summarize(this Analyzer analyzer, string pr List dataFrames = new(); var processes = analyzer.GetProcessGCData(processName); - foreach(var processData in processes) + foreach (var processData in processes) { dataFrames.Add(analyzer.Summarize(processData.ProcessID)); } @@ -40,7 +40,7 @@ internal static DataFrame Summarize(this Analyzer analyzer, int processID) StringDataFrameColumn criteria = new(" "); StringDataFrameColumn value = new("Values"); - void AddStr(string c, object val) + void AddStr(string c, object val) { criteria.Append(c); @@ -55,7 +55,7 @@ void AddStr(string c, object val) } GCProcessData? processData = null; - foreach(var val in analyzer.AllGCProcessData.Values) + foreach (var val in analyzer.AllGCProcessData.Values) { processData = val.FirstOrDefault(v => v.ProcessID == processID); if (processData != null) @@ -73,7 +73,7 @@ void AddStr(string c, object val) AddStr("Max Size Peak MB", processData.Stats.MaxSizePeakMB); // Counts. - AddStr("GC Count", processData.Stats.Count); + AddStr("GC Count", processData.Stats.Count); AddStr("Heap Count", processData.Stats.HeapCount); AddStr("Gen0 Count", processData.Generations[0].Count); AddStr("Gen1 Count", processData.Generations[1].Count); @@ -112,11 +112,11 @@ void AddStr(string c, object val) AddStr("Avg. Gen0 Pause Time (ms)", (gen0.Count() > 0 ? gen0.Average(gc => gc.PauseDurationMSec) : double.NaN)); AddStr("Avg. Gen1 Pause Time (ms)", (gen1.Count() > 0 ? gen1.Average(gc => gc.PauseDurationMSec) : double.NaN)); - AddStr("Avg. Gen0 Promoted (mb)", (gen0.Count() > 0 ? gen0.Average(gc => gc.PromotedMB) : double.NaN)); + AddStr("Avg. Gen0 Promoted (mb)", (gen0.Count() > 0 ? gen0.Average(gc => gc.PromotedMB) : double.NaN)); AddStr("Avg. Gen1 Promoted (mb)", (gen1.Count() > 0 ? gen1.Average(gc => gc.PromotedMB) : double.NaN)); var gen0Speed = processData.Generations[0].TotalPromotedMB / processData.Generations[0].TotalPauseTimeMSec; - AddStr("Avg. Gen0 Speed (mb/ms)", gen0Speed); + AddStr("Avg. Gen0 Speed (mb/ms)", gen0Speed); var gen1Speed = processData.Generations[1].TotalPromotedMB / processData.Generations[1].TotalPauseTimeMSec; AddStr("Avg. Gen1 Speed (mb/ms)", gen1Speed); @@ -209,14 +209,14 @@ void AddStr(string c, string baselineVal, IEnumerable otherVals) IEnumerable gen1 = processData.GCs.Where(gc => gc.Generation == 1); Dictionary> gen0Cache = new(); - foreach(var other in others) + foreach (var other in others) { var gen0s = other.GCs.Where(gc => gc.Generation == 0); gen0Cache[other] = gen0s; } Dictionary> gen1Cache = new(); - foreach(var other in others) + foreach (var other in others) { var gen1s = other.GCs.Where(gc => gc.Generation == 1); gen1Cache[other] = gen1s; @@ -312,7 +312,7 @@ void AddStr(string c, string baselineVal, IEnumerable otherVals) double currentAllocRatio = processData.Stats.TotalAllocatedMB / maxTotalAllocated; Dictionary ratioMap = new(); - foreach(var o in others) + foreach (var o in others) { ratioMap[o] = o.Stats.TotalAllocatedMB / maxTotalAllocated; } @@ -331,12 +331,12 @@ void AddStr(string c, string baselineVal, IEnumerable otherVals) Add("BGC Count", processData.BGCs.Count(), others.Select(p => (double)p.BGCs.Count())); // Pauses - Add("Total Pause Time MSec", processData.Stats.TotalPauseTimeMSec / currentAllocRatio, others.Select(p => p.Stats.TotalPauseTimeMSec / ratioMap[p] )); - Add("Gen0 Total Pause Time MSec", processData.Generations[0].TotalPauseTimeMSec / currentAllocRatio, others.Select(p => p.Generations[0].TotalPauseTimeMSec / ratioMap[p] )); - Add("Gen1 Total Pause Time MSec", processData.Generations[1].TotalPauseTimeMSec / currentAllocRatio, others.Select(p => p.Generations[1].TotalPauseTimeMSec / ratioMap[p] )); - Add("Ephemeral Total Pause Time MSec", (processData.Generations[0].TotalPauseTimeMSec + processData.Generations[1].TotalPauseTimeMSec) / currentAllocRatio, others.Select(p => (p.Generations[0].TotalPauseTimeMSec + p.Generations[1].TotalPauseTimeMSec) / (ratioMap[p] ))); + Add("Total Pause Time MSec", processData.Stats.TotalPauseTimeMSec / currentAllocRatio, others.Select(p => p.Stats.TotalPauseTimeMSec / ratioMap[p])); + Add("Gen0 Total Pause Time MSec", processData.Generations[0].TotalPauseTimeMSec / currentAllocRatio, others.Select(p => p.Generations[0].TotalPauseTimeMSec / ratioMap[p])); + Add("Gen1 Total Pause Time MSec", processData.Generations[1].TotalPauseTimeMSec / currentAllocRatio, others.Select(p => p.Generations[1].TotalPauseTimeMSec / ratioMap[p])); + Add("Ephemeral Total Pause Time MSec", (processData.Generations[0].TotalPauseTimeMSec + processData.Generations[1].TotalPauseTimeMSec) / currentAllocRatio, others.Select(p => (p.Generations[0].TotalPauseTimeMSec + p.Generations[1].TotalPauseTimeMSec) / (ratioMap[p]))); Add("Blocking Gen2 Total Pause Time MSec", processData.Gen2Blocking.Sum(gc => gc.PauseDurationMSec) / currentAllocRatio, others.Select(p => (double)p.Gen2Blocking.Sum(gc => gc.PauseDurationMSec) / ratioMap[p])); - Add("BGC Total Pause Time MSec", processData.BGCs.Sum(gc => gc.PauseDurationMSec) / currentAllocRatio, others.Select(p => p.BGCs.Sum(gc => gc.PauseDurationMSec) / ratioMap[p] )); + Add("BGC Total Pause Time MSec", processData.BGCs.Sum(gc => gc.PauseDurationMSec) / currentAllocRatio, others.Select(p => p.BGCs.Sum(gc => gc.PauseDurationMSec) / ratioMap[p])); Add("GC Pause Time %", processData.Stats.GetGCPauseTimePercentage(), others.Select(gc => gc.Stats.GetGCPauseTimePercentage())); @@ -346,14 +346,14 @@ void AddStr(string c, string baselineVal, IEnumerable otherVals) IEnumerable gen1 = processData.GCs.Where(gc => gc.Generation == 1); Dictionary> gen0Cache = new(); - foreach(var other in others) + foreach (var other in others) { var gen0s = other.GCs.Where(gc => gc.Generation == 0); gen0Cache[other] = gen0s; } Dictionary> gen1Cache = new(); - foreach(var other in others) + foreach (var other in others) { var gen1s = other.GCs.Where(gc => gc.Generation == 1); gen1Cache[other] = gen1s; @@ -417,7 +417,7 @@ string GetDifferenceString(double baselineValue, double comparandValue, string n else { - return string.Empty; + return string.Empty; } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/JoinAnalysis.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/JoinAnalysis.cs index dca9c9f2066..bdc84de057c 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/JoinAnalysis.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GCAnalysis/JoinAnalysis.cs @@ -26,9 +26,9 @@ public sealed class JoinAnalysis private readonly List _wakeupInfo = new(); internal sealed class IntermediateJoinData - { + { public GcJoinType Type { get; set; } - public GcJoinTime Time { get; set; } + public GcJoinTime Time { get; set; } public double Timestamp { get; set; } public int JoinID { get; set; } public int ThreadID { get; set; } @@ -38,7 +38,7 @@ internal sealed class IntermediateJoinData // 1. For a particular join: // 1. Extract the last join event and note the restart start and stop times // 2. For each other threads that aren't the last join one: - // 1. Compute the wake up time: Each Join End - Last Join Event's Restart start time. + // 1. Compute the wake up time: Each Join End - Last Join Event's Restart start time. public JoinAnalysis(GCProcessData gcProcessData) { TraceLogEventSource eventSource = gcProcessData.Parent.TraceLog.Events.GetSource(); @@ -63,40 +63,40 @@ public JoinAnalysis(GCProcessData gcProcessData) IEnumerable lastJoins = joinEvents.Where(e => e.Type == GcJoinType.LastJoin && e.Time == GcJoinTime.Start); - foreach(var j in lastJoins) + foreach (var j in lastJoins) { // Find the closest restart start and stop events corresponding to this last join for this join id. IntermediateJoinData lastJoin = j; - IntermediateJoinData firstRestartStart = joinEvents.First(e => e.Timestamp > lastJoin.Timestamp && - e.ThreadID == j.ThreadID && - e.Time == GcJoinTime.Start && + IntermediateJoinData firstRestartStart = joinEvents.First(e => e.Timestamp > lastJoin.Timestamp && + e.ThreadID == j.ThreadID && + e.Time == GcJoinTime.Start && e.Type == GcJoinType.Restart); - IntermediateJoinData firstRestartEnd = joinEvents.First(e => e.Timestamp > lastJoin.Timestamp && - e.ThreadID == j.ThreadID && - e.Time == GcJoinTime.End && + IntermediateJoinData firstRestartEnd = joinEvents.First(e => e.Timestamp > lastJoin.Timestamp && + e.ThreadID == j.ThreadID && + e.Time == GcJoinTime.End && e.Type == GcJoinType.Restart); // Find all the other join ends from other threads for this join id. - IEnumerable otherJoins = joinEvents.Where(j => j.JoinID == lastJoin.JoinID && - j.ThreadID != lastJoin.ThreadID && - j.Time == GcJoinTime.End && - j.Type == GcJoinType.Join && + IEnumerable otherJoins = joinEvents.Where(j => j.JoinID == lastJoin.JoinID && + j.ThreadID != lastJoin.ThreadID && + j.Time == GcJoinTime.End && + j.Type == GcJoinType.Join && j.Timestamp > firstRestartStart.Timestamp) .OrderBy(o => o.Timestamp - firstRestartStart.Timestamp); JoinWakeUpInfo info = new JoinWakeUpInfo { - JoinID = lastJoin.JoinID, - RestartThreadID = firstRestartStart.ThreadID, + JoinID = lastJoin.JoinID, + RestartThreadID = firstRestartStart.ThreadID, RestartStartTime = firstRestartStart.Timestamp, - RestartStopTime = firstRestartEnd.Timestamp, - LastJoinTime = lastJoin.Timestamp, + RestartStopTime = firstRestartEnd.Timestamp, + LastJoinTime = lastJoin.Timestamp, }; HashSet remainingThreads = new HashSet(gcProcessData.GCThreadIDsToHeapNumbers.Keys); // For all the other join ends, compute the wake up times using: (join end time - restart start time). - foreach(var otherJoin in otherJoins) + foreach (var otherJoin in otherJoins) { if (remainingThreads.Count == 0) { diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Statistics.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Statistics.cs index fd54e9a639e..85c8821a8ec 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Statistics.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/Statistics.cs @@ -7,8 +7,8 @@ public static double Percentile(this IEnumerable seq, double percentile) if (seq.Count() == 0) { return double.NaN; - } - + } + var elements = seq.ToArray(); Array.Sort(elements); double realIndex = percentile * (elements.Length - 1); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/TraceSummarization.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/TraceSummarization.cs index 3267f4e2ede..1982b6b6e5e 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/TraceSummarization.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/TraceSummarization.cs @@ -7,8 +7,8 @@ namespace GC.Analysis.API internal sealed class FirstLastData { public double FirstTimeStamp { get; set; } - public double LastTimeStamp { get; set; } - public int Count { get; set; } + public double LastTimeStamp { get; set; } + public int Count { get; set; } } public static class TraceSummarization @@ -22,14 +22,14 @@ public static IEnumerable SummarizeTrace(this Analyzer analyzer, stri return Enumerable.Empty(); } - var traceLog = analyzer.TraceLog; - var eventSource = traceLog.Events.GetSource(); + var traceLog = analyzer.TraceLog; + var eventSource = traceLog.Events.GetSource(); HashSet processIds = new HashSet(processData.Select(p => p.ProcessID)); - Dictionary cpuData = new(); - Dictionary cswitchData = new(); - Dictionary readyThreadCount = new(); + Dictionary cpuData = new(); + Dictionary cswitchData = new(); + Dictionary readyThreadCount = new(); eventSource.Kernel.ThreadCSwitch += (data) => { @@ -40,7 +40,7 @@ public static IEnumerable SummarizeTrace(this Analyzer analyzer, stri if (!cswitchData.TryGetValue(data.ProcessID, out var firstLast)) { - cswitchData[data.ProcessID] = firstLast = new() + cswitchData[data.ProcessID] = firstLast = new() { FirstTimeStamp = data.TimeStampRelativeMSec }; @@ -88,23 +88,23 @@ public static IEnumerable SummarizeTrace(this Analyzer analyzer, stri List dataFrames = new(); // For each Process. - foreach(var process in processData) + foreach (var process in processData) { int processId = process.ProcessID; - StringDataFrameColumn criteria = new($"Process ID: {processId}"); - StringDataFrameColumn startMS = new("Start (ms)"); + StringDataFrameColumn criteria = new($"Process ID: {processId}"); + StringDataFrameColumn startMS = new("Start (ms)"); StringDataFrameColumn startGCNumber = new("Start GC Index"); - StringDataFrameColumn endMS = new("End (ms)"); - StringDataFrameColumn endGCNumber = new("End GC Index"); - StringDataFrameColumn notes = new("Notes"); + StringDataFrameColumn endMS = new("End (ms)"); + StringDataFrameColumn endGCNumber = new("End GC Index"); + StringDataFrameColumn notes = new("Notes"); IEnumerable traceGCs = process.GCs; // GC Data criteria.Append("GC"); var firstGC = traceGCs.First(gc => gc.Type != GCType.BackgroundGC); - var lastGC = traceGCs.Last(gc => gc.Type != GCType.BackgroundGC); + var lastGC = traceGCs.Last(gc => gc.Type != GCType.BackgroundGC); startMS.Append(DataFrameHelpers.Round2(firstGC.StartRelativeMSec).ToString()); startGCNumber.Append(firstGC.Number.ToString()); endMS.Append(DataFrameHelpers.Round2(lastGC.StartRelativeMSec + lastGC.DurationMSec).ToString()); @@ -115,7 +115,7 @@ public static IEnumerable SummarizeTrace(this Analyzer analyzer, stri { // Get range of the first and last. double firstTimestamp = firstLast.FirstTimeStamp; - double lastTimestamp = firstLast.LastTimeStamp; + double lastTimestamp = firstLast.LastTimeStamp; var encompassedGCs = traceGCs.Where(gc => { @@ -124,7 +124,7 @@ public static IEnumerable SummarizeTrace(this Analyzer analyzer, stri (gc.PauseDurationMSec + gc.PauseStartRelativeMSec < lastTimestamp); // And all GCs before the last timestamp. }); int startGCIdx = encompassedGCs.FirstOrDefault()?.Number ?? -1; - int endGCIdx = encompassedGCs.LastOrDefault()?.Number ?? -1; + int endGCIdx = encompassedGCs.LastOrDefault()?.Number ?? -1; return (startGCIdx, endGCIdx); } @@ -161,7 +161,7 @@ public static IEnumerable SummarizeTrace(this Analyzer analyzer, stri if (readyThreadCount.TryGetValue(processId, out var r)) { - notes.Append($"Ready Thread Event Count: {r}"); + notes.Append($"Ready Thread Event Count: {r}"); } else diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/Presentation/MarkdownReportBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/Presentation/MarkdownReportBuilder.cs index 7c31a41e94a..8c5249b39e5 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/Presentation/MarkdownReportBuilder.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/Presentation/MarkdownReportBuilder.cs @@ -7,7 +7,7 @@ namespace GC.Infrastructure.Core.UnitTests.Presentation public class MarkdownReportBuilderTests { [TestMethod] - public void CopySectionFromMarkdown_CopySuccessful1_Successful() + public void CopySectionFromMarkdown_CopySuccessful1_Successful() { string text = "# Section1\na\nb\nc\nd\n# Section 2"; string details = MarkdownReportBuilder.CopySectionFromMarkDown(text, "Section1"); @@ -15,7 +15,7 @@ public void CopySectionFromMarkdown_CopySuccessful1_Successful() } [TestMethod] - public void CopySectionFromMarkdown_CopySuccessful2_Successful() + public void CopySectionFromMarkdown_CopySuccessful2_Successful() { string text = @"# Summary | | Working Set (MB)|Private Memory (MB)|Requests/sec diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/AnalyzeTrace.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/AnalyzeTrace.cs index 6a477a24019..0fad6796a0f 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/AnalyzeTrace.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/AnalyzeTrace.cs @@ -7,7 +7,7 @@ namespace GC.Infrastructure.Core.Analysis { public static class AnalyzeTrace { - public static string GetExecutionDetailKeyForGCPerfSim (string runName, string corerunName) => $"{runName}.{corerunName}.0"; + public static string GetExecutionDetailKeyForGCPerfSim(string runName, string corerunName) => $"{runName}.{corerunName}.0"; public static GCProcessData? GetGCProcessDataForGCPerfSim(Analyzer analyzer) { @@ -18,7 +18,7 @@ public static class AnalyzeTrace { p = analyzer.AllGCProcessData.First().Value.First(); } - + else // ETL* traces. { p = analyzer.GetProcessGCData("corerun").FirstOrDefault(); @@ -74,7 +74,7 @@ public static class AnalyzeTrace else { - d[corerunName] = processData = new ResultItem(p, run.Key, corerun); + d[corerunName] = processData = new ResultItem(p, run.Key, corerun); } } } @@ -86,7 +86,7 @@ public static class AnalyzeTrace public static IReadOnlyList GetComparisons(GCPerfSimConfiguration configuration, Func keyFunctor) { - ConcurrentDictionary> runToCorerunData = GetTracesFromConfiguration(configuration); + ConcurrentDictionary> runToCorerunData = GetTracesFromConfiguration(configuration); List allComparisonResults = new(); // First corerun is the base. @@ -143,14 +143,14 @@ public static IReadOnlyList GetComparisons(GCPerfSimConfigurat public static Dictionary GetComparisons(string baselinePath, string runPath) { Analyzer baselineAnalyzer = AnalyzerManager.GetAnalyzer(baselinePath); - GCProcessData? baselineProcessData = GetGCProcessDataForGCPerfSim(baselineAnalyzer); + GCProcessData? baselineProcessData = GetGCProcessDataForGCPerfSim(baselineAnalyzer); ResultItem baselineResultItem = (baselineProcessData != null) ? new ResultItem(baselineProcessData, baselinePath, baselinePath) : ResultItem.GetNullItem(baselinePath, baselinePath); - Analyzer runAnalyzer = AnalyzerManager.GetAnalyzer(runPath); - GCProcessData? runProcessData = GetGCProcessDataForGCPerfSim(runAnalyzer); - ResultItem runResultItem = (runProcessData != null) + Analyzer runAnalyzer = AnalyzerManager.GetAnalyzer(runPath); + GCProcessData? runProcessData = GetGCProcessDataForGCPerfSim(runAnalyzer); + ResultItem runResultItem = (runProcessData != null) ? new ResultItem(runProcessData, runPath, runPath) : ResultItem.GetNullItem(runPath, runPath); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/MetricResult.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/MetricResult.cs index f3af14ff82c..449d5dd3ce9 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/MetricResult.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/MetricResult.cs @@ -25,7 +25,7 @@ public sealed class MetricResult public double BaselineValue { get; } public double ComparandValue { get; } public double Delta { get; } - public double DeltaPercent => BaselineValue != 0 ? Math.Round(Delta / BaselineValue, 2) * 100.0 + public double DeltaPercent => BaselineValue != 0 ? Math.Round(Delta / BaselineValue, 2) * 100.0 : double.NaN; public override string ToString() => $"{Key} | {MetricName} | {BaselineValue} | {ComparandValue} | {DeltaPercent}"; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResult.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResult.cs index 803c9f7e0c9..60150f4d4c9 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResult.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResult.cs @@ -36,7 +36,7 @@ public MicrobenchmarkComparisonResult(MicrobenchmarkResult baseline, Microbenchm { if (!Baseline.OtherMetrics.TryGetValue(metric, out var baselineMetric)) { - return null; + return null; } if (!baselineMetric.HasValue) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResults.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResults.cs index 41460498d1f..79d2f8eccee 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResults.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkComparisonResults.cs @@ -6,13 +6,13 @@ public sealed class MicrobenchmarkComparisonResults { public MicrobenchmarkComparisonResults(string baselineName, string runName, IEnumerable comparisons) { - Comparisons = comparisons; - BaselineName = baselineName; - RunName = runName; + Comparisons = comparisons; + BaselineName = baselineName; + RunName = runName; } public string BaselineName { get; } - public string RunName { get; } + public string RunName { get; } public string MarkdownIdentifier => $"#{BaselineName.ToLowerInvariant()}-vs-{RunName.ToLowerInvariant()}"; public IEnumerable Comparisons { get; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResults.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResults.cs index aadc4943089..2af39abd257 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResults.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResults.cs @@ -24,7 +24,7 @@ public sealed class MicrobenchmarkResult { { "number of iterations", (Statistics stats) => stats.N }, { "min", (Statistics stats) => stats.Min }, - { "max", (Statistics stats) => stats.Max }, + { "max", (Statistics stats) => stats.Max }, { "median", (Statistics stats) => stats.Median }, { "q1", (Statistics stats) => stats.Q1 }, { "q3", (Statistics stats) => stats.Q3 }, @@ -83,7 +83,7 @@ public sealed class ConfidenceInterval public int? Level { get; set; } public double? Margin { get; set; } public double? Lower { get; set; } - public double? Upper { get; set; } + public double? Upper { get; set; } } public sealed class Descriptor @@ -186,4 +186,4 @@ public sealed class Statistics public ConfidenceInterval? ConfidenceInterval { get; set; } public Percentiles Percentiles { get; set; } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResultsAnalyzer.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResultsAnalyzer.cs index 850fd7bafe3..4ad9158e74c 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResultsAnalyzer.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/Microbenchmarks/MicrobenchmarkResultsAnalyzer.cs @@ -46,7 +46,7 @@ public static class MicrobenchmarkResultsAnalyzer { Dictionary analyzers = AnalyzerManager.GetAllAnalyzers(outputPathForRun); - foreach(var analyzer in analyzers) + foreach (var analyzer in analyzers) { List allPertinentProcesses = analyzer.Value.GetProcessGCData("dotnet"); List corerunProcesses = analyzer.Value.GetProcessGCData("corerun"); @@ -101,11 +101,11 @@ public static IReadOnlyList GetComparisons(Micr { foreach (var comparison in configuration.Output.run_comparisons) { - string[] breakup = comparison.Split(",", StringSplitOptions.TrimEntries); + string[] breakup = comparison.Split(",", StringSplitOptions.TrimEntries); string baselineName = breakup[0]; - string runName = breakup[1]; + string runName = breakup[1]; - Run run = runResults.Keys.FirstOrDefault(k => string.CompareOrdinal(k.Name, runName) == 0); + Run run = runResults.Keys.FirstOrDefault(k => string.CompareOrdinal(k.Name, runName) == 0); Run baselineRun = runResults.Keys.FirstOrDefault(k => string.CompareOrdinal(k.Name, baselineName) == 0); List microbenchmarkResults = new(); @@ -139,11 +139,11 @@ public static IReadOnlyList GetComparisons(Micr KeyValuePair> baselineResult = baselineName != null ? runResults.First(r => r.Key.Name == baselineName) : runResults.First(); // For each run, we want to grab it and it's baseline and then do a per microbenchmark association. - foreach(var runResult in runResults) + foreach (var runResult in runResults) { Run run = runResult.Key; string runName = run.Name; - + if (string.CompareOrdinal(runName, baselineName) == 0) { continue; @@ -172,7 +172,7 @@ public static IReadOnlyList GetComparisons(Micr } } - return comparisonResults; + return comparisonResults; } } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/ProcessExecutionDetails.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/ProcessExecutionDetails.cs index e1cc3e9187c..c33802d8bb1 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/ProcessExecutionDetails.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Analysis/ProcessExecutionDetails.cs @@ -9,12 +9,12 @@ public sealed class ProcessExecutionDetails string standardOut, int exitCode) { - Key = key; - CommandlineArgs = commandlineArgs; + Key = key; + CommandlineArgs = commandlineArgs; EnvironmentVariables = environmentVariables; - StandardError = standardError; - StandardOut = standardOut; - ExitCode = exitCode; + StandardError = standardError; + StandardOut = standardOut; + ExitCode = exitCode; } public string Key { get; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ASPNetBenchmarks.CommandBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ASPNetBenchmarks.CommandBuilder.cs index 89e46b10813..95847f4fe1d 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ASPNetBenchmarks.CommandBuilder.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ASPNetBenchmarks.CommandBuilder.cs @@ -4,7 +4,7 @@ namespace GC.Infrastructure.Core.CommandBuilders { - public static class ASPNetBenchmarksCommandBuilder + public static class ASPNetBenchmarksCommandBuilder { public static (string, string) Build(ASPNetBenchmarksConfiguration configuration, KeyValuePair run, KeyValuePair benchmarkNameToCommand, OS os) { @@ -40,8 +40,8 @@ public static (string, string) Build(ASPNetBenchmarksConfiguration configuration if (string.CompareOrdinal(env.Key, "DOTNET_GCLogFile") == 0) { string fileNameOfLog = Path.GetFileName(env.Value); - commandStringBuilder.Append( $" --application.options.downloadFiles \"*{fileNameOfLog}.log\" " ); - commandStringBuilder.Append( $" --application.options.downloadFilesOutput \"{Path.Combine(configuration.Output!.Path, run.Key, $"{benchmarkNameToCommand.Key}_GCLog")}\" " ); + commandStringBuilder.Append($" --application.options.downloadFiles \"*{fileNameOfLog}.log\" "); + commandStringBuilder.Append($" --application.options.downloadFilesOutput \"{Path.Combine(configuration.Output!.Path, run.Key, $"{benchmarkNameToCommand.Key}_GCLog")}\" "); } commandStringBuilder.Append($" --application.environmentVariables {env.Key}={variable} "); @@ -51,9 +51,9 @@ public static (string, string) Build(ASPNetBenchmarksConfiguration configuration // If the TraceConfiguration Key is specified in the yaml and if (configuration.TraceConfigurations != null && !string.Equals(configuration.TraceConfigurations.Type, "none", StringComparison.OrdinalIgnoreCase)) { - CollectType collectType = TraceCollector.StringToCollectTypeMap[configuration.TraceConfigurations.Type]; + CollectType collectType = TraceCollector.StringToCollectTypeMap[configuration.TraceConfigurations.Type]; string collectionCommand = TraceCollector.WindowsCollectTypeMap[collectType]; - collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", ""); + collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", ""); string traceFileSuffix = ".etl.zip"; // Add specific commands. @@ -125,7 +125,7 @@ public static (string, string) Build(ASPNetBenchmarksConfiguration configuration if (!string.IsNullOrEmpty(configuration.benchmark_settings.override_arguments)) { List> overrideCommands = GetCrankArgsAsList(configuration.benchmark_settings.override_arguments); - if (overrideCommands.Count > 0) + if (overrideCommands.Count > 0) { // Take the current commands and first replace all the keys that match the override commands. // Subsequently, add the new overrides and then convert the key-value pair list back to a string. diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/GCPerfSim.CommandBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/GCPerfSim.CommandBuilder.cs index 8a1d3d16123..11099d18f22 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/GCPerfSim.CommandBuilder.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/GCPerfSim.CommandBuilder.cs @@ -21,7 +21,7 @@ public static (string, string) BuildForLocal(GCPerfSimConfiguration configuratio string processName = corerunOverride.Path; Dictionary parameters = new(); - foreach(var p in configuration.gcperfsim_configurations.Parameters) + foreach (var p in configuration.gcperfsim_configurations.Parameters) { parameters[p.Key] = p.Value; } @@ -37,7 +37,7 @@ public static (string, string) BuildForLocal(GCPerfSimConfiguration configuratio // Construct the command line with the appropriate parameters. StringBuilder sb = new(); - foreach(var p in parameters) + foreach (var p in parameters) { sb.Append($" -{p.Key} {p.Value}"); } @@ -80,7 +80,7 @@ public static (string, string) BuildForServer(GCPerfSimConfiguration configurati // GCPerfSim Configurations. Dictionary parameters = new(); - foreach(var p in configuration.gcperfsim_configurations!.Parameters) + foreach (var p in configuration.gcperfsim_configurations!.Parameters) { parameters[p.Key] = p.Value; } @@ -131,7 +131,7 @@ public static (string, string) BuildForServer(GCPerfSimConfiguration configurati // Add name of output. string extension = os == OS.Windows ? "etl.zip" : "nettrace"; - commandStringBuilder.Append($" --application.options.traceOutput {Path.Combine(configuration.Output!.Path, run.Key, run.Key + "." + corerunOverride.Key + "." + iterationIdx + "." + collectType + "." + extension)} "); + commandStringBuilder.Append($" --application.options.traceOutput {Path.Combine(configuration.Output!.Path, run.Key, run.Key + "." + corerunOverride.Key + "." + iterationIdx + "." + collectType + "." + extension)} "); } if (corerunOverride.Value.environment_variables != null) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/Microbenchmark.CommandBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/Microbenchmark.CommandBuilder.cs index 33d405ba6dd..90b90d04691 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/Microbenchmark.CommandBuilder.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/Microbenchmark.CommandBuilder.cs @@ -14,7 +14,7 @@ public static (string, string) Build(MicrobenchmarkConfiguration configuration, string command = $"run -f {frameworkVersion} --filter \"{filter}\" -c Release --noOverwrite --no-build"; // [Optional] Add corerun. - if (!string.IsNullOrEmpty(run.Value.corerun)) + if (!string.IsNullOrEmpty(run.Value.corerun)) { command += $" --corerun {run.Value.corerun}"; } @@ -28,9 +28,9 @@ public static (string, string) Build(MicrobenchmarkConfiguration configuration, } // Add bdn arguments and output that must be added to the --bdn-arguments part of the command. - if (!string.IsNullOrEmpty(configuration.MicrobenchmarkConfigurations.bdn_arguments) || !string.IsNullOrEmpty(configuration.Output.Path) || ( run.Value.environment_variables != null && run.Value.environment_variables.Count != 0)) + if (!string.IsNullOrEmpty(configuration.MicrobenchmarkConfigurations.bdn_arguments) || !string.IsNullOrEmpty(configuration.Output.Path) || (run.Value.environment_variables != null && run.Value.environment_variables.Count != 0)) { - command += $" {configuration.MicrobenchmarkConfigurations.bdn_arguments}"; + command += $" {configuration.MicrobenchmarkConfigurations.bdn_arguments}"; // Add artifacts. if (!string.IsNullOrEmpty(configuration.Output.Path)) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/ASPNetBenchmark.Configuration.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/ASPNetBenchmark.Configuration.cs index 35a1d3eb45c..69386e42802 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/ASPNetBenchmark.Configuration.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/ASPNetBenchmark.Configuration.cs @@ -57,7 +57,7 @@ public static ASPNetBenchmarksConfiguration Parse(string path) } // Checks if mandatory arguments are specified in the configuration. - if (configuration.Output == null) + if (configuration.Output == null) { throw new ArgumentNullException($"{nameof(ASPNetBenchmarksConfigurationParser)}: {nameof(configuration.Output)} is null. Check the syntax of the configuration."); } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/Common.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/Common.cs index 633edc41cf1..464fd6afb8b 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/Common.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/Common.cs @@ -7,16 +7,16 @@ public static class Common { private static readonly Lazy _deserializer = new Lazy(new DeserializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build()); - private static readonly Lazy _serializer = + private static readonly Lazy _serializer = new Lazy(new SerializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build()); public static IDeserializer Deserializer => _deserializer.Value; - public static ISerializer Serializer => _serializer.Value; + public static ISerializer Serializer => _serializer.Value; } public class CoreRunInfo { public string Path { get; set; } - public Dictionary environment_variables { get; set; } + public Dictionary environment_variables { get; set; } } public static class ConfigurationChecker diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSim.Configuration.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSim.Configuration.cs index 4818deb88fa..3c17c35df55 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSim.Configuration.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSim.Configuration.cs @@ -14,12 +14,12 @@ public sealed class GCPerfSimConfiguration : ConfigurationBase public Output? Output { get; set; } } - public sealed class Run : RunBase - { + public sealed class Run : RunBase + { public Dictionary? override_parameters { get; set; } } - public sealed class Output : OutputBase {} + public sealed class Output : OutputBase { } public class GCPerfSimConfigurations { @@ -41,16 +41,16 @@ public class Environment } public static class GCPerfSimConfigurationParser { - private static readonly IDeserializer _deserializer = + private static readonly IDeserializer _deserializer = new DeserializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build(); public static GCPerfSimConfiguration Parse(string path, bool isIncompleteConfiguration = false) { // Preconditions. - ConfigurationChecker.VerifyFile(path, nameof(GCPerfSimConfigurationParser)); + ConfigurationChecker.VerifyFile(path, nameof(GCPerfSimConfigurationParser)); string serializedConfiguration = File.ReadAllText(path); - GCPerfSimConfiguration? configuration = null; + GCPerfSimConfiguration? configuration = null; // This try catch is here because the exception from the YamlDotNet isn't helpful and must be imbued with more details. try @@ -102,7 +102,7 @@ public static GCPerfSimConfiguration Parse(string path, bool isIncompleteConfigu // Check to ensure the builds are valid i.e., have an existent path to corerun. foreach (var build in configuration.coreruns!) { - if (string.IsNullOrEmpty(build.Value.Path) || + if (string.IsNullOrEmpty(build.Value.Path) || (!File.Exists(build.Value.Path) && !Directory.Exists(build.Value.Path))) { throw new ArgumentException($"{nameof(GCPerfSimConfigurationParser)}: The corerun for {build.Key} either doesn't exist or the path provided is incorrect. Please ensure that path points to a valid corerun"); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSimFunctional.Configuration.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSimFunctional.Configuration.cs index c057a943cba..b8161535dba 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSimFunctional.Configuration.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/GCPerfSimFunctional.Configuration.cs @@ -64,7 +64,7 @@ public static GCPerfSimFunctionalConfiguration Parse(string path) { ConfigurationChecker.VerifyEnvironmentVariables(run.Value.environment_variables, $"{nameof(GCPerfSimFunctionalConfigurationParser)} for Run: {run.Key}"); } - ConfigurationChecker.VerifyEnvironmentVariables(configuration.Environment.environment_variables, $"{nameof(GCPerfSimFunctionalConfigurationParser)}"); + ConfigurationChecker.VerifyEnvironmentVariables(configuration.Environment.environment_variables, $"{nameof(GCPerfSimFunctionalConfigurationParser)}"); return configuration; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/InputConfiguration.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/InputConfiguration.cs index 60df2fedd83..fb2546f9bb7 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/InputConfiguration.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Configurations/InputConfiguration.cs @@ -2,9 +2,9 @@ { public sealed class InputConfiguration { - public string output_path { get; set; } - public string gcperfsim_path { get; set; } - public string microbenchmark_path { get; set; } + public string output_path { get; set; } + public string gcperfsim_path { get; set; } + public string microbenchmark_path { get; set; } public Dictionary coreruns { get; set; } public Dictionary? linux_coreruns { get; set; } public Dictionary? environment_variables { get; set; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/Markdown.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/Markdown.cs index 64b52c6fbfa..8875f343bec 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/Markdown.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/Markdown.cs @@ -159,7 +159,7 @@ private static ResultItem TryGetResultItemFromDictionary(this ConcurrentDictiona else { - return ResultItem.GetNullItem(run, corerun); + return ResultItem.GetNullItem(run, corerun); } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItem.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItem.cs index 092e617518c..baeb289e184 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItem.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItem.cs @@ -8,48 +8,48 @@ public sealed class ResultItem public static ResultItem GetNullItem(string runName, string corerun) => new ResultItem(runName, corerun); - private ResultItem(string runName, string corerun) + private ResultItem(string runName, string corerun) { - ConfigurationName = corerun; - RunName = runName; - PctTimePausedInGC = double.NaN; - FirstToLastGCSeconds = double.NaN; - HeapSizeBeforeMB_Mean = double.NaN; - HeapSizeAfter_Mean = double.NaN; - PauseDurationMSec_95PWhereIsGen0 = double.NaN; - PauseDurationMSec_95PWhereIsGen1 = double.NaN; - PauseDurationMSec_95PWhereIsBackground = double.NaN; - PauseDurationMSec_MeanWhereIsBackground = double.NaN; - PauseDurationMSec_95PWhereIsBlockingGen2 = double.NaN; + ConfigurationName = corerun; + RunName = runName; + PctTimePausedInGC = double.NaN; + FirstToLastGCSeconds = double.NaN; + HeapSizeBeforeMB_Mean = double.NaN; + HeapSizeAfter_Mean = double.NaN; + PauseDurationMSec_95PWhereIsGen0 = double.NaN; + PauseDurationMSec_95PWhereIsGen1 = double.NaN; + PauseDurationMSec_95PWhereIsBackground = double.NaN; + PauseDurationMSec_MeanWhereIsBackground = double.NaN; + PauseDurationMSec_95PWhereIsBlockingGen2 = double.NaN; PauseDurationMSec_MeanWhereIsBlockingGen2 = double.NaN; - CountIsBlockingGen2 = double.NaN; - PauseDurationSeconds_SumWhereIsGen1 = double.NaN; - PauseDurationMSec_MeanWhereIsEphemeral = double.NaN; - PromotedMB_MeanWhereIsGen1 = double.NaN; - CountIsGen1 = double.NaN; - CountIsGen0 = double.NaN; - HeapCount = double.NaN; - PauseDurationMSec_Sum = double.NaN; - TotalAllocatedMB = double.NaN; - TotalNumberGCs = double.NaN; - Speed_MBPerMSec = double.NaN; - ExecutionTimeMSec = double.NaN; + CountIsBlockingGen2 = double.NaN; + PauseDurationSeconds_SumWhereIsGen1 = double.NaN; + PauseDurationMSec_MeanWhereIsEphemeral = double.NaN; + PromotedMB_MeanWhereIsGen1 = double.NaN; + CountIsGen1 = double.NaN; + CountIsGen0 = double.NaN; + HeapCount = double.NaN; + PauseDurationMSec_Sum = double.NaN; + TotalAllocatedMB = double.NaN; + TotalNumberGCs = double.NaN; + Speed_MBPerMSec = double.NaN; + ExecutionTimeMSec = double.NaN; } public ResultItem(GCProcessData processData, string runName, string configurationName) { RunName = runName; ConfigurationName = configurationName; - ExecutionTimeMSec = processData.DurationMSec; + ExecutionTimeMSec = processData.DurationMSec; PctTimePausedInGC = processData.Stats.GetGCPauseTimePercentage(); - FirstToLastGCSeconds = ( processData.GCs.Last().StartRelativeMSec - processData.GCs.First().StartRelativeMSec ) / 1000; + FirstToLastGCSeconds = (processData.GCs.Last().StartRelativeMSec - processData.GCs.First().StartRelativeMSec) / 1000; HeapSizeAfter_Mean = GoodLinq.Average(processData.GCs, (gc => gc.HeapSizeAfterMB)); HeapSizeBeforeMB_Mean = GoodLinq.Average(processData.GCs, (gc => gc.HeapSizeBeforeMB)); var properties = processData.Stats.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); - foreach (var property in properties) - { + foreach (var property in properties) + { if (property.PropertyType != typeof(double) || property.PropertyType != typeof(int)) { continue; @@ -61,9 +61,9 @@ public ResultItem(GCProcessData processData, string runName, string configuratio } var fields = processData.Stats.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); - foreach (var field in fields) - { - if (field.FieldType != typeof(double) || field.FieldType!= typeof(int)) + foreach (var field in fields) + { + if (field.FieldType != typeof(double) || field.FieldType != typeof(int)) { continue; } @@ -74,13 +74,13 @@ public ResultItem(GCProcessData processData, string runName, string configuratio } // 95P - PauseDurationMSec_95PWhereIsGen0 = Statistics.Percentile(GoodLinq.Select( GoodLinq.Where(processData.GCs, (gc => gc.Generation == 0)), (gc => gc.PauseDurationMSec)), 0.95); - PauseDurationMSec_95PWhereIsGen1 = Statistics.Percentile(GoodLinq.Select( GoodLinq.Where(processData.GCs, (gc => gc.Generation == 1)), (gc => gc.PauseDurationMSec)), 0.95); + PauseDurationMSec_95PWhereIsGen0 = Statistics.Percentile(GoodLinq.Select(GoodLinq.Where(processData.GCs, (gc => gc.Generation == 0)), (gc => gc.PauseDurationMSec)), 0.95); + PauseDurationMSec_95PWhereIsGen1 = Statistics.Percentile(GoodLinq.Select(GoodLinq.Where(processData.GCs, (gc => gc.Generation == 1)), (gc => gc.PauseDurationMSec)), 0.95); - PauseDurationMSec_95PWhereIsBackground = Statistics.Percentile(GoodLinq.Select( GoodLinq.Where(processData.GCs, (gc => gc.Type == GCType.BackgroundGC)), (gc => gc.PauseDurationMSec)), 0.95); + PauseDurationMSec_95PWhereIsBackground = Statistics.Percentile(GoodLinq.Select(GoodLinq.Where(processData.GCs, (gc => gc.Type == GCType.BackgroundGC)), (gc => gc.PauseDurationMSec)), 0.95); PauseDurationMSec_MeanWhereIsBackground = GoodLinq.Average(GoodLinq.Select(GoodLinq.Where(processData.GCs, (gc => gc.Type == GCType.BackgroundGC)), (gc => gc.PauseDurationMSec)), (p => p)); - PauseDurationMSec_95PWhereIsBlockingGen2 = Statistics.Percentile(GoodLinq.Select( GoodLinq.Where(processData.GCs, (gc => gc.Type != GCType.BackgroundGC && gc.Generation == 2)), (gc => gc.PauseDurationMSec)), 0.95); + PauseDurationMSec_95PWhereIsBlockingGen2 = Statistics.Percentile(GoodLinq.Select(GoodLinq.Where(processData.GCs, (gc => gc.Type != GCType.BackgroundGC && gc.Generation == 2)), (gc => gc.PauseDurationMSec)), 0.95); PauseDurationMSec_MeanWhereIsBlockingGen2 = GoodLinq.Average(GoodLinq.Select(GoodLinq.Where(processData.GCs, (gc => gc.Type != GCType.BackgroundGC && gc.Generation == 2)), (gc => gc.PauseDurationMSec)), (p => p)); CountIsBlockingGen2 = processData.GCs.Count(gc => gc.Generation == 2 && gc.Type != GCType.BackgroundGC); @@ -95,29 +95,29 @@ public ResultItem(GCProcessData processData, string runName, string configuratio GoodLinq.Average(GoodLinq.Where(processData.GCs, (gc => gc.Generation == 1 || gc.Generation == 0)), (gc => gc.PauseDurationMSec)); PauseDurationSeconds_SumWhereIsGen1 = GoodLinq.Sum(GoodLinq.Where(processData.GCs, (gc => gc.Generation == 1)), (gc => gc.PauseDurationMSec)); - PauseDurationMSec_Sum = GoodLinq.Sum(processData.GCs, (gc => gc.PauseDurationMSec)); + PauseDurationMSec_Sum = GoodLinq.Sum(processData.GCs, (gc => gc.PauseDurationMSec)); CountIsGen1 = GoodLinq.Where(processData.GCs, gc => gc.Generation == 1).Count; CountIsGen0 = GoodLinq.Where(processData.GCs, gc => gc.Generation == 0).Count; } - public double PctTimePausedInGC { get; } - public double FirstToLastGCSeconds { get; } - public double HeapSizeBeforeMB_Mean { get; } - public double HeapSizeAfter_Mean { get; } - public double PauseDurationMSec_95PWhereIsGen0 { get; } - public double PauseDurationMSec_95PWhereIsGen1 { get; } - public double PauseDurationMSec_95PWhereIsBackground { get; } - public double PauseDurationMSec_MeanWhereIsBackground { get; } + public double PctTimePausedInGC { get; } + public double FirstToLastGCSeconds { get; } + public double HeapSizeBeforeMB_Mean { get; } + public double HeapSizeAfter_Mean { get; } + public double PauseDurationMSec_95PWhereIsGen0 { get; } + public double PauseDurationMSec_95PWhereIsGen1 { get; } + public double PauseDurationMSec_95PWhereIsBackground { get; } + public double PauseDurationMSec_MeanWhereIsBackground { get; } public double PauseDurationMSec_95PWhereIsBlockingGen2 { get; } public double PauseDurationMSec_MeanWhereIsBlockingGen2 { get; } public double CountIsBlockingGen2 { get; } - public double PauseDurationSeconds_SumWhereIsGen1 { get; } - public double PauseDurationMSec_MeanWhereIsEphemeral { get; } - public double PromotedMB_MeanWhereIsGen1 { get; } - public double CountIsGen1 { get; } - public double CountIsGen0 { get; } + public double PauseDurationSeconds_SumWhereIsGen1 { get; } + public double PauseDurationMSec_MeanWhereIsEphemeral { get; } + public double PromotedMB_MeanWhereIsGen1 { get; } + public double CountIsGen1 { get; } + public double CountIsGen0 { get; } public double HeapCount { get; } - public double PauseDurationMSec_Sum { get; } + public double PauseDurationMSec_Sum { get; } public double TotalAllocatedMB { get; set; } public double TotalNumberGCs { get; } public double Speed_MBPerMSec { get; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItemComparison.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItemComparison.cs index 9e1ccfed5b2..81ea3fb9499 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItemComparison.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/GCPerfSim/ResultItemComparison.cs @@ -10,14 +10,14 @@ public ComparisonResult(ResultItem baseline, ResultItem comparand, string metric { Baseline = baseline; Comparand = comparand; - + MetricName = metricName; PropertyInfo pInfo = typeof(ResultItem).GetProperty(metricName, BindingFlags.Instance | BindingFlags.Public); // Property found on the ResultItem. if (pInfo != null) { - BaselineMetric = (double)pInfo.GetValue(baseline); + BaselineMetric = (double)pInfo.GetValue(baseline); ComparandMetric = (double)pInfo.GetValue(comparand); } @@ -38,16 +38,16 @@ public ComparisonResult(ResultItem baseline, ResultItem comparand, string metric else { - BaselineMetric = (double)fieldInfo.GetValue(baseline); + BaselineMetric = (double)fieldInfo.GetValue(baseline); ComparandMetric = (double)fieldInfo.GetValue(comparand); } } else { - BaselineMetric = (double)pInfo.GetValue(baseline); + BaselineMetric = (double)pInfo.GetValue(baseline); ComparandMetric = (double)pInfo.GetValue(comparand); - } + } } } @@ -61,7 +61,7 @@ public string ToMarkdownString(string runName, string baselineCorerunName, strin return sb.ToString(); } - public string RunName => Baseline.RunName; + public string RunName => Baseline.RunName; public string MetricName { get; } public double BaselineMetric { get; } public double ComparandMetric { get; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/MarkdownReportBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/MarkdownReportBuilder.cs index 188e8dba8ce..ce0415c70e0 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/MarkdownReportBuilder.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/MarkdownReportBuilder.cs @@ -29,8 +29,8 @@ public static string CopySectionFromMarkDown(string markdown, string sectionToCo // Iterate till we find the section. int runnerIdx = -1; - for (int startIdx = 0; startIdx < lines.Length; startIdx++) - { + for (int startIdx = 0; startIdx < lines.Length; startIdx++) + { string line = lines[startIdx]; if (line.StartsWith($"# {sectionToCopy}")) { @@ -47,7 +47,7 @@ public static string CopySectionFromMarkDown(string markdown, string sectionToCo // Once the section is obtained, iterate till we get to the next section. StringBuilder sb = new(); - while (runnerIdx < lines.Length) + while (runnerIdx < lines.Length) { string line = lines[runnerIdx]; @@ -114,7 +114,7 @@ public static void AddReproSection(this StreamWriter sw, Dictionary aspnetRuns) { - var cleanedGCPerfSimConfigurations = new HashSet(gcperfsimConfigurations.Select(c => Path.GetFileNameWithoutExtension(c))); + var cleanedGCPerfSimConfigurations = new HashSet(gcperfsimConfigurations.Select(c => Path.GetFileNameWithoutExtension(c))); var cleanedMicrobenchmarkConfigurations = new HashSet(microbenchmarkConfigurations.Select(c => Path.GetFileNameWithoutExtension(c))); // GCPerfSim. @@ -126,11 +126,11 @@ public static void GenerateChecklist(this StreamWriter sw, string[] gcperfsimCon string containsLowMemoryContainer_GCPerfSim = cleanedGCPerfSimConfigurations.Contains("LowMemoryContainer") ? "x" : " "; // Microbenchmarks. - string containsServer_Microbenchmarks = cleanedMicrobenchmarkConfigurations.Contains("Microbenchmrks_Server") ? "x" : " "; + string containsServer_Microbenchmarks = cleanedMicrobenchmarkConfigurations.Contains("Microbenchmrks_Server") ? "x" : " "; string containsWorkstation_Microbenchmarks = cleanedGCPerfSimConfigurations.Contains("Microbenchmarks_Workstation") ? "x" : " "; // ASPNet Configurations. - string contains_JsonMinWindows = aspnetRuns.Contains("JsonMin_Windows") ? "x" : " "; + string contains_JsonMinWindows = aspnetRuns.Contains("JsonMin_Windows") ? "x" : " "; string contains_FortunesEtf_Windows = aspnetRuns.Contains("FortunesETF_Windows") ? "x" : " "; string contains_Stage1Grpc_Windows = aspnetRuns.Contains("Stage1Grpc_Windows") ? "x" : " "; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Markdown.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Markdown.cs index d368a309a07..76dffd7f87d 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Markdown.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Markdown.cs @@ -6,10 +6,10 @@ namespace GC.Infrastructure.Core.Presentation.Microbenchmarks { - public static class Markdown + public static class Markdown { private const string baseTableString = "| Benchmark Name | Baseline | Comparand | Baseline Mean Duration (MSec) | Comparand Mean Duration (MSec) | Δ Mean Duration (MSec) | Δ% Mean Duration |"; - private const string baseTableRows = "| --- | --- | -- | --- | --- | --- | --- | "; + private const string baseTableRows = "| --- | --- | -- | --- | --- | --- | --- | "; public static void GenerateTable(MicrobenchmarkConfiguration configuration, IReadOnlyList comparisonResults, Dictionary executionDetails, string path) { @@ -86,7 +86,7 @@ internal static void AddDetailsOfSingleComparison(this StreamWriter sw, Microben if (configuration.Output.additional_report_metrics != null) { - foreach(var metric in configuration.Output.additional_report_metrics) + foreach (var metric in configuration.Output.additional_report_metrics) { sw.WriteLine($"## Comparison by {metric}"); var ordered = comparisonResult.Comparisons.OrderByDescending(c => c.GetDiffPercentFromOtherMetrics(metric)); @@ -100,7 +100,7 @@ internal static void AddDetailsOfSingleComparison(this StreamWriter sw, Microben sw.WriteLine($"### Large Improvements (>20%): {comparisonResult.LargeImprovements.Count()} \n"); var largeImprovements = GoodLinq.Where(ordered, o => o.GetDiffPercentFromOtherMetrics(metric) < -0.2); largeImprovements.Reverse(); - sw.AddTableForSingleCriteria(configuration, largeImprovements); + sw.AddTableForSingleCriteria(configuration, largeImprovements); sw.WriteLine("\n"); // Regressions @@ -112,7 +112,7 @@ internal static void AddDetailsOfSingleComparison(this StreamWriter sw, Microben sw.WriteLine($"### Improvements (5% - 20%): {comparisonResult.Improvements.Count()} \n"); var improvements = GoodLinq.Where(ordered, o => o.GetDiffPercentFromOtherMetrics(metric) > 0.05 && o.GetDiffPercentFromOtherMetrics(metric) < 0.2); improvements.Reverse(); - sw.AddTableForSingleCriteria(configuration, improvements); + sw.AddTableForSingleCriteria(configuration, improvements); sw.WriteLine("\n"); // Stale Regressions @@ -124,7 +124,7 @@ internal static void AddDetailsOfSingleComparison(this StreamWriter sw, Microben sw.WriteLine($"### Stale Improvements (Same or percent difference within 5% margin): {comparisonResult.StaleImprovements.Count()} \n"); var staleImprovements = GoodLinq.Where(ordered, o => o.GetDiffPercentFromOtherMetrics(metric) > -0.05 && o.GetDiffPercentFromOtherMetrics(metric) < 0.0); staleImprovements.Reverse(); - sw.AddTableForSingleCriteria(configuration, staleImprovements); + sw.AddTableForSingleCriteria(configuration, staleImprovements); sw.WriteLine("\n"); } } @@ -138,7 +138,7 @@ internal static void AddTableForSingleCriteria(this StreamWriter sw, Microbenchm if (configuration.Output.Columns != null) { - foreach(var column in configuration.Output.Columns) + foreach (var column in configuration.Output.Columns) { tableHeader0 += $"Baseline {column} | Comparand {column} | Δ {column} | Δ% {column} |"; tableHeader1 += "--- | --- | --- | --- |"; @@ -147,7 +147,7 @@ internal static void AddTableForSingleCriteria(this StreamWriter sw, Microbenchm if (configuration.Output.cpu_columns != null) { - foreach(var column in configuration.Output.cpu_columns) + foreach (var column in configuration.Output.cpu_columns) { tableHeader0 += $"Baseline {column} | Comparand {column} | Δ {column} | Δ% {column} |"; tableHeader1 += "--- | --- | --- | --- |"; @@ -157,15 +157,15 @@ internal static void AddTableForSingleCriteria(this StreamWriter sw, Microbenchm sw.WriteLine(tableHeader0); sw.WriteLine(tableHeader1); - foreach(var lr in comparisons) + foreach (var lr in comparisons) { try { - var baseRow = $"| {lr.MicrobenchmarkName} | {lr.BaselineRunName} | {lr.ComparandRunName} | {Math.Round(lr.Baseline.Statistics.Mean.Value, 2)} | {Math.Round(lr.Comparand.Statistics.Mean.Value, 2)} | {Math.Round(lr.MeanDiff,2 )}| {Math.Round(lr.MeanDiffPerc, 2)}|"; + var baseRow = $"| {lr.MicrobenchmarkName} | {lr.BaselineRunName} | {lr.ComparandRunName} | {Math.Round(lr.Baseline.Statistics.Mean.Value, 2)} | {Math.Round(lr.Comparand.Statistics.Mean.Value, 2)} | {Math.Round(lr.MeanDiff, 2)}| {Math.Round(lr.MeanDiffPerc, 2)}|"; if (configuration.Output.Columns != null) { - foreach(var column in configuration.Output.Columns) + foreach (var column in configuration.Output.Columns) { if (!lr.Baseline.OtherMetrics.TryGetValue(column, out double? baselineValue)) { @@ -191,7 +191,7 @@ internal static void AddTableForSingleCriteria(this StreamWriter sw, Microbenchm if (configuration.Output.cpu_columns != null) { - foreach(var column in configuration.Output.cpu_columns) + foreach (var column in configuration.Output.cpu_columns) { if (!lr.Baseline.OtherMetrics.TryGetValue(column, out double? baselineValue)) { @@ -226,7 +226,7 @@ internal static void AddTableForSingleCriteria(this StreamWriter sw, Microbenchm } // Dispose all the Analyzers now that we are persisting the values. - foreach(var comparison in comparisons) + foreach (var comparison in comparisons) { comparison.Baseline?.GCData?.Parent?.Dispose(); comparison.Baseline?.CPUData?.Parent?.Analyzer?.Dispose(); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Presentation.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Presentation.cs index d74c99e51e3..93f4faea7f0 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Presentation.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Presentation/Microbenchmarks/Presentation.cs @@ -10,7 +10,7 @@ public static class Presentation public static IReadOnlyList Present(MicrobenchmarkConfiguration configuration, Dictionary executionDetails) { IReadOnlyList comparisonResults = MicrobenchmarkResultsAnalyzer.GetComparisons(configuration); - foreach(var format in configuration.Output.Formats) + foreach (var format in configuration.Output.Formats) { if (format == "markdown") { diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/TraceCollection/TraceCollector.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/TraceCollection/TraceCollector.cs index 181bff12de6..752657610b5 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/TraceCollection/TraceCollector.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/TraceCollection/TraceCollector.cs @@ -78,7 +78,7 @@ public TraceCollector(string name, string collectType, string outputPath) if (_collectType != CollectType.none) { _sessionName = Guid.NewGuid(); - foreach(var invalid in Path.GetInvalidPathChars()) + foreach (var invalid in Path.GetInvalidPathChars()) { name = name.Replace(invalid.ToString(), string.Empty); } @@ -152,7 +152,7 @@ private void Dispose(bool disposing) stopLogmanProcess.StartInfo.Arguments = etsStopCommand; stopLogmanProcess.StartInfo.UseShellExecute = false; stopLogmanProcess.StartInfo.RedirectStandardOutput = false; - stopLogmanProcess.StartInfo.RedirectStandardError = false; + stopLogmanProcess.StartInfo.RedirectStandardError = false; stopLogmanProcess.StartInfo.CreateNoWindow = true; stopLogmanProcess.Start(); stopLogmanProcess.WaitForExit(5_000); @@ -164,11 +164,11 @@ private void Dispose(bool disposing) public string Name { get; init; } - ~TraceCollector() - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(disposing: false); - } + ~TraceCollector() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: false); + } public void Dispose() { diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Utilities.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Utilities.cs index f4f5f2cd323..7ec7371cb0d 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Utilities.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/Utilities.cs @@ -7,7 +7,7 @@ public static void CopyFilesRecursively(string sourcePath, string targetPath) string targetPathAsDirectory = targetPath + "\\"; foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)) { - Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPathAsDirectory)); + Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPathAsDirectory)); } foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories)) @@ -23,8 +23,8 @@ public static bool TryCreateDirectory(string path) throw new ArgumentException($"{nameof(Utilities)}: Path is null or empty."); } - if (!Directory.Exists(path)) - { + if (!Directory.Exists(path)) + { Directory.CreateDirectory(path); return true; } @@ -37,9 +37,9 @@ public static bool TryCreateDirectory(string path) public static bool TryCopyFile(string sourcePath, string destinationPath) { - if (!File.Exists(destinationPath)) - { - File.Copy(sourceFileName: sourcePath, + if (!File.Exists(destinationPath)) + { + File.Copy(sourceFileName: sourcePath, destFileName: destinationPath); return true; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksAnalyzeCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksAnalyzeCommand.cs index e59dc60b743..bf35167644e 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksAnalyzeCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksAnalyzeCommand.cs @@ -107,7 +107,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] AspNetBe if (crankCompareProcess.ExitCode == 0) { - if (!metricResults.TryGetValue(benchmark.Key, out var metrics )) + if (!metricResults.TryGetValue(benchmark.Key, out var metrics)) { metrics = metricResults[benchmark.Key] = new(); } @@ -126,7 +126,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] AspNetBe var topLevelSummarySet = new HashSet(new List { "Working Set (MB)", "Private Memory (MB)", "Requests/sec", "Mean Latency (MSec)", "Latency 50th (MSec)", "Latency 75th (MSec)", "Latency 90th (MSec)", "Latency 99th (MSec)" }); sw.WriteLine($"| | {string.Join("|", topLevelSummarySet)}"); - sw.WriteLine($"|--- | {string.Join( "", Enumerable.Repeat("---|", topLevelSummarySet.Count ))}"); + sw.WriteLine($"|--- | {string.Join("", Enumerable.Repeat("---|", topLevelSummarySet.Count))}"); foreach (var r in metricResults) { @@ -163,17 +163,17 @@ public override int Execute([NotNull] CommandContext context, [NotNull] AspNetBe } // Best way to deep-copy a configuration is to serialize and then deserialize. - string configurationSerialized = Common.Serializer.Serialize(configuration); + string configurationSerialized = Common.Serializer.Serialize(configuration); // We want to be able to rerun the failed tests in an easy manner. For this, we take any failed runs and create a // new configuration based on the run configuration and then add these failed runs to filter on. // The process of creating a deep copy of the old configuration involves serializing and deserializing the current configuration. // We then iterate over all the failed runs, add them as items in the benchmark filters and persist the new configuration in the output path. List> failedRuns = executionDetails.Where(exec => exec.Value.HasFailed).ToList(); - + // This path is only valid if we have failed runs. if (failedRuns.Count > 0) - { + { try { configuration = Common.Deserializer.Deserialize(configurationSerialized); @@ -271,7 +271,7 @@ internal static List GetMetricResultsFromTable(string table, strin List results = new(); string[] firstLineSplit = resultsLineSplit[0].Split("|", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); - string baseline = firstLineSplit[1]; + string baseline = firstLineSplit[1]; string comparand = firstLineSplit[2]; for (int runnerIdx = 0; runnerIdx < resultsLineSplit.Length; runnerIdx++) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksCommand.cs index 0c6afe62e3b..53a90c9450b 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/ASPNetBenchmarks/AspNetBenchmarksCommand.cs @@ -128,10 +128,10 @@ public static AspNetBenchmarkResults RunASPNetBenchmarks(ASPNetBenchmarksConfigu string[] line = lines[lineIdx].Split(',', StringSplitOptions.TrimEntries); Debug.Assert(line.Length == 2); - string benchmarkName = line[0]; + string benchmarkName = line[0]; string benchmarkCommands = line[1]; - benchmarkNameToCommand[benchmarkName] = benchmarkCommands; + benchmarkNameToCommand[benchmarkName] = benchmarkCommands; } List> benchmarkToNameCommandAsKvpList = new(); @@ -175,7 +175,7 @@ public static AspNetBenchmarkResults RunASPNetBenchmarks(ASPNetBenchmarksConfigu } // Overwrite the dictionary with the most up to date results of what will be run. - benchmarkNameToCommand = benchmarkToNameCommandAsKvpList.ToDictionary(pair => pair.Key, pair => pair.Value); + benchmarkNameToCommand = benchmarkToNameCommandAsKvpList.ToDictionary(pair => pair.Key, pair => pair.Value); // For each benchmark, iterate over all specified runs. foreach (var benchmarkToCommand in benchmarkToNameCommandAsKvpList) @@ -187,9 +187,9 @@ public static AspNetBenchmarkResults RunASPNetBenchmarks(ASPNetBenchmarksConfigu return new AspNetBenchmarkResults(executionDetails, results); } - internal static void ExecuteBenchmarkForRuns(ASPNetBenchmarksConfiguration configuration, - KeyValuePair benchmarkToCommand, - Dictionary executionDetails, + internal static void ExecuteBenchmarkForRuns(ASPNetBenchmarksConfiguration configuration, + KeyValuePair benchmarkToCommand, + Dictionary executionDetails, List<(string, string, string)> retryMessages) { foreach (var run in configuration.Runs!) @@ -203,7 +203,7 @@ public static AspNetBenchmarkResults RunASPNetBenchmarks(ASPNetBenchmarksConfigu ExecuteBenchmarkForRuns(configuration, benchmarkToCommand, executionDetails, retryMessages); return; // Return here to prevent infinite looping. } - + ProcessExecutionDetails result = ExecuteBenchmarkForRun(configuration, run, benchmarkToCommand); string key = GetKey(benchmarkToCommand.Key, run.Key); @@ -374,21 +374,21 @@ internal static HashSet CheckForMissingOutputsAndReturnNames(ASPNetBench // Files to expect always from crank: // 1. Build Output: BenchmarkName_RunName.build.log string buildOutput = Path.Combine(basePath, $"{benchmarkName}_{runName}.build.log"); - if (!File.Exists(buildOutput)) + if (!File.Exists(buildOutput)) { missingOutputs.Add("Build Output"); } // 2. Application Output: BenchmarkName_RunName.output.log string applicationOutput = Path.Combine(basePath, $"{benchmarkName}_{runName}.output.log"); - if (!File.Exists(applicationOutput)) + if (!File.Exists(applicationOutput)) { missingOutputs.Add("Application Output"); } // 3. Json Output: BenchmarkName_RunName.json string outputJson = Path.Combine(basePath, $"{benchmarkName}_{runName}.json"); - if (!File.Exists(outputJson)) + if (!File.Exists(outputJson)) { missingOutputs.Add("Output Json"); } @@ -397,7 +397,7 @@ internal static HashSet CheckForMissingOutputsAndReturnNames(ASPNetBench // 1. Trace: BenchmarkName..etl.zip or BenchmarkName..nettrace if (configuration.TraceConfigurations?.Type != "none") { - string etlFileName = Path.Combine(basePath, $"{benchmarkName}.{configuration.TraceConfigurations!.Type}.etl.zip"); + string etlFileName = Path.Combine(basePath, $"{benchmarkName}.{configuration.TraceConfigurations!.Type}.etl.zip"); string nettraceFileName = Path.Combine(basePath, $"{benchmarkName}.{configuration.TraceConfigurations!.Type}.nettrace"); if (!File.Exists(etlFileName) && !File.Exists(nettraceFileName)) { @@ -406,10 +406,10 @@ internal static HashSet CheckForMissingOutputsAndReturnNames(ASPNetBench } // 2. GCLog: BenchmarkName_GCLog/.log - if (configuration.Environment!.environment_variables!.ContainsKey("DOTNET_GCLog") || - configuration.Environment!.environment_variables!.ContainsKey("COMPlus_GCLog") || - configuration.Runs!.Any(r => r.Value.environment_variables?.ContainsKey("DOTNET_GCLog") ?? false) || - configuration.Runs!.Any(r => r.Value.environment_variables?.ContainsKey("COMPlus_GCLog") ?? false) ) + if (configuration.Environment!.environment_variables!.ContainsKey("DOTNET_GCLog") || + configuration.Environment!.environment_variables!.ContainsKey("COMPlus_GCLog") || + configuration.Runs!.Any(r => r.Value.environment_variables?.ContainsKey("DOTNET_GCLog") ?? false) || + configuration.Runs!.Any(r => r.Value.environment_variables?.ContainsKey("COMPlus_GCLog") ?? false)) { string basePathForGCLog = Path.Combine(configuration.Output.Path, runName, $"{benchmarkName}_GCLog"); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimAnalyzeCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimAnalyzeCommand.cs index 71c60f08008..ec08492b7cc 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimAnalyzeCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimAnalyzeCommand.cs @@ -36,7 +36,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] GCPerfSi public static IReadOnlyList ExecuteAnalysis(GCPerfSimConfiguration configuration, Dictionary executionDetails) { string outputPath = Path.Combine(configuration.Output!.Path, "Results.md"); - IReadOnlyList results = Markdown.GenerateTable(configuration, executionDetails, outputPath); + IReadOnlyList results = Markdown.GenerateTable(configuration, executionDetails, outputPath); AnsiConsole.MarkupLine($"[green bold] ({DateTime.Now}) Results written to {outputPath} [/]"); return results; } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimCommand.cs index 1ba63376ffd..94ce7b4b68d 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimCommand.cs @@ -18,7 +18,7 @@ public sealed class GCPerfSimResults public GCPerfSimResults(IReadOnlyDictionary executionDetails, IReadOnlyList analysisResults) { ExecutionDetails = executionDetails; - AnalysisResults = analysisResults; + AnalysisResults = analysisResults; } public IReadOnlyDictionary ExecutionDetails { get; } @@ -43,7 +43,7 @@ internal sealed class RunInfo public RunInfo(KeyValuePair runDetails, KeyValuePair corerunDetails) { RunDetails = runDetails; - CorerunDetails = corerunDetails; + CorerunDetails = corerunDetails; } public KeyValuePair RunDetails { get; set; } @@ -149,7 +149,7 @@ public static GCPerfSimResults RunGCPerfSim(GCPerfSimConfiguration configuration // Add per corerun based environment variables. if (runInfo.CorerunDetails.Value.environment_variables != null) { - foreach (var environmentVar in runInfo.CorerunDetails.Value.environment_variables) + foreach (var environmentVar in runInfo.CorerunDetails.Value.environment_variables) { environmentVariables[environmentVar.Key] = environmentVar.Value; } @@ -170,7 +170,7 @@ public static GCPerfSimResults RunGCPerfSim(GCPerfSimConfiguration configuration { gcperfsimProcess.Start(); output = gcperfsimProcess.StandardOutput.ReadToEnd(); - error = gcperfsimProcess.StandardError.ReadToEnd(); + error = gcperfsimProcess.StandardError.ReadToEnd(); gcperfsimProcess.WaitForExit((int)configuration.Environment.default_max_seconds * 1000); File.WriteAllText(Path.Combine(outputPath, key + ".txt"), "Standard Out: \n" + output + "\n Standard Error: \n" + error); } @@ -184,7 +184,7 @@ public static GCPerfSimResults RunGCPerfSim(GCPerfSimConfiguration configuration AnsiConsole.MarkupLine($"[yellow bold] ({DateTime.Now}) The trace for the run wasn't successfully captured. Please check the log file for more details: {Markup.Escape(output)} Full run details: {Path.GetFileNameWithoutExtension(configuration.Name)}: {runInfo.CorerunDetails.Key} for {runInfo.RunDetails.Key} [/]"); } } - + int exitCode = gcperfsimProcess.ExitCode; if (!string.IsNullOrEmpty(error)) { @@ -192,8 +192,8 @@ public static GCPerfSimResults RunGCPerfSim(GCPerfSimConfiguration configuration } ProcessExecutionDetails details = new(key: key, - commandlineArgs: $"{processAndParameters.Item1} {processAndParameters.Item2}", - environmentVariables: environmentVariables, + commandlineArgs: $"{processAndParameters.Item1} {processAndParameters.Item2}", + environmentVariables: environmentVariables, standardError: error, standardOut: output, exitCode: exitCode); @@ -265,7 +265,7 @@ public static GCPerfSimResults RunGCPerfSim(GCPerfSimConfiguration configuration ProcessExecutionDetails details = new(key: key, commandlineArgs: $"{processAndParameters.Item1} {processAndParameters.Item2}", environmentVariables: new(), // The environment variables are embedded in the command line for crank. - standardError: error.ToString(), + standardError: error.ToString(), standardOut: output.ToString(), exitCode: exitCode); executionDetails[key] = details; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimFunctionalCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimFunctionalCommand.cs index 84b2611a096..c5b0e49d69b 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimFunctionalCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/GCPerfSim/GCPerfSimFunctionalCommand.cs @@ -84,7 +84,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] GCPerfSi { try { - GCPerfSimConfiguration gcperfsimConfiguration = + GCPerfSimConfiguration gcperfsimConfiguration = GCPerfSimConfigurationParser.Parse(gcperfsimConfigurationFileName); Stopwatch sw = new(); @@ -186,7 +186,7 @@ private void CreateNormalWorkstationSuite(string gcPerfSimSuitePath, GCPerfSimFu // modify gcperfsim_configurations gcPerfSimNormalWorkstationConfiguration.gcperfsim_configurations.Parameters["tc"] = "2"; gcPerfSimNormalWorkstationConfiguration.gcperfsim_configurations.Parameters["tagb"] = "100"; - + // modify output gcPerfSimNormalWorkstationConfiguration.Output.Path = Path.Combine(configuration.output_path, "Normal_Workstation"); @@ -230,7 +230,7 @@ private void CreateLowMemoryContainerSuite(string gcPerfSimSuitePath, GCPerfSimF }; // modify gcperfsim_configurations - gcPerfSimLowMemoryContainerConfiguration.gcperfsim_configurations.Parameters["tc"] = (_logicalProcessors * 2).ToString(); + gcPerfSimLowMemoryContainerConfiguration.gcperfsim_configurations.Parameters["tc"] = (_logicalProcessors * 2).ToString(); gcPerfSimLowMemoryContainerConfiguration.gcperfsim_configurations.Parameters["tagb"] = "100"; gcPerfSimLowMemoryContainerConfiguration.gcperfsim_configurations.Parameters["tlgb"] = "0.1"; gcPerfSimLowMemoryContainerConfiguration.gcperfsim_configurations.Parameters["sohsi"] = "50"; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/Microbenchmark/MicrobenchmarkCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/Microbenchmark/MicrobenchmarkCommand.cs index 111e0f5f8e2..088a06b37b9 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/Microbenchmark/MicrobenchmarkCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/Microbenchmark/MicrobenchmarkCommand.cs @@ -21,7 +21,7 @@ public sealed class MicrobenchmarkOutputResults public MicrobenchmarkOutputResults(Dictionary processExecutionDetails, IReadOnlyList analysisResults) { ProcessExecutionDetails = processExecutionDetails; - AnalysisResults = analysisResults; + AnalysisResults = analysisResults; } public IReadOnlyDictionary ProcessExecutionDetails { get; } @@ -161,7 +161,7 @@ public static MicrobenchmarkOutputResults RunMicrobenchmarks(MicrobenchmarkConfi bdnProcess.StartInfo.CreateNoWindow = true; StringBuilder consoleOutput = new(); - StringBuilder consoleError = new(); + StringBuilder consoleError = new(); bdnProcess.OutputDataReceived += (s, e) => { @@ -183,9 +183,9 @@ public static MicrobenchmarkOutputResults RunMicrobenchmarks(MicrobenchmarkConfi } ProcessExecutionDetails details = new(key: $"{run.Key}_{benchmark}", - commandlineArgs: $"{fileNameAndCommand.Item1} {fileNameAndCommand.Item2}", + commandlineArgs: $"{fileNameAndCommand.Item1} {fileNameAndCommand.Item2}", environmentVariables: run.Value.environment_variables, - standardError: consoleError.ToString(), + standardError: consoleError.ToString(), standardOut: consoleOutput.ToString(), exitCode: bdnProcess.ExitCode); executionDetails[$"{run.Key}_{benchmark}"] = details; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/CreateSuiteCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/CreateSuiteCommand.cs index 8c44dbc9633..0cec453d0c3 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/CreateSuiteCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/CreateSuiteCommand.cs @@ -12,13 +12,13 @@ namespace GC.Infrastructure.Commands.RunCommand { public sealed class CreateSuitesCommand : Command { - private static readonly string _baseSuitePath = Path.Combine("Commands", "RunCommand", "BaseSuite"); + private static readonly string _baseSuitePath = Path.Combine("Commands", "RunCommand", "BaseSuite"); // Removed the high volatility configuration. //private static readonly string _gcPerfSimBase = Path.Combine(_baseSuitePath, "GCPerfSim_Normal_Workstation.yaml"); private static readonly string _gcPerfSimBaseLowVolatility = Path.Combine(_baseSuitePath, "LowVolatilityRuns.yaml"); private static readonly string _microbenchmarkBase = Path.Combine(_baseSuitePath, "Microbenchmarks.yaml"); - private static readonly string _aspNetBase = Path.Combine(_baseSuitePath, "ASPNetBenchmarks.yaml"); - private static readonly ISerializer _serializer = Common.Serializer; + private static readonly string _aspNetBase = Path.Combine(_baseSuitePath, "ASPNetBenchmarks.yaml"); + private static readonly ISerializer _serializer = Common.Serializer; public sealed class CreateSuitesSettings : CommandSettings { @@ -59,7 +59,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] CreateSu string outputSymbolPath = Path.Combine(configuration.output_path, "Symbols"); Core.Utilities.TryCreateDirectory(outputSymbolPath); - foreach (var paths in configuration.symbol_path) + foreach (var paths in configuration.symbol_path) { string pathToSymbols = Path.Combine(outputSymbolPath, paths.Key); Core.Utilities.TryCreateDirectory(pathToSymbols); @@ -73,7 +73,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] CreateSu string outputSourcePath = Path.Combine(configuration.output_path, "Sources"); Core.Utilities.TryCreateDirectory(outputSourcePath); - foreach (var paths in configuration.source_path) + foreach (var paths in configuration.source_path) { string pathToSource = Path.Combine(outputSourcePath, paths.Key); Core.Utilities.TryCreateDirectory(pathToSource); @@ -131,7 +131,7 @@ internal static string CreateASPNetBenchmarkSuite(InputConfiguration inputConfig foreach (var envVars in r.Value.environment_variables) { if (string.CompareOrdinal(envVars.Key, "DOTNET_GCName") == 0 || - string.CompareOrdinal(envVars.Key, "DOTNET_GCName") == 0 ) + string.CompareOrdinal(envVars.Key, "DOTNET_GCName") == 0) { string directoryOfCorerun = Path.GetDirectoryName(r.Value.Path)!; run.corerun = Path.Combine(directoryOfCorerun, envVars.Value); @@ -175,7 +175,7 @@ internal static string CreateMicrobenchmarkSuite(InputConfiguration inputConfigu // Workstation Runs. MicrobenchmarkConfiguration workstation = CreateBaseMicrobenchmarkSuite(inputConfiguration, destinationMicrobenchmarksToRun, destinationMicrobenchmarkInvocationCount); - foreach(var r in workstation.Runs) + foreach (var r in workstation.Runs) { if (r.Value.environment_variables == null) { @@ -193,7 +193,7 @@ internal static string CreateMicrobenchmarkSuite(InputConfiguration inputConfigu // Server Runs. MicrobenchmarkConfiguration server = CreateBaseMicrobenchmarkSuite(inputConfiguration, destinationMicrobenchmarksToRun, destinationMicrobenchmarkInvocationCount); server.Name = "Server"; - foreach(var r in server.Runs) + foreach (var r in server.Runs) { if (r.Value.environment_variables == null) { @@ -220,7 +220,7 @@ internal static MicrobenchmarkConfiguration CreateBaseMicrobenchmarkSuite(InputC configuration.Runs.Add(corerun.Key, new Core.Configurations.Microbenchmarks.Run { corerun = corerun.Value.Path, - Name = corerun.Key, + Name = corerun.Key, environment_variables = corerun.Value.environment_variables }); } @@ -233,7 +233,7 @@ internal static MicrobenchmarkConfiguration CreateBaseMicrobenchmarkSuite(InputC configuration.MicrobenchmarkConfigurations.FilterPath = microbenchmarkFilterFile; // Microbenchmark Invocation Count Path. - configuration.MicrobenchmarkConfigurations.InvocationCountPath = microbenchmarkInvocationCountFile; + configuration.MicrobenchmarkConfigurations.InvocationCountPath = microbenchmarkInvocationCountFile; // Update Trace Configuration type. configuration.TraceConfigurations.Type = inputConfiguration.trace_configuration_type.ToLower(); @@ -242,7 +242,7 @@ internal static MicrobenchmarkConfiguration CreateBaseMicrobenchmarkSuite(InputC string baseMicrobenchmarkPath = Path.Combine(inputConfiguration.output_path, "Microbenchmarks"); Core.Utilities.TryCreateDirectory(baseMicrobenchmarkPath); - configuration.Output.Path = baseMicrobenchmarkPath; + configuration.Output.Path = baseMicrobenchmarkPath; return configuration; } @@ -279,7 +279,7 @@ internal static void SaveConfiguration(ConfigurationBase configuration, string o internal static GCPerfSimConfiguration GetBaseConfiguration(InputConfiguration inputConfiguration, string name) { GCPerfSimConfiguration baseConfiguration = GCPerfSimConfigurationParser.Parse(_gcPerfSimBaseLowVolatility, isIncompleteConfiguration: true); - baseConfiguration.Output.Path = Path.Combine(inputConfiguration.output_path, name); + baseConfiguration.Output.Path = Path.Combine(inputConfiguration.output_path, name); baseConfiguration.TraceConfigurations.Type = inputConfiguration.trace_configuration_type.ToLower(); baseConfiguration.gcperfsim_configurations.gcperfsim_path = inputConfiguration.gcperfsim_path; baseConfiguration.coreruns = inputConfiguration.coreruns; @@ -309,7 +309,7 @@ internal static GCPerfSimConfiguration CreateNormalServerCase(InputConfiguration normalServerCase.gcperfsim_configurations.Parameters["tagb"] = (30 * logicalProcessors).ToString(); // Set the environment variables appropriately. - normalServerCase.Environment.environment_variables["DOTNET_gcServer"] = "1"; + normalServerCase.Environment.environment_variables["DOTNET_gcServer"] = "1"; normalServerCase.Environment.environment_variables["DOTNET_GCHeapCount"] = logicalProcessors.ToString("x"); normalServerCase.Name = Path.GetFileNameWithoutExtension(name); @@ -408,7 +408,7 @@ internal static int GetAppropriateLogicalProcessors() int logicalProcessors = System.Environment.ProcessorCount; switch (logicalProcessors) { - case int lp when lp > 4: return logicalProcessors - 2; + case int lp when lp > 4: return logicalProcessors - 2; case int lp when lp > 2 && lp <= 4: return logicalProcessors - 1; default: return logicalProcessors; diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunCommand.cs index b5191b9dd8d..0cd4fc33087 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunCommand.cs @@ -63,7 +63,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma sw.Start(); int gcperfsimTestCount = 0; - string gcperfsimBase = configurationMap["GCPerfSim"]; + string gcperfsimBase = configurationMap["GCPerfSim"]; string[] gcperfsimConfigurations = Directory.GetFiles(gcperfsimBase, "*.yaml"); Dictionary allComparisonResults = new(); @@ -75,8 +75,8 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma Dictionary> configurationToTopLevelMetrics_GCPerfSim = new(); - HashSet gcTopLevelResults = new HashSet(new List - { + HashSet gcTopLevelResults = new HashSet(new List + { "ExecutionTimeMSec", "PctTimePausedInGC", "HeapSizeBeforeMB_Mean", @@ -212,7 +212,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma foreach (var d in gcPerfsimDirectories) { string resultPath = Path.Combine(d, "Results.md"); - string results = File.ReadAllText(resultPath); + string results = File.ReadAllText(resultPath); sb.AppendLine($"\n## Results for: {d}\n"); sb.Append(results); @@ -225,7 +225,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma foreach (var d in microbenchmarkDirectories) { string resultPath = Path.Combine(d, "Results.md"); - string results = File.ReadAllText(resultPath); + string results = File.ReadAllText(resultPath); sb.AppendLine($"\n## Results for: {d}\n"); sb.Append(results); @@ -234,12 +234,12 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma // Add the ASPNet Benchmarks Results. sb.AppendLine("# ASPNet Benchmarks"); string aspnetBenchmarkBasePath = Path.Combine(configuration.output_path, "ASPNetBenchmarks"); - string aspnetResultPath = Path.Combine(aspnetBenchmarkBasePath, "Results.md"); - string aspnetResultsText = ""; + string aspnetResultPath = Path.Combine(aspnetBenchmarkBasePath, "Results.md"); + string aspnetResultsText = ""; aspnetResultsText = File.ReadAllText(aspnetResultPath); sb.Append(aspnetResultsText); - swReport.WriteLine($"# Results Comparing {string.Join(" and ", configuration.coreruns.Select(c => $"```{c.Key}```"))}"); + swReport.WriteLine($"# Results Comparing {string.Join(" and ", configuration.coreruns.Select(c => $"```{c.Key}```"))}"); swReport.WriteLine("# Contents"); swReport.WriteLine("- [Checklist](#checklist)"); @@ -276,8 +276,8 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma // GC PerfSim Top Level Results. swReport.WriteLine($"## GC PerfSim ({uniqueGCPerfSimTests.Count})\n"); - swReport.WriteLine($"| | {string.Join("|", gcTopLevelResults.Select(r => gcLevelResultsMap[ r ] ))}"); - swReport.WriteLine($"|--- | {string.Join("", Enumerable.Repeat("---|", gcTopLevelResults.Count ))}"); + swReport.WriteLine($"| | {string.Join("|", gcTopLevelResults.Select(r => gcLevelResultsMap[r]))}"); + swReport.WriteLine($"|--- | {string.Join("", Enumerable.Repeat("---|", gcTopLevelResults.Count))}"); foreach (var r in configurationToTopLevelMetrics_GCPerfSim) { @@ -287,13 +287,13 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma restOfMetrics += $" {Math.Round(r.Value[l], 2)}% |"; } - swReport.WriteLine($"| {r.Key} | {restOfMetrics}"); + swReport.WriteLine($"| {r.Key} | {restOfMetrics}"); } swReport.WriteLine(); swReport.WriteLine($"## Microbenchmarks ({uniqueMicrobenchmarks.Count})\n"); - swReport.WriteLine($"| | Mean Execution Time (MSec) | {string.Join("|", gcTopLevelResults.Select(r => gcLevelResultsMap[ r ] ))}"); - swReport.WriteLine($"|--- | ---- | {string.Join("", Enumerable.Repeat("---|", gcTopLevelResults.Count ))}"); + swReport.WriteLine($"| | Mean Execution Time (MSec) | {string.Join("|", gcTopLevelResults.Select(r => gcLevelResultsMap[r]))}"); + swReport.WriteLine($"|--- | ---- | {string.Join("", Enumerable.Repeat("---|", gcTopLevelResults.Count))}"); foreach (var m in allMicrobenchmarkResults) { @@ -306,7 +306,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma restOfMetrics += $" {Math.Round(metric, 2)}% |"; } - swReport.WriteLine($"| {m.Key} {r.MicrobenchmarkName} | {Math.Round(r.MeanDiffPerc, 2)}% | {restOfMetrics}" ); + swReport.WriteLine($"| {m.Key} {r.MicrobenchmarkName} | {Math.Round(r.MeanDiffPerc, 2)}% | {restOfMetrics}"); } } @@ -315,7 +315,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] RunComma string aspNetSummary = MarkdownReportBuilder.CopySectionFromMarkDownPath(aspnetResultPath, "Summary"); swReport.Write(aspNetSummary); swReport.WriteLine(); - swReport.Write( sb.ToString() ); + swReport.Write(sb.ToString()); } sw.Stop(); diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunSuiteCommand.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunSuiteCommand.cs index 1ba5f1139b4..2fc52eb00ff 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunSuiteCommand.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Commands/RunCommand/RunSuiteCommand.cs @@ -23,7 +23,7 @@ public sealed class RunSuiteCommandSettings : CommandSettings public override int Execute([NotNull] CommandContext context, [NotNull] RunSuiteCommandSettings settings) { if (!string.IsNullOrEmpty(settings.SuiteBasePath) || !Directory.Exists(settings.SuiteBasePath)) - { + { throw new ArgumentNullException($"{nameof(RunSuiteCommandSettings)}: {nameof(settings.SuiteBasePath)} was either null or the directory doesn't exists."); } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Program.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Program.cs index a1d9d7a8e0b..331efe5a744 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Program.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/Program.cs @@ -69,7 +69,7 @@ internal static void Main(string[] args) } } - internal static bool IsAdministrator => + internal static bool IsAdministrator => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); } } \ No newline at end of file From 2da56e62638f88d7b012ccfb4b92323af50cd083 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 17 Jun 2024 13:07:33 -0700 Subject: [PATCH 2/7] Upgrade TraceEvent dependencies --- .gitignore | 1 + .../GC.Analysis.API/GC.Analysis.API.csproj | 2 +- .../Notebooks/ASPNetBenchmarkAnalysis.ipynb | 2 +- .../Notebooks/Examples/CPUExamples.ipynb | 2 +- .../Notebooks/Examples/GCAnalysisExamples.ipynb | 15 +++++++++++++-- .../Notebooks/VolatilityReport.ipynb | 2 +- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index fd0a136bd56..2e6a5e28e60 100644 --- a/.gitignore +++ b/.gitignore @@ -258,6 +258,7 @@ ClientBin/ *.jfm *.publishsettings orleans.codegen.cs +*.xlf # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj index 67dd813685e..9992a0a00d4 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/ASPNetBenchmarkAnalysis.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/ASPNetBenchmarkAnalysis.ipynb index 4cf05c2a2f9..93031f9dd7b 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/ASPNetBenchmarkAnalysis.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/ASPNetBenchmarkAnalysis.ipynb @@ -36,7 +36,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.7\"\n", + "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.9\"\n", "#r \"nuget: YamlDotnet\"\n", "#r \"nuget: XPlot.Plotly\"\n", "#r \"nuget: XPlot.Plotly.Interactive\"\n", diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CPUExamples.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CPUExamples.ipynb index 139ffb304af..858c8e7b1f0 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CPUExamples.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CPUExamples.ipynb @@ -67,7 +67,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.7\"\n", + "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.9\"\n", "#r \"nuget: XPlot.Plotly\"\n", "#r \"nuget: XPlot.Plotly.Interactive\"\n", "#r \"nuget: Microsoft.Data.Analysis\"\n", diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb index 6981796d121..101017c1307 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb @@ -31,7 +31,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.7\"\n", + "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.9\"\n", "#r \"nuget: XPlot.Plotly\"\n", "#r \"nuget: XPlot.Plotly.Interactive\"\n", "#r \"nuget: Microsoft.Data.Analysis\"\n", @@ -869,7 +869,18 @@ "pygments_lexer": "csharp", "version": "9.0" }, - "orig_nbformat": 4 + "orig_nbformat": 4, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/VolatilityReport.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/VolatilityReport.ipynb index b3f1fd3657b..70cdc4d3b74 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/VolatilityReport.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/VolatilityReport.ipynb @@ -24,7 +24,7 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.7\"\n", + "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.9\"\n", "#r \"nuget: YamlDotnet\" \n", "#r \"nuget: XPlot.Plotly\"\n", "#r \"nuget: XPlot.Plotly.Interactive\"\n", From cc46a94bd68c6db30a98c8981771629f765f27df Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 17 Jun 2024 18:51:41 -0700 Subject: [PATCH 3/7] Delete output from notebook --- .../Examples/GCAnalysisExamples.ipynb | 300 +++--------------- 1 file changed, 41 insertions(+), 259 deletions(-) diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb index 101017c1307..fa237be00b8 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -19,17 +19,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.Data.Analysis, 0.20.1
  • Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.6
  • Newtonsoft.Json, 13.0.3
  • XPlot.Plotly, 4.0.6
  • XPlot.Plotly.Interactive, 4.0.7
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.Diagnostics.Tracing.TraceEvent, 3.1.9\"\n", "#r \"nuget: XPlot.Plotly\"\n", @@ -59,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -68,31 +58,14 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "MSBuild version 17.8.0+6cdef4241 for .NET\n", - " Determining projects to restore...\n", - " All projects are up-to-date for restore.\n", - " GC.Analysis.API -> C:\\temp\\InstructionsForCTI\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net7.0\\GC.Analysis.API.dll\n", - "\n", - "Build succeeded.\n", - " 0 Warning(s)\n", - " 0 Error(s)\n", - "\n", - "Time Elapsed 00:00:00.81\n" - ] - } - ], + "outputs": [], "source": [ "dotnet build -c Release \"..\\..\\GC.Analysis.API\"" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -101,17 +74,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0006: Metadata file ' C:\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net6.0\\GC.Analysis.API.dll' could not be found\r\n(3,7): error CS0246: The type or namespace name 'GC' could not be found (are you missing a using directive or an assembly reference?)", - "output_type": "error", - "traceback": [ - "(1,1): error CS0006: Metadata file ' C:\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net6.0\\GC.Analysis.API.dll' could not be found\r\n", - "(3,7): error CS0246: The type or namespace name 'GC' could not be found (are you missing a using directive or an assembly reference?)" - ] - } - ], + "outputs": [], "source": [ "#r \"C:\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net7.0\\GC.Analysis.API.dll\" \n", "\n", @@ -128,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -153,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -162,17 +125,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,20): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,44): error CS0103: The name 'AnalyzerManager' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,20): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,44): error CS0103: The name 'AnalyzerManager' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "Dictionary gcTraceData = AnalyzerManager.GetAnalyzer(tracePaths: new[] { TRACE_PATH });" ] @@ -187,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -196,17 +149,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,20): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,44): error CS0103: The name 'AnalyzerManager' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,20): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,44): error CS0103: The name 'AnalyzerManager' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "Dictionary gcTraceData = AnalyzerManager.GetAllAnalyzers(BASE_PATH);" ] @@ -229,7 +172,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -238,17 +181,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,28): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)", - "output_type": "error", - "traceback": [ - "(1,1): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,28): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)" - ] - } - ], + "outputs": [], "source": [ "Analyzer gcTraceData = new Analyzer(tracePath: TRACE_PATH);" ] @@ -263,7 +196,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -272,17 +205,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,28): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)", - "output_type": "error", - "traceback": [ - "(1,1): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,28): error CS0246: The type or namespace name 'Analyzer' could not be found (are you missing a using directive or an assembly reference?)" - ] - } - ], + "outputs": [], "source": [ "Analyzer gcTraceData = new Analyzer(tracePath: TRACE_PATH, processNames: new HashSet { \"devenv\" });" ] @@ -297,7 +220,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -306,16 +229,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0103: The name 'gcTraceData' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0103: The name 'gcTraceData' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "gcTraceData.SummarizeTrace(processName: \"devenv\")" ] @@ -346,7 +260,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -355,16 +269,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0103: The name 'gcTraceData' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0103: The name 'gcTraceData' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "gcTraceData.Summarize(processName: \"devenv\")" ] @@ -379,7 +284,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -388,17 +293,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,6): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,34): error CS0103: The name 'gcTraceData' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,6): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,34): error CS0103: The name 'gcTraceData' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "List allDevenvs = gcTraceData.GetProcessGCData(\"devenv\");\n", "var data = allDevenvs[0].Compare(new [] { allDevenvs[1], allDevenvs[2] });\n", @@ -415,7 +310,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -424,16 +319,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0103: The name 'gcTraceData' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0103: The name 'gcTraceData' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "gcTraceData.Summarize(topN: 3, criteriaInGCStats: nameof(GCStats.MeanSizeAfterMB))" ] @@ -456,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -465,18 +351,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,6): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n(2,1): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,39): error CS0103: The name 'gcTraceData' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,6): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(2,1): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,39): error CS0103: The name 'gcTraceData' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "List devenvChartData = gcTraceData.GetProcessGCData(processName: \"devenv\");\n", "GCProcessData devenvToInvestigate = devenvChartData[0];\n", @@ -493,7 +368,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -502,17 +377,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n(1,36): error CS0103: The name 'devenvTraceGCs' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n", - "(1,36): error CS0103: The name 'devenvTraceGCs' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "GCCharting.ChartGCData(gcs : devenvTraceGCs, \n", " title : \"Pause Duration (MSec)\", \n", @@ -530,7 +395,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -539,19 +404,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0246: The type or namespace name 'ChartInfo' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,27): error CS0246: The type or namespace name 'ChartInfo' could not be found (are you missing a using directive or an assembly reference?)\r\n(9,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n(9,36): error CS0103: The name 'devenvTraceGCs' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0246: The type or namespace name 'ChartInfo' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,27): error CS0246: The type or namespace name 'ChartInfo' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(9,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n", - "(9,36): error CS0103: The name 'devenvTraceGCs' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "ChartInfo chartInfo = new ChartInfo\n", "{\n", @@ -578,7 +431,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -587,18 +440,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n(1,37): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n(6,37): error CS0103: The name 'chartInfo' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n", - "(1,37): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n", - "(6,37): error CS0103: The name 'chartInfo' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "GCCharting.ChartGCData(gcs : devenvTraceGCs,\n", " title : \"Pause Durations and Suspend Durations\",\n", @@ -626,7 +468,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -635,19 +477,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(1,1): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n(1,42): error CS0103: The name 'devenvChartData' does not exist in the current context\r\n(7,71): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n(11,1): error CS0103: The name 'GCCharting' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(1,1): error CS0246: The type or namespace name 'GCProcessData' could not be found (are you missing a using directive or an assembly reference?)\r\n", - "(1,42): error CS0103: The name 'devenvChartData' does not exist in the current context\r\n", - "(7,71): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n", - "(11,1): error CS0103: The name 'GCCharting' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "GCProcessData otherDevenvToInvestigate = devenvChartData[1];\n", "List devenvTraceGCsOther = otherDevenvToInvestigate.GCs;\n", @@ -675,7 +505,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -684,18 +514,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(4,71): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n(5,71): error CS0103: The name 'allDevenvs' does not exist in the current context\r\n(8,1): error CS0103: The name 'GCCharting' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(4,71): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n", - "(5,71): error CS0103: The name 'allDevenvs' does not exist in the current context\r\n", - "(8,1): error CS0103: The name 'GCCharting' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "List<(string scatterName, List gcs)> gcData = \n", " new()\n", @@ -721,7 +540,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -730,17 +549,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(7,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n(7,36): error CS0103: The name 'devenvTraceGCs' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(7,1): error CS0103: The name 'GCCharting' does not exist in the current context\r\n", - "(7,36): error CS0103: The name 'devenvTraceGCs' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "IEnumerable<(string, Func)> filters = new (string, Func)[] \n", "{\n", @@ -764,7 +573,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -773,17 +582,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(14,14): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n(21,1): error CS0103: The name 'GCCharting' does not exist in the current context", - "output_type": "error", - "traceback": [ - "(14,14): error CS0103: The name 'devenvTraceGCs' does not exist in the current context\r\n", - "(21,1): error CS0103: The name 'GCCharting' does not exist in the current context" - ] - } - ], + "outputs": [], "source": [ "class CustomType\n", "{\n", @@ -822,7 +621,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -831,24 +630,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Current Process ID: 13000\r\n" - ] - }, - { - "data": { - "text/html": [ - "

.NET Interactive

© 2020 Microsoft Corporation

Version: 1.0.425803+1db2979099d0272660e1497cae9b9af1238db42f

Library version: 1.0.0-beta.23258.3+1db2979099d0272660e1497cae9b9af1238db42f

Build date: 2023-05-19T04:42:05.2974204Z

https://github.com/dotnet/interactive

" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "Console.WriteLine($\"Current Process ID: {System.Diagnostics.Process.GetCurrentProcess().Id}\");\n", "\n", From b07fff181baa30aea40ce178dd9a4ff33799d6b9 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Tue, 18 Jun 2024 06:29:24 -0700 Subject: [PATCH 4/7] Enable using custom TraceEvent --- .../GC.Analysis.API/GC.Analysis.API.csproj | 15 +- .../GC.Infrastructure.Core.UnitTests.csproj | 2 +- .../GC.Infrastructure.Core.csproj | 13 +- .../GC.Infrastructure.csproj | 2 +- .../Examples/CustomTraceEventExample.ipynb | 246 ++++++++++++++++++ .../Examples/GCAnalysisExamples.ipynb | 2 +- .../gc/GC.Infrastructure/Versions.props | 9 + 7 files changed, 283 insertions(+), 6 deletions(-) create mode 100644 src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb create mode 100644 src/benchmarks/gc/GC.Infrastructure/Versions.props diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj index 9992a0a00d4..d1bde30ef4e 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/GC.Analysis.API.csproj @@ -2,21 +2,32 @@ enable - net7.0 + net8.0 enable false false false + + - + + + + + $(PerfViewPath)\src\FastSerialization\bin\Release\netstandard2.0\Microsoft.Diagnostics.FastSerialization.dll + + + $(PerfViewPath)\src\TraceEvent\bin\Release\netstandard2.0\Microsoft.Diagnostics.Tracing.TraceEvent.dll + + diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/GC.Infrastructure.Core.UnitTests.csproj b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/GC.Infrastructure.Core.UnitTests.csproj index 7891d8663cb..0a7a6e22fe4 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/GC.Infrastructure.Core.UnitTests.csproj +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core.UnitTests/GC.Infrastructure.Core.UnitTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/GC.Infrastructure.Core.csproj b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/GC.Infrastructure.Core.csproj index 0ab07e4a534..3c3ad5c0fba 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/GC.Infrastructure.Core.csproj +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/GC.Infrastructure.Core.csproj @@ -1,13 +1,15 @@  - net7.0 + net8.0 enable enable false false + + @@ -23,5 +25,14 @@ + + + + $(PerfViewPath)\src\FastSerialization\bin\Release\netstandard2.0\Microsoft.Diagnostics.FastSerialization.dll + + + $(PerfViewPath)\src\TraceEvent\bin\Release\netstandard2.0\Microsoft.Diagnostics.Tracing.TraceEvent.dll + + diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/GC.Infrastructure.csproj b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/GC.Infrastructure.csproj index 53eff53aa87..33ed8cf8b92 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/GC.Infrastructure.csproj +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure/GC.Infrastructure.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 enable enable false diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb new file mode 100644 index 00000000000..927ab5e680b --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb @@ -0,0 +1,246 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Usage of GC.Analysis.API for GC Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// In order to use a custom TraceEvent library, we need to reference it directly here\n", + "\n", + "#r \"C:\\Dev\\perfview\\src\\TraceEvent\\bin\\Release\\netstandard2.0\\Microsoft.Diagnostics.Tracing.TraceEvent.dll\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget: XPlot.Plotly\"\n", + "#r \"nuget: XPlot.Plotly.Interactive\"\n", + "#r \"nuget: Microsoft.Data.Analysis\"\n", + "#r \"nuget: Newtonsoft.Json\"\n", + "\n", + "using Etlx = Microsoft.Diagnostics.Tracing.Etlx;\n", + "using Microsoft.Data.Analysis;\n", + "using Microsoft.Diagnostics.Tracing.Analysis.GC;\n", + "using Microsoft.Diagnostics.Tracing.Analysis;\n", + "using Microsoft.Diagnostics.Tracing.Parsers.Clr;\n", + "using Microsoft.Diagnostics.Tracing;\n", + "using XPlot.Plotly;\n", + "\n", + "using System.IO;\n", + "using Newtonsoft.Json;" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Building and Using The GC Analysis API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before building `GC.Analysis.API`, make sure we change the project file so that it references the local copy instead of pulling it from Nuget. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "dotnet build -c Release \"..\\..\\GC.Analysis.API\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"C:\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net8.0\\GC.Analysis.API.dll\" \n", + "\n", + "using GC.Analysis.API;" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating the Analyzer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var TRACE_PATH = @\".\\Traces\\gccollectonly.etl.zip\";" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Analyzer From a Single Path" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Get All Processes From a Trace" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "Analyzer gcTraceData = new Analyzer(tracePath: TRACE_PATH);" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Get Select Processes From a Trace" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "gcTraceData.SummarizeTrace(processName: \"corerun\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Getting To a ``List`` from the Trace Data For a Process" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "List corerunData = gcTraceData.GetProcessGCData(processName: \"corerun\");\n", + "GCProcessData corerunToInvestigate = corerunData[0];\n", + "List traceGCs = corerunToInvestigate.GCs;" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/x-csharp", + "name": "C#", + "pygments_lexer": "csharp", + "version": "9.0" + }, + "orig_nbformat": 4, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb index fa237be00b8..9d908cb8e19 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/GCAnalysisExamples.ipynb @@ -76,7 +76,7 @@ }, "outputs": [], "source": [ - "#r \"C:\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net7.0\\GC.Analysis.API.dll\" \n", + "#r \"C:\\performance\\artifacts\\bin\\GC.Analysis.API\\Release\\net8.0\\GC.Analysis.API.dll\" \n", "\n", "using GC.Analysis.API;" ] diff --git a/src/benchmarks/gc/GC.Infrastructure/Versions.props b/src/benchmarks/gc/GC.Infrastructure/Versions.props new file mode 100644 index 00000000000..17f1c70b330 --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/Versions.props @@ -0,0 +1,9 @@ + + + + + false + $(MSBuildProjectDirectory)\..\..\..\..\..\..\PerfView + CUSTOM_TRACE_EVENT;$(DefineConstants) + + \ No newline at end of file From 625d3a22afa635e58ace15c87c2245d71da4f037 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Tue, 18 Jun 2024 06:34:23 -0700 Subject: [PATCH 5/7] Initial DynamicEvent support --- .../DynamicEventTests.cs | 119 +++++++++++++ .../GC.Analysis.API.UnitTests.csproj | 36 ++++ .../GC.Analysis.API.UnitTests/Usings.cs | 1 + .../DynamicEvents/DynamicEvents.cs | 158 ++++++++++++++++++ .../Examples/CustomTraceEventExample.ipynb | 60 ++++++- 5 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs create mode 100644 src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/GC.Analysis.API.UnitTests.csproj create mode 100644 src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/Usings.cs create mode 100644 src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs new file mode 100644 index 00000000000..5cd243ac144 --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs @@ -0,0 +1,119 @@ +using FluentAssertions; +using Microsoft.Diagnostics.Tracing.Analysis.GC; +using Microsoft.Diagnostics.Tracing.Parsers.GCDynamic; +using GC.Analysis.API.DynamicEvents; +using System.Reflection; + +namespace GC.Analysis.API.UnitTests +{ + [TestClass] + public class DynamicEventTests + { + [TestMethod] + public void TestDuplicatedSchema() + { + Action test = () => { + DynamicEventSchema.Set( + new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + new KeyValuePair("Number", typeof(ulong)), + } + }, + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + new KeyValuePair("Number", typeof(ulong)), + } + } + } + ); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestDuplicatedFields() + { + Action test = () => { + DynamicEventSchema.Set( + new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + new KeyValuePair("version", typeof(ulong)), + } + }, + } + ); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestUnsupportedType() + { + Action test = () => { + DynamicEventSchema.Set( + new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + Fields = new List> + { + new KeyValuePair("version", typeof(DateTime)), + } + }, + } + ); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestValidSchema() + { + DynamicEventSchema.Set( + new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + new KeyValuePair("Number", typeof(ulong)), + } + }, + } + ); + DynamicEvent sampleEvent = new DynamicEvent( + "SampleEventName", + DateTime.Now, + new byte[] {1, 0, 2, 0, 0, 0, 0, 0, 0, 0} + ); + + List dynamicEvents = new List + { + sampleEvent + }; + dynamic index = new DynamicIndex(dynamicEvents); + + ((int)index.SampleEventName.version).Should().Be(1); + ((int)index.SampleEventName.Number).Should().Be(2); + } + } +} \ No newline at end of file diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/GC.Analysis.API.UnitTests.csproj b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/GC.Analysis.API.UnitTests.csproj new file mode 100644 index 00000000000..58bd121eb27 --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/GC.Analysis.API.UnitTests.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + false + false + false + + + + + + + + + + + + + + + + $(PerfViewPath)\src\FastSerialization\bin\Release\netstandard2.0\Microsoft.Diagnostics.FastSerialization.dll + + + $(PerfViewPath)\src\TraceEvent\bin\Release\netstandard2.0\Microsoft.Diagnostics.Tracing.TraceEvent.dll + + + + + + + + diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/Usings.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/Usings.cs new file mode 100644 index 00000000000..ab67c7ea9df --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs new file mode 100644 index 00000000000..b86920c1e05 --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs @@ -0,0 +1,158 @@ +// TODO, AndrewAu, remove this condition when new TraceEvent is available through Nuget. +#if CUSTOM_TRACE_EVENT + +using Microsoft.Diagnostics.Tracing.Analysis.GC; +using Microsoft.Diagnostics.Tracing.Parsers.GCDynamic; +using System.Diagnostics; +using System.Dynamic; +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("GC.Analysis.API.UnitTests")] + +namespace GC.Analysis.API.DynamicEvents +{ + public static class TraceGCExtensions + { + public static dynamic DynamicEvents(this TraceGC traceGC) + { + return new DynamicIndex(traceGC.DynamicEvents); + } + } + + public class DynamicEventSchema + { + internal static Dictionary>> DynamicEventSchemas = new Dictionary>>(); + + public string DynamicEventName { get; set; } + + public List> Fields { get; set; } + + public static void Set(List dynamicEventSchemas) + { + DynamicEventSchemas.Clear(); + foreach (DynamicEventSchema dynamicEventSchema in dynamicEventSchemas) + { + if (DynamicEventSchemas.ContainsKey(dynamicEventSchema.DynamicEventName)) + { + throw new Exception($"Provided schema has a duplicated event named {dynamicEventSchema.DynamicEventName}"); + } + Dictionary> fields = new Dictionary>(); + int offset = 0; + foreach (KeyValuePair field in dynamicEventSchema.Fields) + { + if (fields.ContainsKey(field.Key)) + { + throw new Exception($"Provided schema has a duplicated field named {field.Key}"); + } + fields.Add(field.Key, Tuple.Create(offset, field.Value)); + + // TODO, AndrewAu, all types that we envision this will be needed + if (field.Value == typeof(ushort)) + { + offset += 2; + } + else if (field.Value == typeof(ulong)) + { + offset += 8; + } + else + { + throw new Exception($"Provided schema has a field named {field.Key} using an unsupported type {field.Value}"); + } + } + DynamicEventSchemas.Add(dynamicEventSchema.DynamicEventName, fields); + } + } + } + + internal class DynamicIndex : DynamicObject + { + private List index; + + public DynamicIndex(List dynamicEvents) + { + // TODO, andrewau, index the events by name at this point + // TODO, andrewau, define multiplicity constraint + // TODO, andrewau, define size constraint + // TODO, andrewau, validate events according to constraints. + this.index = dynamicEvents; + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + string name = binder.Name; + Dictionary> fieldOffsets; + if (DynamicEventSchema.DynamicEventSchemas.TryGetValue(name, out fieldOffsets)) + { + // TODO, at this point, we should already have the events indexed and validated + result = new DynamicEventObject(index.Single(r => string.Equals(r.Name, binder.Name)), fieldOffsets); + return true; + } + else + { + result = null; + return false; + } + } + } + + internal class DynamicEventObject : DynamicObject + { + private DynamicEvent dynamicEvent; + private Dictionary fieldValues; + + public DynamicEventObject(DynamicEvent dynamicEvent, Dictionary> fieldOffsets) + { + this.dynamicEvent = dynamicEvent; + this.fieldValues = new Dictionary(); + foreach (KeyValuePair> field in fieldOffsets) + { + object value = null; + int fieldOffset = field.Value.Item1; + Type fieldType = field.Value.Item2; + + if (fieldType == typeof(ushort)) + { + value = BitConverter.ToUInt16(dynamicEvent.Payload, fieldOffset); + } + else if (fieldType == typeof(ulong)) + { + value = BitConverter.ToUInt64(dynamicEvent.Payload, fieldOffset); + } + else + { + Debug.Fail("Unknown field type"); + } + this.fieldValues.Add(field.Key, value); + } + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + string name = binder.Name; + if (string.Equals(name, "TimeStamp")) + { + result = this.dynamicEvent.TimeStamp; + return true; + } + else + if (this.fieldValues.TryGetValue(name, out var fieldValue)) + { + result = fieldValue; + return true; + } + else + { + result = null; + return false; + } + } + + public override string ToString() + { + return "I am " + this.dynamicEvent.Name + " with these fields: \n" + string.Join("\n", this.fieldValues.Select(kvp => kvp.Key + "->" + kvp.Value)); + } + } +} + +#endif \ No newline at end of file diff --git a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb index 927ab5e680b..278edacfc80 100644 --- a/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb +++ b/src/benchmarks/gc/GC.Infrastructure/Notebooks/Examples/CustomTraceEventExample.ipynb @@ -87,7 +87,7 @@ }, "outputs": [], "source": [ - "dotnet build -c Release \"..\\..\\GC.Analysis.API\"" + "dotnet build -c Release \"..\\..\\GC.Analysis.API\" /p:CustomTraceEvent=true /p:PerfViewPath=C:\\Dev\\PerfView" ] }, { @@ -213,6 +213,64 @@ "GCProcessData corerunToInvestigate = corerunData[0];\n", "List traceGCs = corerunToInvestigate.GCs;" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Dynamic Event" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using GC.Analysis.API.DynamicEvents;\n", + "\n", + "DynamicEventSchema.Set(new List\n", + "{\n", + " new DynamicEventSchema\n", + " {\n", + " DynamicEventName = \"ABC\",\n", + " Fields = new List>\n", + " {\n", + " new KeyValuePair(\"version\", typeof(ushort)),\n", + " new KeyValuePair(\"Number\", typeof(ulong)),\n", + " }\n", + " }\n", + "});" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "traceGCs[0].DynamicEvents().ABC.Number" + ] } ], "metadata": { From 6acc4bec786d580c385d737adbc3669ed6b1f6fb Mon Sep 17 00:00:00 2001 From: "Mukund Raghav Sharma (Moko)" <68247673+mrsharm@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:14:21 -0700 Subject: [PATCH 6/7] Fixes from @mrsharm --- src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.sln | 8 +++++++- .../GC.Analysis.API/DynamicEvents/DynamicEvents.cs | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.sln b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.sln index 48c3fc1fbaa..b4502db2694 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.sln +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.sln @@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GC.Infrastructure.Core", "G EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GC.Infrastructure.Core.UnitTests", "GC.Infrastructure.Core.UnitTests\GC.Infrastructure.Core.UnitTests.csproj", "{61F3DF76-A933-44AE-B5FF-B7909ED21999}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GC.Infrastructure", "GC.Infrastructure\GC.Infrastructure.csproj", "{7B2B6934-0DBD-45E0-9563-AE9DC8EBD538}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GC.Infrastructure", "GC.Infrastructure\GC.Infrastructure.csproj", "{7B2B6934-0DBD-45E0-9563-AE9DC8EBD538}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GC.Analysis.API.UnitTests", "GC.Analysis.API.UnitTests\GC.Analysis.API.UnitTests.csproj", "{A7D40245-CF5C-437E-B7E7-278AEA02954D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,6 +35,10 @@ Global {7B2B6934-0DBD-45E0-9563-AE9DC8EBD538}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B2B6934-0DBD-45E0-9563-AE9DC8EBD538}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B2B6934-0DBD-45E0-9563-AE9DC8EBD538}.Release|Any CPU.Build.0 = Release|Any CPU + {A7D40245-CF5C-437E-B7E7-278AEA02954D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7D40245-CF5C-437E-B7E7-278AEA02954D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7D40245-CF5C-437E-B7E7-278AEA02954D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7D40245-CF5C-437E-B7E7-278AEA02954D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs index b86920c1e05..3fbbb791364 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs @@ -51,6 +51,10 @@ public static void Set(List dynamicEventSchemas) { offset += 2; } + else if (field.Value == typeof(uint)) + { + offset += 4; + } else if (field.Value == typeof(ulong)) { offset += 8; @@ -115,6 +119,10 @@ public DynamicEventObject(DynamicEvent dynamicEvent, Dictionary Date: Mon, 1 Jul 2024 07:36:00 -0700 Subject: [PATCH 7/7] Compile and Validate --- .../DynamicEventTests.cs | 230 ++++++++++++++++- .../DynamicEvents/DynamicEvents.cs | 234 +++++++++++++----- 2 files changed, 388 insertions(+), 76 deletions(-) diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs index 5cd243ac144..31b8eaf415e 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API.UnitTests/DynamicEventTests.cs @@ -12,7 +12,8 @@ public class DynamicEventTests [TestMethod] public void TestDuplicatedSchema() { - Action test = () => { + Action test = () => + { DynamicEventSchema.Set( new List { @@ -43,7 +44,8 @@ public void TestDuplicatedSchema() [TestMethod] public void TestDuplicatedFields() { - Action test = () => { + Action test = () => + { DynamicEventSchema.Set( new List { @@ -65,7 +67,8 @@ public void TestDuplicatedFields() [TestMethod] public void TestUnsupportedType() { - Action test = () => { + Action test = () => + { DynamicEventSchema.Set( new List { @@ -84,7 +87,190 @@ public void TestUnsupportedType() } [TestMethod] - public void TestValidSchema() + public void TestNegativeMinOccurrence() + { + Action test = () => + { + DynamicEventSchema.Set( + new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + MinOccurrence = -1, + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + } + }, + } + ); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestSmallerMaxOccurrence() + { + Action test = () => + { + DynamicEventSchema.Set( + new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + MinOccurrence = 1, + MaxOccurrence = 0, + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + } + }, + } + ); + }; + test.Should().Throw(); + } + + private List correctSingleSchema = new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + MinOccurrence = 1, + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + new KeyValuePair("Number", typeof(ulong)), + } + }, + }; + + private DynamicEvent sampleEvent = new DynamicEvent( + "SampleEventName", + DateTime.Now, + new byte[] { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0 } + ); + + private DynamicEvent unknownEvent = new DynamicEvent( + "UnknownEventName", + DateTime.Now, + new byte[] { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0 } + ); + + [TestMethod] + public void TestMissedSingleEvent() + { + DynamicEventSchema.Set(correctSingleSchema); + List dynamicEvents = new List(); + Action test = () => + { + dynamic index = new DynamicIndex(dynamicEvents); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestDuplicatedSingleEvent() + { + DynamicEventSchema.Set(correctSingleSchema); + List dynamicEvents = new List + { + sampleEvent, + sampleEvent + }; + Action test = () => + { + dynamic index = new DynamicIndex(dynamicEvents); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestSingleEvent() + { + DynamicEventSchema.Set(correctSingleSchema); + List dynamicEvents = new List + { + sampleEvent + }; + dynamic index = new DynamicIndex(dynamicEvents); + + ((int)index.SampleEventName.version).Should().Be(1); + ((int)index.SampleEventName.Number).Should().Be(2); + string pattern = @" +SampleEventName +version : 1 +Number : 2 +TimeStamp : * +".Trim(); + ((string)index.SampleEventName.ToString()).Should().Match(pattern); + } + + private List correctMultipleSchema = new List + { + new DynamicEventSchema + { + DynamicEventName = "SampleEventName", + MinOccurrence = 1, + MaxOccurrence = 2, + Fields = new List> + { + new KeyValuePair("version", typeof(ushort)), + new KeyValuePair("Number", typeof(ulong)), + } + }, + }; + + [TestMethod] + public void TestMissedMultipleEvent() + { + DynamicEventSchema.Set(correctMultipleSchema); + List dynamicEvents = new List(); + Action test = () => + { + dynamic index = new DynamicIndex(dynamicEvents); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestTooManyMultipleEvents() + { + DynamicEventSchema.Set(correctMultipleSchema); + List dynamicEvents = new List + { + sampleEvent, + sampleEvent, + sampleEvent, + }; + Action test = () => + { + dynamic index = new DynamicIndex(dynamicEvents); + }; + test.Should().Throw(); + } + + [TestMethod] + public void TestMultipleEvents() + { + DynamicEventSchema.Set(correctMultipleSchema); + List dynamicEvents = new List + { + sampleEvent, + sampleEvent, + }; + dynamic index = new DynamicIndex(dynamicEvents); + + ((int)index.SampleEventName[0].version).Should().Be(1); + ((int)index.SampleEventName[0].Number).Should().Be(2); + ((int)index.SampleEventName[1].version).Should().Be(1); + ((int)index.SampleEventName[1].Number).Should().Be(2); + } + + [TestMethod] + public void TestOptionalEvent() { DynamicEventSchema.Set( new List @@ -100,20 +286,38 @@ public void TestValidSchema() }, } ); - DynamicEvent sampleEvent = new DynamicEvent( - "SampleEventName", - DateTime.Now, - new byte[] {1, 0, 2, 0, 0, 0, 0, 0, 0, 0} - ); - + List dynamicEvents = new List(); + dynamic index = new DynamicIndex(dynamicEvents); + ((bool)(index.SampleEventName == null)).Should().Be(true); + } + + [TestMethod] + public void TestForgivingUnknownEvent() + { + DynamicEventSchema.Set(correctSingleSchema); List dynamicEvents = new List { - sampleEvent + sampleEvent, + unknownEvent }; dynamic index = new DynamicIndex(dynamicEvents); + // As long as we don't throw exception, this is forgiving. + } - ((int)index.SampleEventName.version).Should().Be(1); - ((int)index.SampleEventName.Number).Should().Be(2); + [TestMethod] + public void TestReportingUnknownEvent() + { + DynamicEventSchema.Set(correctSingleSchema, false); + List dynamicEvents = new List + { + sampleEvent, + unknownEvent + }; + Action test = () => + { + dynamic index = new DynamicIndex(dynamicEvents); + }; + test.Should().Throw(); } } } \ No newline at end of file diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs index 3fbbb791364..ee9b5899016 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs @@ -1,4 +1,4 @@ -// TODO, AndrewAu, remove this condition when new TraceEvent is available through Nuget. +// TODO, andrewau, remove this condition when new TraceEvent is available through Nuget. #if CUSTOM_TRACE_EVENT using Microsoft.Diagnostics.Tracing.Analysis.GC; @@ -6,47 +6,74 @@ using System.Diagnostics; using System.Dynamic; using System.Runtime.CompilerServices; +using System.Text; -[assembly:InternalsVisibleTo("GC.Analysis.API.UnitTests")] +[assembly: InternalsVisibleTo("GC.Analysis.API.UnitTests")] namespace GC.Analysis.API.DynamicEvents { public static class TraceGCExtensions { + private readonly static ConditionalWeakTable dynamicEventsCache = new ConditionalWeakTable(); + public static dynamic DynamicEvents(this TraceGC traceGC) { - return new DynamicIndex(traceGC.DynamicEvents); + DynamicIndex dynamicIndex; + if (!dynamicEventsCache.TryGetValue(traceGC, out dynamicIndex)) + { + dynamicIndex = new DynamicIndex(traceGC.DynamicEvents); + dynamicEventsCache.Add(traceGC, dynamicIndex); + } + + return dynamicIndex; } } - public class DynamicEventSchema + public sealed class DynamicEventSchema { - internal static Dictionary>> DynamicEventSchemas = new Dictionary>>(); + internal static Dictionary DynamicEventSchemas = new Dictionary(); + + internal static bool allowPartialSchema; - public string DynamicEventName { get; set; } + public required string DynamicEventName { get; init; } - public List> Fields { get; set; } + public required List> Fields { get; init; } - public static void Set(List dynamicEventSchemas) + public int MinOccurrence { get; init; } = 0; + + public int MaxOccurrence { get; init; } = 1; + + public static void Set(List dynamicEventSchemas, bool allowPartialSchema = true) { DynamicEventSchemas.Clear(); + DynamicEventSchema.allowPartialSchema = allowPartialSchema; foreach (DynamicEventSchema dynamicEventSchema in dynamicEventSchemas) { if (DynamicEventSchemas.ContainsKey(dynamicEventSchema.DynamicEventName)) { throw new Exception($"Provided schema has a duplicated event named {dynamicEventSchema.DynamicEventName}"); } - Dictionary> fields = new Dictionary>(); + CompiledSchema schema = new CompiledSchema(); + if (dynamicEventSchema.MinOccurrence < 0) + { + throw new Exception($"Provided event named {dynamicEventSchema.DynamicEventName} has a negative MinOccurrence"); + } + if (dynamicEventSchema.MaxOccurrence < dynamicEventSchema.MinOccurrence) + { + throw new Exception($"Provided event named {dynamicEventSchema.DynamicEventName} has a MaxOccurrence smaller than MinOccurrence"); + } + schema.MinOccurrence = dynamicEventSchema.MinOccurrence; + schema.MaxOccurrence = dynamicEventSchema.MaxOccurrence; int offset = 0; foreach (KeyValuePair field in dynamicEventSchema.Fields) { - if (fields.ContainsKey(field.Key)) + if (schema.ContainsKey(field.Key)) { - throw new Exception($"Provided schema has a duplicated field named {field.Key}"); + DynamicEventSchemas.Clear(); + throw new Exception($"Provided event named {dynamicEventSchema.DynamicEventName} has a duplicated field named {field.Key}"); } - fields.Add(field.Key, Tuple.Create(offset, field.Value)); + schema.Add(field.Key, new DynamicEventField { FieldOffset = offset, FieldType = field.Value }); - // TODO, AndrewAu, all types that we envision this will be needed if (field.Value == typeof(ushort)) { offset += 2; @@ -55,66 +82,134 @@ public static void Set(List dynamicEventSchemas) { offset += 4; } + else if (field.Value == typeof(float)) + { + offset += 4; + } else if (field.Value == typeof(ulong)) { offset += 8; } + else if (field.Value == typeof(byte)) + { + offset += 1; + } + else if (field.Value == typeof(bool)) + { + offset += 1; + } else { - throw new Exception($"Provided schema has a field named {field.Key} using an unsupported type {field.Value}"); + DynamicEventSchemas.Clear(); + throw new Exception($"Provided event named {dynamicEventSchema.DynamicEventName} has a field named {field.Key} using an unsupported type {field.Value}"); } } - DynamicEventSchemas.Add(dynamicEventSchema.DynamicEventName, fields); + schema.Size = offset; + DynamicEventSchemas.Add(dynamicEventSchema.DynamicEventName, schema); } } } - internal class DynamicIndex : DynamicObject + internal sealed class DynamicEventField { - private List index; + public required int FieldOffset { get; init; } + public required Type FieldType { get; init; } + } - public DynamicIndex(List dynamicEvents) - { - // TODO, andrewau, index the events by name at this point - // TODO, andrewau, define multiplicity constraint - // TODO, andrewau, define size constraint - // TODO, andrewau, validate events according to constraints. - this.index = dynamicEvents; - } + internal sealed class CompiledSchema : Dictionary + { + public int MinOccurrence { get; set; } + public int MaxOccurrence { get; set; } + public int Size { get; set; } + } - public override bool TryGetMember(GetMemberBinder binder, out object result) + internal sealed class DynamicIndex : DynamicObject + { + private readonly Dictionary index; + + public DynamicIndex(List dynamicEvents) { - string name = binder.Name; - Dictionary> fieldOffsets; - if (DynamicEventSchema.DynamicEventSchemas.TryGetValue(name, out fieldOffsets)) + this.index = new Dictionary(); + Dictionary> indexedEvents = new Dictionary>(); + foreach (string eventName in DynamicEventSchema.DynamicEventSchemas.Keys) { - // TODO, at this point, we should already have the events indexed and validated - result = new DynamicEventObject(index.Single(r => string.Equals(r.Name, binder.Name)), fieldOffsets); - return true; + indexedEvents.Add(eventName, new List()); } - else + foreach (DynamicEvent dynamicEvent in dynamicEvents) { - result = null; - return false; + List? dynamicEventList; + if (indexedEvents.TryGetValue(dynamicEvent.Name, out dynamicEventList)) + { + dynamicEventList.Add(dynamicEvent); + } + else + { + if (!DynamicEventSchema.allowPartialSchema) + { + throw new Exception($"Event with unknown name {dynamicEvent.Name} is found."); + } + } } + foreach (string eventName in DynamicEventSchema.DynamicEventSchemas.Keys) + { + List eventList = indexedEvents[eventName]; + CompiledSchema schema = DynamicEventSchema.DynamicEventSchemas[eventName]; + if (eventList.Count > schema.MaxOccurrence) + { + throw new Exception($"More than {schema.MaxOccurrence} {eventName} is found."); + } + if (eventList.Count < schema.MinOccurrence) + { + throw new Exception($"Less than {schema.MinOccurrence} {eventName} is found."); + } + if (schema.MaxOccurrence == 1) + { + if (eventList.Count >= 1) + { + this.index.Add(eventName, new DynamicEventObject(eventList[0], schema)); + } + else + { + this.index.Add(eventName, null); + } + } + else + { + List output = new List(); + foreach (DynamicEvent dynamicEvent in eventList) + { + output.Add(new DynamicEventObject(dynamicEvent, schema)); + } + this.index.Add(eventName, output); + } + } + } + + public override bool TryGetMember(GetMemberBinder binder, out object? result) + { + return index.TryGetValue(binder.Name, out result); } } - internal class DynamicEventObject : DynamicObject + internal sealed class DynamicEventObject : DynamicObject { - private DynamicEvent dynamicEvent; + private string name; private Dictionary fieldValues; - public DynamicEventObject(DynamicEvent dynamicEvent, Dictionary> fieldOffsets) + public DynamicEventObject(DynamicEvent dynamicEvent, CompiledSchema schema) { - this.dynamicEvent = dynamicEvent; + this.name = dynamicEvent.Name; this.fieldValues = new Dictionary(); - foreach (KeyValuePair> field in fieldOffsets) + if (dynamicEvent.Payload.Length != schema.Size) { - object value = null; - int fieldOffset = field.Value.Item1; - Type fieldType = field.Value.Item2; - + throw new Exception($"Event {dynamicEvent.Name} does not have matching size"); + } + foreach (KeyValuePair field in schema) + { + object? value = null; + int fieldOffset = field.Value.FieldOffset; + Type fieldType = field.Value.FieldType; + if (fieldType == typeof(ushort)) { value = BitConverter.ToUInt16(dynamicEvent.Payload, fieldOffset); @@ -123,42 +218,55 @@ public DynamicEventObject(DynamicEvent dynamicEvent, Dictionary field in this.fieldValues) { - result = fieldValue; - return true; + fieldLength = Math.Max(fieldLength, field.Key.Length); } - else + StringBuilder sb = new StringBuilder(); + sb.Append(this.name); + foreach (KeyValuePair field in this.fieldValues) { - result = null; - return false; + sb.AppendLine(); + sb.Append(field.Key); + sb.Append(' ', fieldLength - field.Key.Length + 1); + sb.Append(": "); + sb.Append(field.Value); } - } - public override string ToString() - { - return "I am " + this.dynamicEvent.Name + " with these fields: \n" + string.Join("\n", this.fieldValues.Select(kvp => kvp.Key + "->" + kvp.Value)); + return sb.ToString(); } } }