Skip to content

Commit d86fb52

Browse files
authored
common class for server run command build (#4851)
* common class for server run command build * rename GenerateKeyValuePairListForParameters and fix bugs in OverrideKeyValuePairList
1 parent 7bce924 commit d86fb52

File tree

3 files changed

+244
-211
lines changed

3 files changed

+244
-211
lines changed
Lines changed: 45 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using GC.Infrastructure.Core.Configurations.ASPNetBenchmarks;
22
using GC.Infrastructure.Core.TraceCollection;
3+
using System.Linq;
34
using System.Text;
45

56
namespace GC.Infrastructure.Core.CommandBuilders
@@ -10,162 +11,84 @@ public static (string, string) Build(ASPNetBenchmarksConfiguration configuration
1011
{
1112
string processName = "crank";
1213
StringBuilder commandStringBuilder = new();
13-
14-
// Load the base configuration.
1514
commandStringBuilder.Append(benchmarkNameToCommand.Value);
1615

16+
List<KeyValuePair<string, string>> keyValueArgsList = new();
17+
1718
// Environment Variables.
1819
// Add the environment variables from the configuration.
19-
Dictionary<string, string> environmentVariables = new();
20-
foreach (var env in configuration.Environment!.environment_variables)
21-
{
22-
environmentVariables[env.Key] = env.Value;
23-
}
20+
var environmentVariables = ServerRunCommandBuilder.OverrideDictionary(
21+
configuration.Environment!.environment_variables!,
22+
run.Value!.environment_variables!);
2423

25-
// Add overrides, if available.
26-
if (run.Value.environment_variables != null)
27-
{
28-
foreach (var env in run.Value.environment_variables)
29-
{
30-
environmentVariables[env.Key] = env.Value;
31-
}
32-
}
24+
keyValueArgsList.AddRange(
25+
ServerRunCommandBuilder.GenerateKeyValuePairListForEnvironmentVariables(environmentVariables));
3326

34-
foreach (var env in environmentVariables)
27+
// Check if the log file is specified, also add the fact that we want to retrieve the log file back.
28+
// This log file should be named in concordance with the name of the run and the benchmark.
29+
string? fileNameOfLog = environmentVariables!.GetValueOrDefault("DOTNET_GCLogFile", null);
30+
if (!String.IsNullOrEmpty(fileNameOfLog))
3531
{
36-
string variable = env.Value;
37-
38-
// Check if the log file is specified, also add the fact that we want to retrieve the log file back.
39-
// This log file should be named in concordance with the name of the run and the benchmark.
40-
if (string.CompareOrdinal(env.Key, "DOTNET_GCLogFile") == 0)
41-
{
42-
string fileNameOfLog = Path.GetFileName(env.Value);
43-
commandStringBuilder.Append($" --application.options.downloadFiles \"*{fileNameOfLog}.log\" ");
44-
commandStringBuilder.Append($" --application.options.downloadFilesOutput \"{Path.Combine(configuration.Output!.Path, run.Key, $"{benchmarkNameToCommand.Key}_GCLog")}\" ");
45-
}
46-
47-
commandStringBuilder.Append($" --application.environmentVariables {env.Key}={variable} ");
32+
string gcLogDownloadPath = Path.Combine(configuration.Output!.Path, run.Key, $"{benchmarkNameToCommand.Key}_GCLog");
33+
keyValueArgsList.AddRange(
34+
ServerRunCommandBuilder.GenerateKeyValuePairListForGCLog(fileNameOfLog, gcLogDownloadPath));
4835
}
4936

5037
// Trace Collection.
5138
// If the TraceConfiguration Key is specified in the yaml and
5239
if (configuration.TraceConfigurations != null && !string.Equals(configuration.TraceConfigurations.Type, "none", StringComparison.OrdinalIgnoreCase))
5340
{
5441
CollectType collectType = TraceCollector.StringToCollectTypeMap[configuration.TraceConfigurations.Type];
55-
string collectionCommand = TraceCollector.WindowsCollectTypeMap[collectType];
56-
collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", "");
57-
58-
string traceFileSuffix = ".etl.zip";
59-
// Add specific commands.
60-
if (os == OS.Windows)
61-
{
62-
commandStringBuilder.Append(" --application.collect true ");
63-
commandStringBuilder.Append(" --application.collectStartup true ");
64-
commandStringBuilder.Append($" --application.collectArguments \"{collectionCommand}\" ");
65-
}
66-
67-
else
68-
{
69-
if (configuration.TraceConfigurations.Type != "gc")
70-
{
71-
throw new ArgumentException($"{nameof(ASPNetBenchmarksCommandBuilder)}: Currently only GCCollectOnly traces are allowed for Linux.");
72-
}
73-
74-
else
75-
{
76-
traceFileSuffix = ".nettrace";
77-
commandStringBuilder.Append(" --application.dotnetTrace true ");
78-
commandStringBuilder.Append(" --application.dotnetTraceProviders gc-collect ");
79-
}
80-
}
81-
82-
// Add name of output.
83-
commandStringBuilder.Append($" --application.options.traceOutput {Path.Combine(configuration.Output.Path, run.Key, (benchmarkNameToCommand.Key + "." + collectType)) + traceFileSuffix}");
84-
}
42+
string traceFileSuffix = os == OS.Windows? ".etl.zip": ".nettrace";
43+
string tracePath = Path.Combine(configuration.Output.Path, run.Key, (benchmarkNameToCommand.Key + "." + collectType)) + traceFileSuffix;
8544

86-
string frameworkVersion = configuration.Environment.framework_version;
87-
// Override the framework version if it's specified at the level of the run.
88-
if (!string.IsNullOrEmpty(run.Value.framework_version))
89-
{
90-
frameworkVersion = run.Value.framework_version;
45+
keyValueArgsList.AddRange(
46+
ServerRunCommandBuilder.GenerateKeyValuePairListForTrace(configuration.TraceConfigurations.Type, tracePath, os));
9147
}
92-
commandStringBuilder.Append($" --application.framework {frameworkVersion} ");
9348

94-
string artifactsToUpload = run.Value.corerun!;
49+
// Override the framework version if it's specified at the level of the run.
50+
string frameworkVersion = string.IsNullOrEmpty(run.Value.framework_version) ?
51+
configuration.Environment.framework_version : run.Value.framework_version;
52+
keyValueArgsList.AddRange(
53+
ServerRunCommandBuilder.GenerateKeyValuePairListForFramework(frameworkVersion));
9554

9655
// If the corerun specified is a directory, upload the entire directory.
9756
// Else, we upload just the file.
98-
if (Directory.Exists(run.Value.corerun!))
99-
{
100-
artifactsToUpload = Path.Combine(artifactsToUpload, "*.*");
101-
}
102-
commandStringBuilder.Append($" --application.options.outputFiles {artifactsToUpload} ");
57+
keyValueArgsList.AddRange(
58+
ServerRunCommandBuilder.GenerateKeyValuePairListForUploadFiles(run.Value.corerun));
10359

10460
// Get the logs.
105-
commandStringBuilder.Append(" --application.options.downloadOutput true ");
106-
commandStringBuilder.Append($" --application.options.downloadOutputOutput {Path.Combine(configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}.output.log")} ");
107-
108-
commandStringBuilder.Append(" --application.options.downloadBuildLog true ");
109-
commandStringBuilder.Append($" --application.options.downloadBuildLogOutput {Path.Combine(configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}.build.log")} ");
110-
111-
commandStringBuilder.Append($" --json {Path.Combine(configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}.json")}");
61+
string logDownloadPathWithoutExtension = Path.Combine(
62+
configuration.Output.Path, run.Key, $"{benchmarkNameToCommand.Key}_{run.Key}");
63+
keyValueArgsList.AddRange(
64+
ServerRunCommandBuilder.GenerateKeyValuePairListForGettingLogs(logDownloadPathWithoutExtension));
11265

11366
// Add the extra metrics by including the configuration.
114-
commandStringBuilder.Append($" --config {Path.Combine("Commands", "RunCommand", "BaseSuite", "PercentileBasedMetricsConfiguration.yml")} ");
115-
116-
// Add any additional arguments specified.
117-
if (!string.IsNullOrEmpty(configuration.benchmark_settings.additional_arguments))
118-
{
119-
commandStringBuilder.Append($" {configuration.benchmark_settings.additional_arguments} ");
120-
}
121-
122-
string commandString = commandStringBuilder.ToString();
67+
string configPath = Path.Combine("Commands", "RunCommand", "BaseSuite", "PercentileBasedMetricsConfiguration.yml");
68+
keyValueArgsList.AddRange(
69+
ServerRunCommandBuilder.GenerateKeyValuePairListForConfig(configPath));
12370

12471
// Apply overrides.
12572
if (!string.IsNullOrEmpty(configuration.benchmark_settings.override_arguments))
12673
{
127-
List<KeyValuePair<string, string>> overrideCommands = GetCrankArgsAsList(configuration.benchmark_settings.override_arguments);
128-
if (overrideCommands.Count > 0)
129-
{
130-
// Take the current commands and first replace all the keys that match the override commands.
131-
// Subsequently, add the new overrides and then convert the key-value pair list back to a string.
132-
List<KeyValuePair<string, string>> currentCommands = GetCrankArgsAsList(commandString);
133-
foreach (var item in overrideCommands)
134-
{
135-
var existing = currentCommands.Where(kv => kv.Key == item.Key).ToList();
136-
foreach (var kv in existing)
137-
{
138-
if (kv.Key != null)
139-
{
140-
currentCommands.Remove(kv);
141-
}
142-
}
143-
144-
currentCommands.Add(item);
145-
}
146-
147-
commandString = string.Join(" ", currentCommands.Select(c => $"--{c.Key} {c.Value}"));
148-
}
149-
}
74+
List<KeyValuePair<string, string>> overrideCommands = ServerRunCommandBuilder.GetCrankArgsAsList(
75+
configuration.benchmark_settings.override_arguments);
15076

151-
return (processName, commandString);
152-
}
77+
keyValueArgsList = ServerRunCommandBuilder.OverrideKeyValuePairList(
78+
keyValueArgsList, overrideCommands);
79+
}
15380

154-
internal static List<KeyValuePair<string, string>> GetCrankArgsAsList(string input)
155-
{
156-
var keyValuePairs = new List<KeyValuePair<string, string>>();
157-
var splitStr = input.Split(new[] { "--" }, StringSplitOptions.RemoveEmptyEntries);
81+
// Add key-Value arguments to commandStringBuilder
82+
commandStringBuilder.Append(ServerRunCommandBuilder.ConvertKeyValueArgsListToString(keyValueArgsList));
15883

159-
foreach (var item in splitStr)
84+
// Add any additional arguments specified.
85+
if (!string.IsNullOrEmpty(configuration.benchmark_settings.additional_arguments))
16086
{
161-
var keyValue = item.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
162-
if (keyValue.Length == 2)
163-
{
164-
keyValuePairs.Add(new KeyValuePair<string, string>(keyValue[0], keyValue[1]));
165-
}
87+
commandStringBuilder.Append($" {configuration.benchmark_settings.additional_arguments} ");
16688
}
16789

168-
return keyValuePairs;
90+
string commandString = commandStringBuilder.ToString();
91+
return (processName, commandString);
16992
}
17093
}
17194
}

src/benchmarks/gc/GC.Infrastructure/GC.Infrastructure.Core/CommandBuilders/GCPerfSim.CommandBuilder.cs

Lines changed: 32 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@
55

66
namespace GC.Infrastructure.Core.CommandBuilders
77
{
8-
public enum OS
9-
{
10-
Windows,
11-
Linux
12-
}
13-
148
public static class GCPerfSimCommandBuilder
159
{
1610
// Example output:
@@ -52,108 +46,57 @@ public static (string, string) BuildForServer(GCPerfSimConfiguration configurati
5246
string processName = "crank";
5347
StringBuilder commandStringBuilder = new();
5448

49+
List<KeyValuePair<string, string>> keyValueArgsList = new();
50+
5551
// Add the configuration and the scenario to be run.
5652
string pathOfAssembly = Directory.GetParent(System.Reflection.Assembly.GetAssembly(typeof(GCPerfSimCommandBuilder)).Location).FullName;
57-
commandStringBuilder.Append($"--config {Path.Combine(pathOfAssembly, "Commands", "RunCommand", "BaseSuite", "CrankConfiguration.yaml")} --scenario gcperfsim");
53+
string configPath = Path.Combine(pathOfAssembly, "Commands", "RunCommand", "BaseSuite", "CrankConfiguration.yaml");
54+
55+
keyValueArgsList.AddRange(
56+
ServerRunCommandBuilder.GenerateKeyValuePairListForConfig(configPath));
57+
keyValueArgsList.AddRange(
58+
ServerRunCommandBuilder.GenerateKeyValuePairListForScenario("gcperfsim"));
5859

5960
// Environment Variables.
6061
// Add the environment variables from the configuration.
61-
Dictionary<string, string> environmentVariables = new();
62-
foreach (var env in configuration.Environment.environment_variables)
63-
{
64-
environmentVariables[env.Key] = env.Value;
65-
}
66-
67-
// Add overrides, if available.
68-
if (run.Value.environment_variables != null)
69-
{
70-
foreach (var env in run.Value.environment_variables)
71-
{
72-
environmentVariables[env.Key] = env.Value;
73-
}
74-
}
75-
76-
foreach (var env in environmentVariables)
77-
{
78-
commandStringBuilder.Append($" --application.environmentVariables {env.Key}={env.Value} ");
79-
}
62+
Dictionary<string, string> environmentVariables = ServerRunCommandBuilder.OverrideDictionary(
63+
configuration.Environment.environment_variables, corerunOverride.Value.environment_variables);
64+
environmentVariables = ServerRunCommandBuilder.OverrideDictionary(
65+
environmentVariables, run.Value.environment_variables!);
66+
keyValueArgsList.AddRange(
67+
ServerRunCommandBuilder.GenerateKeyValuePairListForEnvironmentVariables(environmentVariables));
8068

8169
// GCPerfSim Configurations.
82-
Dictionary<string, string> parameters = new();
83-
foreach (var p in configuration.gcperfsim_configurations!.Parameters)
84-
{
85-
parameters[p.Key] = p.Value;
86-
}
87-
88-
// Add overrides, if available.
89-
if (run.Value?.override_parameters != null)
90-
{
91-
foreach (var p in run.Value.override_parameters)
92-
{
93-
parameters[p.Key] = p.Value;
94-
}
95-
}
70+
Dictionary<string, string> parameters = ServerRunCommandBuilder.OverrideDictionary(
71+
configuration.gcperfsim_configurations!.Parameters, run.Value.override_parameters);
9672

97-
foreach (var @params in parameters)
98-
{
99-
commandStringBuilder.Append($" --application.variables.{@params.Key} {@params.Value} ");
100-
}
73+
keyValueArgsList.AddRange(
74+
ServerRunCommandBuilder.GenerateKeyValuePairListForParameters(parameters));
10175

10276
// Trace Collection.
10377
// If the TraceConfiguration Key is specified in the yaml and
10478
if (configuration.TraceConfigurations != null && !string.Equals(configuration.TraceConfigurations.Type, "none", StringComparison.OrdinalIgnoreCase))
10579
{
10680
CollectType collectType = TraceCollector.StringToCollectTypeMap[configuration.TraceConfigurations.Type];
107-
string collectionCommand = os == OS.Windows ? TraceCollector.WindowsCollectTypeMap[collectType] : TraceCollector.LinuxCollectTypeMap[collectType];
108-
109-
collectionCommand = collectionCommand.Replace(" ", ";").Replace("/", "");
110-
111-
// Add specific commands.
112-
if (os == OS.Windows)
113-
{
114-
commandStringBuilder.Append(" --application.collect true ");
115-
commandStringBuilder.Append(" --application.collectStartup true ");
116-
commandStringBuilder.Append($" --application.collectArguments {collectionCommand} ");
117-
}
118-
119-
else
120-
{
121-
if (!string.Equals(configuration.TraceConfigurations.Type, "gc", StringComparison.OrdinalIgnoreCase))
122-
{
123-
throw new ArgumentException($"{nameof(GCPerfSimCommandBuilder)}: Currently only GCCollectOnly traces are allowed for Linux.");
124-
}
125-
126-
commandStringBuilder.Append(" --application.dotnetTrace true ");
127-
commandStringBuilder.Append(" --application.dotnetTraceProviders gc-collect ");
128-
}
81+
string extension = os == OS.Windows ? ".etl.zip" : ".nettrace";
82+
string tracePath = Path.Combine(configuration.Output!.Path, run.Key, run.Key + "." + corerunOverride.Key + "." + iterationIdx + "." + collectType + extension);
12983

130-
commandStringBuilder.Append($" --application.framework net8.0 ");
131-
132-
// Add name of output.
133-
string extension = os == OS.Windows ? "etl.zip" : "nettrace";
134-
commandStringBuilder.Append($" --application.options.traceOutput {Path.Combine(configuration.Output!.Path, run.Key, run.Key + "." + corerunOverride.Key + "." + iterationIdx + "." + collectType + "." + extension)} ");
84+
keyValueArgsList.AddRange(
85+
ServerRunCommandBuilder.GenerateKeyValuePairListForTrace(configuration.TraceConfigurations.Type, tracePath, os));
86+
keyValueArgsList.AddRange(
87+
ServerRunCommandBuilder.GenerateKeyValuePairListForFramework("net8.0"));
13588
}
13689

137-
if (corerunOverride.Value.environment_variables != null)
138-
{
139-
foreach (var env in corerunOverride.Value.environment_variables)
140-
{
141-
commandStringBuilder.Append($" --application.environmentVariables {env.Key}={env.Value} ");
142-
}
143-
}
90+
// Upload corerun or Core_Root
91+
keyValueArgsList.AddRange(
92+
ServerRunCommandBuilder.GenerateKeyValuePairListForUploadFiles(corerunOverride.Value.Path));
14493

145-
// If Path is a file, upload single file.
146-
if (File.Exists(corerunOverride.Value.Path))
147-
{
148-
commandStringBuilder.Append($" --application.options.outputFiles {corerunOverride.Value.Path}");
149-
}
150-
// If Path is a folder, upload entire folder.
151-
if (Directory.Exists(corerunOverride.Value.Path))
152-
{
153-
commandStringBuilder.Append($" --application.options.outputFiles {Path.Combine(corerunOverride.Value.Path, "*")} ");
154-
}
94+
// Set profile
95+
keyValueArgsList.AddRange(
96+
ServerRunCommandBuilder.GenerateKeyValuePairListForProfile(serverName));
15597

156-
commandStringBuilder.Append($" --profile {serverName} ");
98+
// Add key-Value arguments to commandStringBuilder
99+
commandStringBuilder.Append(ServerRunCommandBuilder.ConvertKeyValueArgsListToString(keyValueArgsList));
157100
return (processName, commandStringBuilder.ToString());
158101
}
159102
}

0 commit comments

Comments
 (0)