Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Users/nmalkapuram/my sql compete recipe #403

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void MySQLSysbenchOLTPWorkloadProfileActionsWillNotBeExecutedIfTheWorkloa

[Test]
[TestCase("PERF-MYSQL-SYSBENCH-OLTP.json", PlatformID.Unix, Architecture.X64)]
[Ignore("This functional test takes more than a minute to run. There is likely a Task.Delay somewhere that needs to be designed better to avoid long blocking behavior")]
// [Ignore("This functional test takes more than a minute to run. There is likely a Task.Delay somewhere that needs to be designed better to avoid long blocking behavior")]
public async Task MySQLSysbenchOLTPWorkloadProfileExecutesTheExpectedWorkloadsOnUnixPlatform(string profile, PlatformID platform, Architecture architecture)
{
this.fixture.Setup(platform, architecture, this.clientAgentId).SetupLayout(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ namespace VirtualClient.Actions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using MathNet.Numerics;
using Microsoft.Extensions.DependencyInjection;
using VirtualClient;
using VirtualClient.Common;
Expand Down Expand Up @@ -98,7 +100,8 @@ await this.ServerApiClient.PollForExpectedStateAsync<CtsTrafficServerState>(
cancellationToken,
this.PollingInterval);

string targetIPAddress = this.GetServerIPAddress(cancellationToken);
ClientInstance instance = this.Layout.GetClientInstance(this.AgentId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in other comments, there is an extension method on the VirtualClientComponent class that can get instances by role. We don't need the GetServerIpAddress method.

string targetIPAddress = (instance.Role == ClientRole.Server) ? "localhost" : this.GetServerIpAddress();

string ctsTrafficCommandArgs = $"-Target:{targetIPAddress} -Consoleverbosity:1 -StatusFilename:{this.StatusFileName} " +
$@"-ConnectionFilename:{this.ConnectionsFileName} -ErrorFileName:{this.ErrorFileName} -Port:{this.Port} " +
Expand Down Expand Up @@ -146,17 +149,17 @@ await this.ServerApiClient.PollForExpectedStateAsync<CtsTrafficServerState>(

}

private string GetServerIPAddress(CancellationToken cancellationToken)
private string GetServerIpAddress()
{
string targetIPAddress = "localhost";
string serverIPAddress = IPAddress.Loopback.ToString();

if (this.IsMultiRoleLayout())
{
ClientInstance serverInstance = this.GetLayoutClientInstances(ClientRole.Server).First();
targetIPAddress = serverInstance.IPAddress;
serverIPAddress = serverInstance.IPAddress;
}

return targetIPAddress;
return serverIPAddress;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ namespace VirtualClient.Actions
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MathNet.Numerics;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using VirtualClient.Common;
Expand All @@ -27,6 +29,8 @@ public class SysbenchClientExecutor : SysbenchExecutor
{
private string sysbenchExecutionArguments;
private string sysbenchLoggingArguments;
private string sysbenchPrepareArguments;
private string packageDirectory;

/// <summary>
/// Initializes a new instance of the <see cref="SysbenchClientExecutor"/> class.
Expand Down Expand Up @@ -169,7 +173,24 @@ private Task ExecuteWorkloadAsync(EventContext telemetryContext, CancellationTok
{
if (this.Benchmark == BenchmarkName.OLTP)
{
await this.RunOLTPWorkloadAsync(telemetryContext, cancellationToken);
if (this.Action == ClientAction.TruncateDatabase)
{
DependencyPath workloadPackage = await this.GetPackageAsync(this.PackageName, cancellationToken).ConfigureAwait(false);
nmalkapuram marked this conversation as resolved.
Show resolved Hide resolved
workloadPackage.ThrowIfNull(this.PackageName);

DependencyPath package = await this.GetPlatformSpecificPackageAsync(this.PackageName, cancellationToken);
this.packageDirectory = package.Path;

await this.TruncateMySQLDatabaseAsync(telemetryContext, cancellationToken).ConfigureAwait(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we doing this? The logic to create the database is already a part of the MySqlServerConfiguration and SysbenchConfiguration classes. We ARE NOT trying to support rebuilding the database on every round of processing. This is extremely inefficient.

It may not be clear how we intend to support this database workload, so I will share the guidance given to Erica initially. The related profile should build the database out on a first run. It does this making no assumptions and will/should drop the database if it exists. The database should then be reused on each subsequent run. This means that the database must be a set size (e.g. #tables, records) for a given profile. If the user decides they want to operate against a database that is sized differently, they are expected to perform a "clean". This removes the state tracking and causes VC to behave like it is a first time run again thus dropping any existing DB and recreating it. I don't want to attempt to handle deep eccentricities with database workloads such as resizing an existing database in any other way other than dropping and recreating.

}
else if (this.Action == ClientAction.PopulateDatabase)
{
await this.PrepareOLTPMySQLDatabase(telemetryContext, cancellationToken);
}
else
{
await this.RunOLTPWorkloadAsync(telemetryContext, cancellationToken);
}
}
else if (this.Benchmark == BenchmarkName.TPCC)
{
Expand All @@ -194,11 +215,10 @@ private async Task RunOLTPWorkloadAsync(EventContext telemetryContext, Cancellat
this.sysbenchLoggingArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --workload {this.Workload} --threadCount {threadCount} --tableCount {tableCount} --recordCount {recordCount} ";
this.sysbenchExecutionArguments = this.sysbenchLoggingArguments + $"--hostIpAddress {this.ServerIpAddress} --durationSecs {this.Duration.TotalSeconds} --password {this.SuperUserPassword}";

string command = "python3";
string script = $"{this.SysbenchPackagePath}/run-workload.py ";

using (IProcessProxy process = await this.ExecuteCommandAsync(
command,
SysbenchExecutor.PythonCommand,
script + this.sysbenchExecutionArguments,
this.SysbenchPackagePath,
telemetryContext,
Expand All @@ -223,11 +243,10 @@ private async Task RunTPCCWorkloadAsync(EventContext telemetryContext, Cancellat
this.sysbenchLoggingArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --workload tpcc --threadCount {threadCount} --tableCount {tableCount} --warehouses {warehouseCount} ";
this.sysbenchExecutionArguments = this.sysbenchLoggingArguments + $"--hostIpAddress {this.ServerIpAddress} --durationSecs {this.Duration.TotalSeconds} --password {this.SuperUserPassword}";

string command = "python3";
string script = $"{this.SysbenchPackagePath}/run-workload.py ";

using (IProcessProxy process = await this.ExecuteCommandAsync(
command,
SysbenchExecutor.PythonCommand,
script + this.sysbenchExecutionArguments,
this.SysbenchPackagePath,
telemetryContext,
Expand All @@ -242,5 +261,69 @@ private async Task RunTPCCWorkloadAsync(EventContext telemetryContext, Cancellat
}
}
}

private async Task TruncateMySQLDatabaseAsync(EventContext telemetryContext, CancellationToken cancellationToken)
{
string arguments = $"{this.packageDirectory}/truncate-tables.py --dbName {this.DatabaseName}";
nmalkapuram marked this conversation as resolved.
Show resolved Hide resolved

string serverIps = "localhost";

if (this.IsMultiRoleLayout())
{
ClientInstance instance = this.Layout.GetClientInstance(this.AgentId);
serverIps = (instance.Role == ClientRole.Server) ? "localhost" : this.GetLayoutClientInstances(ClientRole.Server).First().IPAddress;
}

arguments += $" --clientIps \"{serverIps}\"";

using (IProcessProxy process = await this.ExecuteCommandAsync(
SysbenchExecutor.PythonCommand,
arguments,
Environment.CurrentDirectory,
telemetryContext,
cancellationToken))
{
if (!cancellationToken.IsCancellationRequested)
{
await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true);
process.ThrowIfDependencyInstallationFailed(process.StandardError.ToString());
}
}
}

private async Task PrepareOLTPMySQLDatabase(EventContext telemetryContext, CancellationToken cancellationToken)
{
int tableCount = GetTableCount(this.DatabaseScenario, this.TableCount, this.Workload);
int threadCount = GetThreadCount(this.SystemManager, this.DatabaseScenario, this.Threads);
int recordCount = GetRecordCount(this.SystemManager, this.DatabaseScenario, this.RecordCount);

this.sysbenchPrepareArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --tableCount {tableCount} --recordCount {recordCount} --threadCount {threadCount} --password {this.SuperUserPassword}";

string serverIp = "localhost";

if (this.IsMultiRoleLayout())
{
ClientInstance instance = this.Layout.GetClientInstance(this.AgentId);
serverIp = (instance.Role == ClientRole.Server) ? "localhost" : this.GetLayoutClientInstances(ClientRole.Server).First().IPAddress;
}

this.sysbenchPrepareArguments += $" --host \"{serverIp}\"";

string arguments = $"{this.SysbenchPackagePath}/populate-database.py ";

using (IProcessProxy process = await this.ExecuteCommandAsync(
SysbenchExecutor.PythonCommand,
arguments + this.sysbenchPrepareArguments,
this.SysbenchPackagePath,
telemetryContext,
cancellationToken))
{
if (!cancellationToken.IsCancellationRequested)
{
await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true);
process.ThrowIfErrored<WorkloadException>(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ namespace VirtualClient.Actions
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -81,11 +84,20 @@ private async Task PrepareOLTPMySQLDatabase(EventContext telemetryContext, Cance

this.sysbenchPrepareArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --tableCount {tableCount} --recordCount {recordCount} --threadCount {threadCount} --password {this.SuperUserPassword}";

string command = $"python3";
string serverIp = "localhost";

if (this.IsMultiRoleLayout())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? The SysbenchConfiguration SHOULD be running on the Server role (database) system to begin with.

{
ClientInstance instance = this.Layout.GetClientInstance(this.AgentId);
serverIp = (instance.Role == ClientRole.Server) ? "localhost" : this.GetServerIpAddress();
}

this.sysbenchPrepareArguments += $" --host \"{serverIp}\"";

string arguments = $"{this.SysbenchPackagePath}/populate-database.py ";

using (IProcessProxy process = await this.ExecuteCommandAsync(
command,
SysbenchExecutor.PythonCommand,
arguments + this.sysbenchPrepareArguments,
this.SysbenchPackagePath,
telemetryContext,
Expand All @@ -107,11 +119,10 @@ private async Task PrepareTPCCMySQLDatabase(EventContext telemetryContext, Cance

this.sysbenchPrepareArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --tableCount {tableCount} --warehouses {warehouseCount} --threadCount {threadCount} --password {this.SuperUserPassword}";

string command = $"python3";
string arguments = $"{this.SysbenchPackagePath}/populate-database.py ";

using (IProcessProxy process = await this.ExecuteCommandAsync(
command,
SysbenchExecutor.PythonCommand,
arguments + this.sysbenchPrepareArguments,
this.SysbenchPackagePath,
telemetryContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public class SysbenchExecutor : VirtualClientComponent
/// </summary>
public const int SelectWorkloadDefaultTableCount = 1;

/// <summary>
/// const for python command.
/// </summary>
protected const string PythonCommand = "python3";

private readonly IStateManager stateManager;
private static readonly string[] SelectWorkloads =
{
Expand Down Expand Up @@ -175,6 +180,18 @@ public string Workload
}
}

/// <summary>
/// The specifed action that controls the execution of the dependency.
/// </summary>
public string Action
{
get
{
this.Parameters.TryGetValue(nameof(this.Action), out IConvertible action);
return action?.ToString();
}
}

/// <summary>
/// Client used to communicate with the hosted instance of the
/// Virtual Client API at server side.
Expand Down Expand Up @@ -299,7 +316,10 @@ await this.CheckDistroSupportAsync(telemetryContext, cancellationToken)
DependencyPath package = await this.GetPackageAsync(this.PackageName, cancellationToken);
this.SysbenchPackagePath = package.Path;

await this.InitializeExecutablesAsync(telemetryContext, cancellationToken);
if (this.Action != ClientAction.TruncateDatabase)
{
await this.InitializeExecutablesAsync(telemetryContext, cancellationToken);
}

this.InitializeApiClients(telemetryContext, cancellationToken);

Expand Down Expand Up @@ -377,6 +397,23 @@ protected async Task InitializeExecutablesAsync(EventContext telemetryContext, C
await this.stateManager.SaveStateAsync<SysbenchState>(nameof(SysbenchState), state, cancellationToken);
}

/// <summary>
///
/// </summary>
/// <returns></returns>
protected string GetServerIpAddress()
{
string serverIPAddress = IPAddress.Loopback.ToString();

if (this.IsMultiRoleLayout())
{
ClientInstance serverInstance = this.GetLayoutClientInstances(ClientRole.Server).First();
serverIPAddress = serverInstance.IPAddress;
}

return serverIPAddress;
}

private async Task CheckDistroSupportAsync(EventContext telemetryContext, CancellationToken cancellationToken)
{
if (this.Platform == PlatformID.Unix)
Expand Down Expand Up @@ -460,5 +497,26 @@ internal class BenchmarkName
public const string OLTP = nameof(OLTP);
public const string TPCC = nameof(TPCC);
}

/// <summary>
/// Supported Sysbench Client actions.
/// </summary>
internal class ClientAction
{
/// <summary>
/// Creates Database on MySQL server and Users on Server and any Clients.
/// </summary>
public const string PopulateDatabase = nameof(PopulateDatabase);

/// <summary>
/// Truncates all tables existing in database
/// </summary>
public const string TruncateDatabase = nameof(TruncateDatabase);

/// <summary>
/// Truncates all tables existing in database
/// </summary>
public const string RunWorkload = nameof(RunWorkload);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace VirtualClient.Contracts
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;

/// <summary>
/// Extensions for <see cref="EnvironmentLayout"/> instances.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)

if (this.Parameters?.Any() == true)
{
Console.WriteLine("before adding parameters to dictonary");
this.MetadataContract.Add(
this.Parameters.Keys.ToDictionary(key => key, entry => this.Parameters[entry] as object).ObscureSecrets(),
MetadataContractCategory.Scenario,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ public async Task ProfileExpressionEvaluatorSupportsFunctionReferences()

Dictionary<string, string> expressions = new Dictionary<string, string>
{
{"{calculate(67419566080 * 800000 / 100)}", "23456"},
{ "{calculate(512 + 2)}", "514" },
{ "{calculate(512 - 2)}", "510" },
{ "{calculate(512 * 2)}", "1024" },
Expand Down
Loading
Loading