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

Added a new optional parameter ClientsMax to Memtier Client Executor. #341

Merged
merged 16 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,37 @@ public class MemtierBenchmarkClientExecutorTests
private DependencyPath mockPackage;
private string results;

private void SetMultipleServerInstances()
{
// Setup:
// Two Memcached server instances running on ports 6379 and 6380 with affinity to 4 logical processors
this.mockFixture.ApiClient.OnGetState(nameof(ServerState))
.ReturnsAsync(this.mockFixture.CreateHttpResponse(
HttpStatusCode.OK,
new Item<ServerState>(nameof(ServerState), new ServerState(new List<PortDescription>
{
new PortDescription
{
CpuAffinity = "0,1,2,3",
Port = 6379
},
new PortDescription
{
CpuAffinity = "0,1,2,3",
Port = 6380
}
}))));

this.mockFixture.ApiClientManager.Setup(mgr => mgr.GetOrCreateApiClient(It.IsAny<string>(), It.IsAny<ClientInstance>()))
.Returns<string, ClientInstance>((id, instance) => this.mockFixture.ApiClient.Object);

this.mockFixture.ApiClient.OnGetHeartbeat()
.ReturnsAsync(this.mockFixture.CreateHttpResponse(System.Net.HttpStatusCode.OK));

this.mockFixture.ApiClient.OnGetServerOnline()
.ReturnsAsync(this.mockFixture.CreateHttpResponse(System.Net.HttpStatusCode.OK));
}

[SetUp]
public void SetupDefaults()
{
Expand Down Expand Up @@ -165,21 +196,30 @@ public async Task MemtierBenchmarkClientExecutorExecutesExpectedCommandsWhenAUse
[Test]
public async Task MemtierBenchmarkClientExecutorExecutesExpectedCommands2ClientInstances()
{
this.SetMultipleServerInstances();

using (var executor = new TestMemtierBenchmarkClientExecutor(this.mockFixture.Dependencies, this.mockFixture.Parameters))
{
// 2 client instances running in-parallel to target the server.
// 2 client instances running in-parallel to target each of the 2 servers
executor.Parameters[nameof(executor.ClientInstances)] = 2;
executor.Parameters[nameof(executor.MaxClients)] = 6;

List<string> expectedCommands = new List<string>()
{
// Make the benchmark toolset executable
$"sudo chmod +x \"{this.mockPackage.Path}/memtier_benchmark\"",

// Client instance #1
$"sudo bash -c \"numactl -C 1 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",
// Client instance #1 hitting server #1
$"sudo bash -c \"numactl -C 2 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",

// Client instance #2
$"sudo bash -c \"numactl -C 1 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\""
// Client instance #2 hitting server #1
$"sudo bash -c \"numactl -C 2 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",

// Client instance #1 hitting server #2
$"sudo bash -c \"numactl -C 3 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6380 {executor.CommandLine}\"",

// Client instance #2 hitting server #2
$"sudo bash -c \"numactl -C 3 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6380 {executor.CommandLine}\""
};

this.mockFixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDirectory) =>
Expand All @@ -198,27 +238,31 @@ public async Task MemtierBenchmarkClientExecutorExecutesExpectedCommands2ClientI
[Test]
public async Task MemtierBenchmarkClientExecutorExecutesExpectedCommands4ClientInstances()
{

this.SetMultipleServerInstances();

using (var executor = new TestMemtierBenchmarkClientExecutor(this.mockFixture.Dependencies, this.mockFixture.Parameters))
{
// 4 client instances running in-parallel to target the server.
// 4 client instances running in-parallel to target 1 server as the other server will sit idle because MaxClients = 4, If we Set MaxClients >= 8 both the servers will be engaged .
executor.Parameters[nameof(executor.ClientInstances)] = 4;
executor.Parameters[nameof(executor.MaxClients)] = 4;

List<string> expectedCommands = new List<string>()
{
// Make the benchmark toolset executable
$"sudo chmod +x \"{this.mockPackage.Path}/memtier_benchmark\"",

// Client instance #1
$"sudo bash -c \"numactl -C 1 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",
$"sudo bash -c \"numactl -C 2 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",

// Client instance #2
$"sudo bash -c \"numactl -C 1 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",
$"sudo bash -c \"numactl -C 2 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",

// Client instance #3
$"sudo bash -c \"numactl -C 1 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",
$"sudo bash -c \"numactl -C 2 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\"",

// Client instance #4
$"sudo bash -c \"numactl -C 1 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\""
$"sudo bash -c \"numactl -C 2 {this.mockPackage.Path}/memtier_benchmark --server 1.2.3.5 --port 6379 {executor.CommandLine}\""
};

this.mockFixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDirectory) =>
Expand Down Expand Up @@ -474,6 +518,7 @@ public async Task MemtierBenchmarkClientExecutorEmitsTheExpectedMetricsAggregate
}
}


private class TestMemtierBenchmarkClientExecutor : MemtierBenchmarkClientExecutor
{
public TestMemtierBenchmarkClientExecutor(IServiceCollection services, IDictionary<string, IConvertible> parameters = null)
Expand All @@ -488,5 +533,6 @@ public TestMemtierBenchmarkClientExecutor(IServiceCollection services, IDictiona
}

}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ public string RedisResourcesPackageName
}
}

/// <summary>
/// Parameter defines the maximum number of memtier processes.
/// </summary>
public int MaxClients
{
get
{
return this.Parameters.GetValue<int>(nameof(this.MaxClients), int.MaxValue);
}
}

/// <summary>
/// The benchmark target server (e.g. Redis, Memcached).
/// </summary>
Expand Down Expand Up @@ -338,7 +349,7 @@ protected override bool IsSupported()
{
return false;
}

}

private void CaptureMetrics(EventContext telemetryContext, CancellationToken cancellationToken)
Expand Down Expand Up @@ -443,7 +454,9 @@ private Task ExecuteWorkloadsAsync(IPAddress serverIPAddress, ServerState server
CpuInfo cpuInfo = this.SystemManagement.GetCpuInfoAsync(CancellationToken.None).GetAwaiter().GetResult();
int logicalProcessorCount = cpuInfo.LogicalProcessorCount;

for (int i = 0; i < serverState.Ports.Count(); i++)
int serverInstancesMax = this.MaxClients / this.ClientInstances;

for (int i = 0; i < Math.Min(serverInstancesMax, serverprocesscount); i++)
{
PortDescription portDescription = serverState.Ports.ElementAt(i);
int serverPort = portDescription.Port;
Expand Down Expand Up @@ -578,8 +591,8 @@ private string ParseCommand(string command)
@".*\/memtier_benchmark",
@"--port\s+\d+",
@"--key-prefix\s+\w+",
@"--key-prefix\s+\w+",
@"--print-percentiles\s+(?:\d{1,2}(?:\.\d+)?(?:,\d{1,2}(?:\.\d+)?)*)+",
@"--key-prefix\s+\w+",
@"--print-percentiles\s+(?:\d{1,2}(?:\.\d+)?(?:,\d{1,2}(?:\.\d+)?)*)+",
@"--cert\s+.*\.crt",
@"--key\s+.*\.key",
@"--cacert\s+.*\.crt",
Expand Down
Loading