From 60adabbf091fb750fabcaface945c68fd6dd3aa6 Mon Sep 17 00:00:00 2001 From: "Vincent Bu (Centific Technologies Inc)" Date: Mon, 12 May 2025 16:24:53 +0800 Subject: [PATCH 1/2] common class for server run command build --- .../ASPNetBenchmarks.CommandBuilder.cs | 167 +++++------------ .../GCPerfSim.CommandBuilder.cs | 121 ++++--------- .../ServerRun.CommandBuilder.cs | 168 ++++++++++++++++++ 3 files changed, 245 insertions(+), 211 deletions(-) create mode 100644 src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs 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 95847f4fe1d..d261ab6f036 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 @@ -1,5 +1,6 @@ using GC.Infrastructure.Core.Configurations.ASPNetBenchmarks; using GC.Infrastructure.Core.TraceCollection; +using System.Linq; using System.Text; namespace GC.Infrastructure.Core.CommandBuilders @@ -10,41 +11,27 @@ public static (string, string) Build(ASPNetBenchmarksConfiguration configuration { string processName = "crank"; StringBuilder commandStringBuilder = new(); - - // Load the base configuration. commandStringBuilder.Append(benchmarkNameToCommand.Value); + List> keyValueArgsList = new(); + // Environment Variables. // Add the environment variables from the configuration. - Dictionary environmentVariables = new(); - foreach (var env in configuration.Environment!.environment_variables) - { - environmentVariables[env.Key] = env.Value; - } + var environmentVariables = ServerRunCommandBuilder.OverrideDictionary( + configuration.Environment!.environment_variables!, + run.Value!.environment_variables!); - // Add overrides, if available. - if (run.Value.environment_variables != null) - { - foreach (var env in run.Value.environment_variables) - { - environmentVariables[env.Key] = env.Value; - } - } + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForEnvironmentVariables(environmentVariables)); - foreach (var env in environmentVariables) + // Check if the log file is specified, also add the fact that we want to retrieve the log file back. + // This log file should be named in concordance with the name of the run and the benchmark. + string? fileNameOfLog = environmentVariables!.GetValueOrDefault("DOTNET_GCLogFile", null); + if (!String.IsNullOrEmpty(fileNameOfLog)) { - string variable = env.Value; - - // Check if the log file is specified, also add the fact that we want to retrieve the log file back. - // This log file should be named in concordance with the name of the run and the benchmark. - 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.environmentVariables {env.Key}={variable} "); + string gcLogDownloadPath = Path.Combine(configuration.Output!.Path, run.Key, $"{benchmarkNameToCommand.Key}_GCLog"); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForGCLog(fileNameOfLog, gcLogDownloadPath)); } // Trace Collection. @@ -52,120 +39,56 @@ public static (string, string) Build(ASPNetBenchmarksConfiguration configuration if (configuration.TraceConfigurations != null && !string.Equals(configuration.TraceConfigurations.Type, "none", StringComparison.OrdinalIgnoreCase)) { CollectType collectType = TraceCollector.StringToCollectTypeMap[configuration.TraceConfigurations.Type]; - string collectionCommand = TraceCollector.WindowsCollectTypeMap[collectType]; - collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", ""); - - string traceFileSuffix = ".etl.zip"; - // Add specific commands. - if (os == OS.Windows) - { - commandStringBuilder.Append(" --application.collect true "); - commandStringBuilder.Append(" --application.collectStartup true "); - commandStringBuilder.Append($" --application.collectArguments \"{collectionCommand}\" "); - } - - else - { - if (configuration.TraceConfigurations.Type != "gc") - { - throw new ArgumentException($"{nameof(ASPNetBenchmarksCommandBuilder)}: Currently only GCCollectOnly traces are allowed for Linux."); - } - - else - { - traceFileSuffix = ".nettrace"; - commandStringBuilder.Append(" --application.dotnetTrace true "); - commandStringBuilder.Append(" --application.dotnetTraceProviders gc-collect "); - } - } - - // Add name of output. - commandStringBuilder.Append($" --application.options.traceOutput {Path.Combine(configuration.Output.Path, run.Key, (benchmarkNameToCommand.Key + "." + collectType)) + traceFileSuffix}"); - } + string traceFileSuffix = os == OS.Windows? ".etl.zip": ".nettrace"; + string tracePath = Path.Combine(configuration.Output.Path, run.Key, (benchmarkNameToCommand.Key + "." + collectType)) + traceFileSuffix; - string frameworkVersion = configuration.Environment.framework_version; - // Override the framework version if it's specified at the level of the run. - if (!string.IsNullOrEmpty(run.Value.framework_version)) - { - frameworkVersion = run.Value.framework_version; + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForTrace(configuration.TraceConfigurations.Type, tracePath, os)); } - commandStringBuilder.Append($" --application.framework {frameworkVersion} "); - string artifactsToUpload = run.Value.corerun!; + // Override the framework version if it's specified at the level of the run. + string frameworkVersion = string.IsNullOrEmpty(run.Value.framework_version) ? + configuration.Environment.framework_version : run.Value.framework_version; + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForFramework(frameworkVersion)); // If the corerun specified is a directory, upload the entire directory. // Else, we upload just the file. - if (Directory.Exists(run.Value.corerun!)) - { - artifactsToUpload = Path.Combine(artifactsToUpload, "*.*"); - } - commandStringBuilder.Append($" --application.options.outputFiles {artifactsToUpload} "); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForUploadFiles(run.Value.corerun)); // Get the logs. - commandStringBuilder.Append(" --application.options.downloadOutput true "); - commandStringBuilder.Append($" --application.options.downloadOutputOutput {Path.Combine(configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}.output.log")} "); - - commandStringBuilder.Append(" --application.options.downloadBuildLog true "); - commandStringBuilder.Append($" --application.options.downloadBuildLogOutput {Path.Combine(configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}.build.log")} "); - - commandStringBuilder.Append($" --json {Path.Combine(configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}.json")}"); + string logDownloadPathWithoutExtension = Path.Combine( + configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}"); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForGettingLogs(logDownloadPathWithoutExtension)); // Add the extra metrics by including the configuration. - commandStringBuilder.Append($" --config {Path.Combine("Commands", "RunCommand", "BaseSuite", "PercentileBasedMetricsConfiguration.yml")} "); - - // Add any additional arguments specified. - if (!string.IsNullOrEmpty(configuration.benchmark_settings.additional_arguments)) - { - commandStringBuilder.Append($" {configuration.benchmark_settings.additional_arguments} "); - } - - string commandString = commandStringBuilder.ToString(); + string configPath = Path.Combine("Commands", "RunCommand", "BaseSuite", "PercentileBasedMetricsConfiguration.yml"); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForConfig(configPath)); // Apply overrides. if (!string.IsNullOrEmpty(configuration.benchmark_settings.override_arguments)) { - List> overrideCommands = GetCrankArgsAsList(configuration.benchmark_settings.override_arguments); - 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. - List> currentCommands = GetCrankArgsAsList(commandString); - foreach (var item in overrideCommands) - { - var existing = currentCommands.Where(kv => kv.Key == item.Key).ToList(); - foreach (var kv in existing) - { - if (kv.Key != null) - { - currentCommands.Remove(kv); - } - } - - currentCommands.Add(item); - } - - commandString = string.Join(" ", currentCommands.Select(c => $"--{c.Key} {c.Value}")); - } - } + List> overrideCommands = ServerRunCommandBuilder.GetCrankArgsAsList( + configuration.benchmark_settings.override_arguments); - return (processName, commandString); - } + keyValueArgsList = ServerRunCommandBuilder.OverrideKeyValuePairList( + keyValueArgsList, overrideCommands); + } - internal static List> GetCrankArgsAsList(string input) - { - var keyValuePairs = new List>(); - var splitStr = input.Split(new[] { "--" }, StringSplitOptions.RemoveEmptyEntries); + // Add key-Value arguments to commandStringBuilder + commandStringBuilder.Append(ServerRunCommandBuilder.ConvertKeyValueArgsListToString(keyValueArgsList)); - foreach (var item in splitStr) + // Add any additional arguments specified. + if (!string.IsNullOrEmpty(configuration.benchmark_settings.additional_arguments)) { - var keyValue = item.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - if (keyValue.Length == 2) - { - keyValuePairs.Add(new KeyValuePair(keyValue[0], keyValue[1])); - } + commandStringBuilder.Append($" {configuration.benchmark_settings.additional_arguments} "); } - return keyValuePairs; + string commandString = commandStringBuilder.ToString(); + return (processName, commandString); } } } 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 7643f48711b..8885d060e6d 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 @@ -5,12 +5,6 @@ namespace GC.Infrastructure.Core.CommandBuilders { - public enum OS - { - Windows, - Linux - } - public static class GCPerfSimCommandBuilder { // Example output: @@ -52,108 +46,57 @@ public static (string, string) BuildForServer(GCPerfSimConfiguration configurati string processName = "crank"; StringBuilder commandStringBuilder = new(); + List> keyValueArgsList = new(); + // Add the configuration and the scenario to be run. string pathOfAssembly = Directory.GetParent(System.Reflection.Assembly.GetAssembly(typeof(GCPerfSimCommandBuilder)).Location).FullName; - commandStringBuilder.Append($"--config {Path.Combine(pathOfAssembly, "Commands", "RunCommand", "BaseSuite", "CrankConfiguration.yaml")} --scenario gcperfsim"); + string configPath = Path.Combine(pathOfAssembly, "Commands", "RunCommand", "BaseSuite", "CrankConfiguration.yaml"); + + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForConfig(configPath)); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForScenario("gcperfsim")); // Environment Variables. // Add the environment variables from the configuration. - Dictionary environmentVariables = new(); - foreach (var env in configuration.Environment.environment_variables) - { - environmentVariables[env.Key] = env.Value; - } - - // Add overrides, if available. - if (run.Value.environment_variables != null) - { - foreach (var env in run.Value.environment_variables) - { - environmentVariables[env.Key] = env.Value; - } - } - - foreach (var env in environmentVariables) - { - commandStringBuilder.Append($" --application.environmentVariables {env.Key}={env.Value} "); - } + Dictionary environmentVariables = ServerRunCommandBuilder.OverrideDictionary( + configuration.Environment.environment_variables, corerunOverride.Value.environment_variables); + environmentVariables = ServerRunCommandBuilder.OverrideDictionary( + environmentVariables, run.Value.environment_variables!); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForEnvironmentVariables(environmentVariables)); // GCPerfSim Configurations. - Dictionary parameters = new(); - foreach (var p in configuration.gcperfsim_configurations!.Parameters) - { - parameters[p.Key] = p.Value; - } - - // Add overrides, if available. - if (run.Value?.override_parameters != null) - { - foreach (var p in run.Value.override_parameters) - { - parameters[p.Key] = p.Value; - } - } + Dictionary parameters = ServerRunCommandBuilder.OverrideDictionary( + configuration.gcperfsim_configurations!.Parameters, run.Value.override_parameters); - foreach (var @params in parameters) - { - commandStringBuilder.Append($" --application.variables.{@params.Key} {@params.Value} "); - } + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListFoParameters(parameters)); // Trace Collection. // 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]; - string collectionCommand = os == OS.Windows ? TraceCollector.WindowsCollectTypeMap[collectType] : TraceCollector.LinuxCollectTypeMap[collectType]; - - collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", ""); - - // Add specific commands. - if (os == OS.Windows) - { - commandStringBuilder.Append(" --application.collect true "); - commandStringBuilder.Append(" --application.collectStartup true "); - commandStringBuilder.Append($" --application.collectArguments {collectionCommand} "); - } - - else - { - if (!string.Equals(configuration.TraceConfigurations.Type, "gc", StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException($"{nameof(GCPerfSimCommandBuilder)}: Currently only GCCollectOnly traces are allowed for Linux."); - } - - commandStringBuilder.Append(" --application.dotnetTrace true "); - commandStringBuilder.Append(" --application.dotnetTraceProviders gc-collect "); - } + string extension = os == OS.Windows ? ".etl.zip" : ".nettrace"; + string tracePath = Path.Combine(configuration.Output!.Path, run.Key, run.Key + "." + corerunOverride.Key + "." + iterationIdx + "." + collectType + extension); - commandStringBuilder.Append($" --application.framework net8.0 "); - - // 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)} "); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForTrace(configuration.TraceConfigurations.Type, tracePath, os)); + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForFramework("net8.0")); } - if (corerunOverride.Value.environment_variables != null) - { - foreach (var env in corerunOverride.Value.environment_variables) - { - commandStringBuilder.Append($" --application.environmentVariables {env.Key}={env.Value} "); - } - } + // Upload corerun or Core_Root + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForUploadFiles(corerunOverride.Value.Path)); - // If Path is a file, upload single file. - if (File.Exists(corerunOverride.Value.Path)) - { - commandStringBuilder.Append($" --application.options.outputFiles {corerunOverride.Value.Path}"); - } - // If Path is a folder, upload entire folder. - if (Directory.Exists(corerunOverride.Value.Path)) - { - commandStringBuilder.Append($" --application.options.outputFiles {Path.Combine(corerunOverride.Value.Path, "*")} "); - } + // Set profile + keyValueArgsList.AddRange( + ServerRunCommandBuilder.GenerateKeyValuePairListForProfile(serverName)); - commandStringBuilder.Append($" --profile {serverName} "); + // Add key-Value arguments to commandStringBuilder + commandStringBuilder.Append(ServerRunCommandBuilder.ConvertKeyValueArgsListToString(keyValueArgsList)); return (processName, commandStringBuilder.ToString()); } } diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs new file mode 100644 index 00000000000..caea21f207c --- /dev/null +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs @@ -0,0 +1,168 @@ +using GC.Infrastructure.Core.TraceCollection; + +namespace GC.Infrastructure.Core.CommandBuilders +{ + public enum OS + { + Windows, + Linux + } + + public static class ServerRunCommandBuilder + { + public static List> GenerateKeyValuePairListForUploadFiles(string? uploadFilesPath) + { + List> commandKVPList = new(); + string artifactsToUpload = Directory.Exists(uploadFilesPath!) ? Path.Combine(uploadFilesPath!, "*.*") : uploadFilesPath!; + commandKVPList.Add(new("application.options.outputFiles", artifactsToUpload)); + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForGettingLogs(string logDownloadPathWithoutExtension) + { + List> commandKVPList = new(); + commandKVPList.Add(new("application.options.downloadOutput", "true")); + commandKVPList.Add(new("application.options.downloadOutputOutput", $"{logDownloadPathWithoutExtension}.output.log")); + commandKVPList.Add(new("application.options.downloadBuildLog", "true")); + commandKVPList.Add(new("application.options.downloadBuildLogOutput", $"{logDownloadPathWithoutExtension}.build.log")); + commandKVPList.Add(new("json", $"{logDownloadPathWithoutExtension}.json")); + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForFramework(string frameworkVersion) + { + List> commandKVPList = new(); + commandKVPList.Add(new("application.framework", frameworkVersion)); + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForEnvironmentVariables(Dictionary environmentVariables) + { + return environmentVariables + .Select(kv => new KeyValuePair("application.environmentVariables", $"{kv.Key}={kv.Value}")) + .ToList(); + } + + public static List> GenerateKeyValuePairListFoParameters(Dictionary parameters) + { + return parameters + .Select(kv => new KeyValuePair($"application.variables.{kv.Key}", kv.Value)) + .ToList(); + } + + public static List> GenerateKeyValuePairListForConfig(string configPath) + { + List> commandKVPList = new(); + commandKVPList.Add(new("config", configPath)); + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForProfile(string profilePath) + { + List> commandKVPList = new(); + commandKVPList.Add(new("profile", profilePath)); + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForScenario(string scenario) + { + List> commandKVPList = new(); + commandKVPList.Add(new("scenario", scenario)); + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForTrace(string? traceType, string tracePath, OS os) + { + List> commandKVPList = new(); + CollectType collectType = TraceCollector.StringToCollectTypeMap[traceType]; + string collectionCommand = TraceCollector.WindowsCollectTypeMap[collectType]; + collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", ""); + + // Add specific commands. + if (os == OS.Windows) + { + commandKVPList.Add(new("application.collect", "true")); + commandKVPList.Add(new("application.collectStartup", "true")); + commandKVPList.Add(new("application.collectArguments", $"\"{collectionCommand}\"")); + } + else + { + if (traceType != "gc") + { + throw new ArgumentException($"{nameof(ServerRunCommandBuilder)}: Currently only GCCollectOnly traces are allowed for Linux."); + } + + else + { + commandKVPList.Add(new("application.dotnetTrace", "true")); + commandKVPList.Add(new("application.dotnetTraceProviders", "gc-collect")); + } + } + + // Add name of output. + commandKVPList.Add(new("application.options.traceOutput", tracePath)); + + return commandKVPList; + } + + public static List> GenerateKeyValuePairListForGCLog(string fileNameOfLog, string gcLogDownloadPath) + { + List> commandKVPList = new(); + commandKVPList.Add(new("application.options.downloadFiles", $"\"*{fileNameOfLog}.log\"")); + commandKVPList.Add(new("application.options.downloadFilesOutput", $"\"{gcLogDownloadPath}\"")); + return commandKVPList; + } + + public static Dictionary OverrideDictionary(Dictionary baseDict, Dictionary overrideDict) + { + Dictionary dict = new(baseDict); + overrideDict + .ToList() + .ForEach(kv => dict[kv.Key] = kv.Value); + return dict; + } + + public static List> OverrideKeyValuePairList(List> baseKVPList, List> overrideKVPList) + { + List> kvpList = new(baseKVPList); + + foreach (var item in overrideKVPList) + { + var existing = baseKVPList.Where(kv => kv.Key == item.Key).ToList(); + foreach (var kv in existing) + { + if (kv.Key != null) + { + baseKVPList.Remove(kv); + } + } + + baseKVPList.Add(item); + } + + return kvpList; + } + + internal static List> GetCrankArgsAsList(string input) + { + var keyValuePairs = new List>(); + var splitStr = input.Split(new[] { "--" }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var item in splitStr) + { + var keyValue = item.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + if (keyValue.Length == 2) + { + keyValuePairs.Add(new KeyValuePair(keyValue[0], keyValue[1])); + } + } + + return keyValuePairs; + } + + public static string ConvertKeyValueArgsListToString(List> keyValueArgsList) + { + return string.Join(" ", keyValueArgsList.Select(c => $" --{c.Key} {c.Value} ")); + } + } +} From c3c298a9a31f0c5e7ab75e24f8eaa2563ae15c29 Mon Sep 17 00:00:00 2001 From: "Vincent Bu (Centific Technologies Inc)" Date: Thu, 22 May 2025 09:44:59 +0800 Subject: [PATCH 2/2] rename GenerateKeyValuePairListForParameters and fix bugs in OverrideKeyValuePairList --- .../CommandBuilders/GCPerfSim.CommandBuilder.cs | 2 +- .../CommandBuilders/ServerRun.CommandBuilder.cs | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) 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 8885d060e6d..6c02d546524 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 @@ -71,7 +71,7 @@ public static (string, string) BuildForServer(GCPerfSimConfiguration configurati configuration.gcperfsim_configurations!.Parameters, run.Value.override_parameters); keyValueArgsList.AddRange( - ServerRunCommandBuilder.GenerateKeyValuePairListFoParameters(parameters)); + ServerRunCommandBuilder.GenerateKeyValuePairListForParameters(parameters)); // Trace Collection. // If the TraceConfiguration Key is specified in the yaml and diff --git a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs index caea21f207c..d0874bbc4e0 100644 --- a/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs +++ b/src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/ServerRun.CommandBuilder.cs @@ -43,7 +43,7 @@ public static List> GenerateKeyValuePairListForEnvi .ToList(); } - public static List> GenerateKeyValuePairListFoParameters(Dictionary parameters) + public static List> GenerateKeyValuePairListForParameters(Dictionary parameters) { return parameters .Select(kv => new KeyValuePair($"application.variables.{kv.Key}", kv.Value)) @@ -128,18 +128,17 @@ public static List> OverrideKeyValuePairList(List kv.Key == item.Key).ToList(); + var existing = kvpList.Where(kv => kv.Key == item.Key).ToList(); foreach (var kv in existing) { if (kv.Key != null) { - baseKVPList.Remove(kv); + kvpList.Remove(kv); } } - baseKVPList.Add(item); + kvpList.Add(item); } - return kvpList; }