@@ -34,8 +34,14 @@ auto main(int argc, char** argv) -> int {
34
34
auto cfg = std::get<cbdc::config::options>(cfg_or_err);
35
35
36
36
auto gen_id = std::stoull (args[2 ]);
37
- auto logger
38
- = std::make_shared<cbdc::logging::log >(cbdc::logging::log_level::info);
37
+ if (gen_id >= cfg.m_loadgen_count ) {
38
+ std::cerr << " Attempted to run more loadgens than configured"
39
+ << std::endl;
40
+ return -1 ;
41
+ }
42
+
43
+ auto logger = std::make_shared<cbdc::logging::log >(
44
+ cfg.m_loadgen_loglevels [gen_id]);
39
45
40
46
auto sha2_impl = SHA256AutoDetect ();
41
47
logger->info (" using sha2: " , sha2_impl);
@@ -115,6 +121,25 @@ auto main(int argc, char** argv) -> int {
115
121
logger->info (" Mint confirmed" );
116
122
}
117
123
124
+ size_t per_gen_send_limit = 0 ;
125
+ size_t per_gen_step_size = 0 ;
126
+ size_t per_gen_send_tgt = 0 ;
127
+ if (cfg.m_loadgen_tps_target != 0 ) {
128
+ per_gen_send_tgt = cfg.m_loadgen_tps_target / cfg.m_loadgen_count ;
129
+ per_gen_send_limit = cfg.m_loadgen_tps_initial / cfg.m_loadgen_count ;
130
+ size_t range = cfg.m_loadgen_tps_target - cfg.m_loadgen_tps_initial ;
131
+ size_t per_gen_range = range / cfg.m_loadgen_count ;
132
+ per_gen_step_size = std::max (
133
+ std::min (static_cast <size_t >(
134
+ per_gen_range * (cfg.m_loadgen_tps_step_size * .01 )),
135
+ per_gen_range),
136
+ size_t {1 });
137
+ }
138
+
139
+ if (cfg.m_loadgen_tps_step_time == 0 ) {
140
+ per_gen_send_limit = per_gen_send_tgt;
141
+ }
142
+
118
143
static constexpr auto lookup_timeout = std::chrono::milliseconds (5000 );
119
144
auto status_client = cbdc::locking_shard::rpc::status_client (
120
145
cfg.m_locking_shard_readonly_endpoints ,
@@ -161,7 +186,13 @@ auto main(int argc, char** argv) -> int {
161
186
162
187
constexpr auto send_amt = 5 ;
163
188
189
+ uint64_t send_gap{};
164
190
uint64_t gen_avg{};
191
+ auto ramp_timer_full
192
+ = std::chrono::nanoseconds (cfg.m_loadgen_tps_step_time * 1000000 );
193
+ auto ramp_timer = ramp_timer_full;
194
+ auto ramping
195
+ = ramp_timer.count () != 0 && per_gen_send_limit != per_gen_send_tgt;
165
196
auto gen_thread = std::thread ([&]() {
166
197
while (running) {
167
198
// Determine if we should attempt to send a double-spending
@@ -219,8 +250,51 @@ auto main(int argc, char** argv) -> int {
219
250
gen_avg = static_cast <uint64_t >(
220
251
(static_cast <double >(gen_t .count ()) * average_factor)
221
252
+ (static_cast <double >(gen_avg) * (1.0 - average_factor)));
253
+ if (ramping) {
254
+ if (gen_t >= ramp_timer) {
255
+ logger->debug (
256
+ " Ramp Timer Exhausted (gen_t). Resetting" );
257
+ ramp_timer = ramp_timer_full;
258
+ per_gen_send_limit
259
+ = std::min (per_gen_send_tgt,
260
+ per_gen_send_limit + per_gen_step_size);
261
+ logger->debug (" New Send Limit:" , per_gen_send_limit);
262
+ if (per_gen_send_limit == per_gen_send_tgt) {
263
+ ramping = false ;
264
+ logger->info (" Reached Target Throughput" );
265
+ }
266
+ } else {
267
+ ramp_timer -= gen_t ;
268
+ }
269
+ }
270
+ auto total_send_time
271
+ = std::chrono::nanoseconds (gen_avg * per_gen_send_limit);
272
+ if (total_send_time < std::chrono::seconds (1 )) {
273
+ send_gap
274
+ = (std::chrono::seconds (1 ) - total_send_time).count ()
275
+ / per_gen_send_limit;
276
+ logger->trace (" New send-gap:" , send_gap);
277
+ }
222
278
} else {
223
279
std::this_thread::sleep_for (std::chrono::nanoseconds (gen_avg));
280
+ if (ramping) {
281
+ auto avg = std::chrono::nanoseconds (gen_avg);
282
+ if (avg >= ramp_timer) {
283
+ logger->debug (" Ramp Timer Exhausted (dbl-spend "
284
+ " gen_avg). Resetting" );
285
+ ramp_timer = ramp_timer_full;
286
+ per_gen_send_limit
287
+ = std::min (per_gen_send_tgt,
288
+ per_gen_send_limit + per_gen_step_size);
289
+ logger->debug (" New Send Limit:" , per_gen_send_limit);
290
+ if (per_gen_send_limit == per_gen_send_tgt) {
291
+ ramping = false ;
292
+ logger->info (" Reached Target Throughput" );
293
+ }
294
+ } else {
295
+ ramp_timer -= avg;
296
+ }
297
+ }
224
298
}
225
299
226
300
// We couldn't send a double-spend or a newly generated valid
@@ -234,6 +308,23 @@ auto main(int argc, char** argv) -> int {
234
308
// instead.
235
309
static constexpr auto send_delay = std::chrono::seconds (1 );
236
310
std::this_thread::sleep_for (send_delay);
311
+ if (ramping) {
312
+ if (send_delay >= ramp_timer) {
313
+ logger->debug (
314
+ " Ramp Timer Exhausted (send_delay). Resetting" );
315
+ ramp_timer = ramp_timer_full;
316
+ per_gen_send_limit
317
+ = std::min (per_gen_send_tgt,
318
+ per_gen_send_limit + per_gen_step_size);
319
+ logger->debug (" New Send Limit:" , per_gen_send_limit);
320
+ if (per_gen_send_limit == per_gen_send_tgt) {
321
+ ramping = false ;
322
+ logger->info (" Reached Target Throughput" );
323
+ }
324
+ } else {
325
+ ramp_timer -= send_delay;
326
+ }
327
+ }
237
328
continue ;
238
329
}
239
330
@@ -280,6 +371,27 @@ auto main(int argc, char** argv) -> int {
280
371
logger->error (" Failure sending transaction to sentinel" );
281
372
wallet.confirm_inputs (tx.value ().m_inputs );
282
373
}
374
+
375
+ auto gap = std::chrono::nanoseconds (send_gap);
376
+ if (gap < std::chrono::seconds (1 )) {
377
+ std::this_thread::sleep_for (gap);
378
+ if (ramping) {
379
+ if (gap >= ramp_timer) {
380
+ logger->debug (" Ramp Timer Exhausted (gap). Resetting" );
381
+ ramp_timer = ramp_timer_full;
382
+ per_gen_send_limit
383
+ = std::min (per_gen_send_tgt,
384
+ per_gen_send_limit + per_gen_step_size);
385
+ logger->debug (" New Send Limit:" , per_gen_send_limit);
386
+ if (per_gen_send_limit == per_gen_send_tgt) {
387
+ ramping = false ;
388
+ logger->info (" Reached Target Throughput" );
389
+ }
390
+ } else {
391
+ ramp_timer -= gap;
392
+ }
393
+ }
394
+ }
283
395
}
284
396
});
285
397
0 commit comments