Skip to content

Commit da2a3a6

Browse files
Added Load Mode (With PoolingSessionSource) vs (Without PoolingSessionSource) (#484)
1 parent 30a4fa2 commit da2a3a6

File tree

5 files changed

+188
-18
lines changed

5 files changed

+188
-18
lines changed

src/Ydb.Sdk/test/Ydb.Sdk.Ado.Stress.Loader/Cli.cs

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ public static class Cli
3939
"SQL query to execute during stress test"
4040
);
4141

42-
public static readonly RootCommand RootCommand = new("YDB ADO.NET Stress Test Tank - Variable Load Generator")
42+
private static readonly Command StressLoadCommand = new(
43+
"cycle",
44+
"runs workload (read and write to table with sets RPS)"
45+
)
4346
{
4447
ConnectionString,
4548
PeakRps,
@@ -53,14 +56,30 @@ public static class Cli
5356
TestQuery
5457
};
5558

59+
private static readonly Command LoadCommand = new(
60+
"load",
61+
"Load Mode (With PoolingSessionSource) vs (Without PoolingSessionSource)")
62+
{
63+
TotalTestTimeSeconds,
64+
ConnectionString,
65+
SaFilePath,
66+
TestQuery
67+
};
68+
69+
public static readonly RootCommand RootCommand = new("YDB ADO.NET Stress Test Tank - Variable Load Generator")
70+
{
71+
StressLoadCommand,
72+
LoadCommand
73+
};
74+
5675
static Cli()
5776
{
58-
RootCommand.SetHandler(async config =>
77+
StressLoadCommand.SetHandler(async config =>
5978
{
60-
var stressLoader = new StressTestTank(config);
61-
await stressLoader.RunAsync();
79+
var stressLoader = new StressLoadTank(config);
80+
await stressLoader.Run();
6281
},
63-
new ConfigBinder(
82+
new StressConfigBinder(
6483
ConnectionString,
6584
PeakRps,
6685
MediumRps,
@@ -73,10 +92,23 @@ static Cli()
7392
TestQuery
7493
)
7594
);
95+
96+
LoadCommand.SetHandler(async config =>
97+
{
98+
var loader = new LoadTank(config);
99+
await loader.Run();
100+
},
101+
new LoadConfigBinder(
102+
ConnectionString,
103+
TotalTestTimeSeconds,
104+
SaFilePath,
105+
TestQuery
106+
)
107+
);
76108
}
77109
}
78110

79-
public class ConfigBinder(
111+
public class StressConfigBinder(
80112
Argument<string> connectionString,
81113
Option<int> peakRps,
82114
Option<int> mediumRps,
@@ -87,9 +119,9 @@ public class ConfigBinder(
87119
Option<int> totalTestTimeSeconds,
88120
Option<string?> saFilePath,
89121
Option<string> testQuery
90-
) : BinderBase<StressTestConfig>
122+
) : BinderBase<StressConfig>
91123
{
92-
protected override StressTestConfig GetBoundValue(BindingContext bindingContext) => new(
124+
protected override StressConfig GetBoundValue(BindingContext bindingContext) => new(
93125
ConnectionString: bindingContext.ParseResult.GetValueForArgument(connectionString),
94126
PeakRps: bindingContext.ParseResult.GetValueForOption(peakRps),
95127
MediumRps: bindingContext.ParseResult.GetValueForOption(mediumRps),
@@ -103,7 +135,22 @@ Option<string> testQuery
103135
);
104136
}
105137

106-
public record StressTestConfig(
138+
public class LoadConfigBinder(
139+
Argument<string> connectionString,
140+
Option<int> totalTestTimeSeconds,
141+
Option<string?> saFilePath,
142+
Option<string> testQuery
143+
) : BinderBase<LoadConfig>
144+
{
145+
protected override LoadConfig GetBoundValue(BindingContext bindingContext) => new(
146+
bindingContext.ParseResult.GetValueForArgument(connectionString),
147+
bindingContext.ParseResult.GetValueForOption(totalTestTimeSeconds),
148+
bindingContext.ParseResult.GetValueForOption(saFilePath),
149+
bindingContext.ParseResult.GetValueForOption(testQuery)!
150+
);
151+
}
152+
153+
public record StressConfig(
107154
string ConnectionString,
108155
int PeakRps,
109156
int MediumRps,
@@ -115,3 +162,10 @@ public record StressTestConfig(
115162
string? SaFilePath,
116163
string TestQuery
117164
);
165+
166+
public record LoadConfig(
167+
string ConnectionString,
168+
int TotalTestTimeSeconds,
169+
string? SaFilePath,
170+
string TestQuery
171+
);

src/Ydb.Sdk/test/Ydb.Sdk.Ado.Stress.Loader/LoadPattern.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Ydb.Sdk.Ado.Stress.Loader;
55

6-
public class LoadPattern(StressTestConfig config, ILogger logger)
6+
public class LoadPattern(StressConfig config, ILogger logger)
77
{
88
public async IAsyncEnumerable<int> GetLoadStepsAsync(
99
[EnumeratorCancellation] CancellationToken cancellationToken = default
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System.Data;
2+
using Microsoft.Extensions.Logging;
3+
using Ydb.Sdk.Yc;
4+
5+
namespace Ydb.Sdk.Ado.Stress.Loader;
6+
7+
public class LoadTank
8+
{
9+
private readonly ILogger<LoadTank> _logger;
10+
private readonly YdbConnectionStringBuilder _settings;
11+
private readonly LoadConfig _config;
12+
13+
public LoadTank(LoadConfig config)
14+
{
15+
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));
16+
17+
_logger = loggerFactory.CreateLogger<LoadTank>();
18+
_settings = new YdbConnectionStringBuilder(config.ConnectionString)
19+
{
20+
CredentialsProvider = config.SaFilePath != null
21+
? new ServiceAccountProvider(config.SaFilePath, loggerFactory)
22+
: new MetadataProvider(loggerFactory),
23+
ServerCertificates = YcCerts.GetYcServerCertificates()
24+
};
25+
_config = config;
26+
}
27+
28+
public async Task Run()
29+
{
30+
_logger.LogInformation(
31+
"""
32+
Starting YDB ADO.NET Stress Test Tank
33+
Configuration:
34+
Total Test Time: {TotalTime}s
35+
Test Query: {TestQuery}
36+
""",
37+
_config.TotalTestTimeSeconds,
38+
_config.TestQuery
39+
);
40+
41+
_logger.LogInformation("[{Now}] Starting shooting with PoolingSessionSource...", DateTime.Now);
42+
var ctsStep1 = new CancellationTokenSource();
43+
var workers = new List<Task>();
44+
ctsStep1.CancelAfter(_config.TotalTestTimeSeconds * 500);
45+
46+
for (var i = 0; i < _settings.MaxSessionPool; i++)
47+
{
48+
workers.Add(Task.Run(async () =>
49+
{
50+
while (!ctsStep1.IsCancellationRequested)
51+
{
52+
try
53+
{
54+
await using var ydbConnection = new YdbConnection(_settings);
55+
await ydbConnection.OpenAsync(ctsStep1.Token);
56+
await new YdbCommand(ydbConnection) { CommandText = _config.TestQuery }
57+
.ExecuteNonQueryAsync(ctsStep1.Token);
58+
}
59+
catch (Exception)
60+
{
61+
// ignored
62+
}
63+
}
64+
}, ctsStep1.Token));
65+
}
66+
67+
await Task.WhenAll(workers);
68+
workers.Clear();
69+
_logger.LogInformation("Phase 1 stopped shooting");
70+
await Task.Delay(10_000);
71+
72+
_logger.LogInformation("[{Now}] Starting shooting without PoolingSessionSource...", DateTime.Now);
73+
var ctsStep2 = new CancellationTokenSource();
74+
ctsStep2.CancelAfter(_config.TotalTestTimeSeconds * 500);
75+
for (var i = 0; i < _settings.MaxSessionPool; i++)
76+
{
77+
workers.Add(Task.Run(async () =>
78+
{
79+
await using var ydbConnection = new YdbConnection(_settings);
80+
81+
while (!ctsStep2.IsCancellationRequested)
82+
{
83+
try
84+
{
85+
if (ydbConnection.State != ConnectionState.Open)
86+
{
87+
await ydbConnection.OpenAsync(ctsStep2.Token);
88+
}
89+
90+
await new YdbCommand(ydbConnection) { CommandText = _config.TestQuery }
91+
.ExecuteNonQueryAsync(ctsStep2.Token);
92+
}
93+
catch (Exception)
94+
{
95+
// ignored
96+
}
97+
}
98+
}, ctsStep2.Token));
99+
}
100+
101+
await Task.WhenAll(workers);
102+
_logger.LogInformation("Phase 2 stopped shooting");
103+
}
104+
}

src/Ydb.Sdk/test/Ydb.Sdk.Ado.Stress.Loader/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Variable load generator for testing YDB ADO.NET driver performance with step-like pattern.
44

5-
## Description
5+
## Description Cycle Mode
66

77
The stress test "tank" generates cyclical load using a step-like pattern:
88

@@ -17,3 +17,13 @@ Peak RPS (1000) ─┐
1717
│ Medium Duration
1818
└─ (cycle repeats)
1919
```
20+
21+
## Description Load Mode
22+
23+
```
24+
Loading With PoolingSourceSession
25+
26+
sleep 10s
27+
28+
Loading Without PoolingSourceSession
29+
```

src/Ydb.Sdk/test/Ydb.Sdk.Ado.Stress.Loader/StressTestTank.cs renamed to src/Ydb.Sdk/test/Ydb.Sdk.Ado.Stress.Loader/StressLoadTank.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44

55
namespace Ydb.Sdk.Ado.Stress.Loader;
66

7-
public class StressTestTank
7+
public class StressLoadTank
88
{
9-
private readonly StressTestConfig _config;
10-
private readonly ILogger<StressTestTank> _logger;
9+
private readonly StressConfig _config;
10+
private readonly ILogger<StressLoadTank> _logger;
1111
private readonly YdbConnectionStringBuilder _settings;
1212

13-
public StressTestTank(StressTestConfig config)
13+
public StressLoadTank(StressConfig config)
1414
{
1515
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));
1616

1717
_config = config;
18-
_logger = loggerFactory.CreateLogger<StressTestTank>();
18+
_logger = loggerFactory.CreateLogger<StressLoadTank>();
1919
_settings = new YdbConnectionStringBuilder(config.ConnectionString)
2020
{
2121
LoggerFactory = loggerFactory,
@@ -28,7 +28,7 @@ public StressTestTank(StressTestConfig config)
2828
ValidateConfig();
2929
}
3030

31-
public async Task RunAsync()
31+
public async Task Run()
3232
{
3333
_logger.LogInformation(
3434
"""
@@ -98,9 +98,11 @@ private async Task StartWorkersForRpsAsync(int targetRps, CancellationToken canc
9898
{
9999
if (targetRps <= 0) return;
100100

101+
targetRps = targetRps / 10 + targetRps % 10;
102+
101103
await using var rateLimiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions
102104
{
103-
Window = TimeSpan.FromSeconds(1),
105+
Window = TimeSpan.FromMilliseconds(100),
104106
PermitLimit = targetRps,
105107
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
106108
QueueLimit = targetRps * 2

0 commit comments

Comments
 (0)