diff --git a/apps/EchoClient.cpp b/apps/EchoClient.cpp index 1a4773489cec3bc20baf992ffb19abc4b12970e2..a3a7a6ea449a4e29bac3c769d169a68c23267213 100644 --- a/apps/EchoClient.cpp +++ b/apps/EchoClient.cpp @@ -18,7 +18,8 @@ #include <cstring> // for memcmp #include <iomanip> #include <iostream> // for operator<<, basic_ostream, endl -#include <string> // for allocator, string, char_traits +#include <ratio> +#include <string> #include <thread> #include <utility> @@ -69,6 +70,8 @@ size_t size = SIZE; size_t server_backlog = SERVER_BACKLOG; bool linked_futures; bool histogram = false; +static ssize_t maxLowLoadClients = -1; +static std::chrono::milliseconds loadSwitchPeriod(1000); std::atomic<bool> terminate = false; @@ -225,6 +228,24 @@ class Client { } } + [[nodiscard]] auto shouldYield() const -> bool { + if (maxLowLoadClients < 0) { + return false; + } + + if (id < static_cast<size_t>(maxLowLoadClients)) { + return false; + } + + auto now = std::chrono::steady_clock::now(); + auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now); + auto ms_since_epoch = now_ms.time_since_epoch(); + auto ms_since_epoch_duration = + std::chrono::duration_cast<std::chrono::milliseconds>(ms_since_epoch); + uint64_t periodNum = ms_since_epoch_duration / loadSwitchPeriod; + return periodNum % 2; + } + public: template <bool collectTimeStamps = false> void run() { @@ -237,6 +258,11 @@ class Client { startSem.acquire(); while (iteration < iterations && !terminate.load(std::memory_order_relaxed)) { + if (shouldYield()) { + emper::yield(); + continue; + } + SendFuture sendFuture(sock, outBuf, size, MSG_NOSIGNAL); RecvFuture recvFuture(sock, inBuf, size, MSG_WAITALL); @@ -361,8 +387,10 @@ static void printUsage(char* name) { std::cerr << "Usage: " << name << "[-h] [-p <port>] [-c <clients>] [-a <address>] [-s <size>] [-b <server backlog>]" - " [-f <output-file>] [-i <iterations> | -t <execution time in sec>] [--linked-futures]" - << std::endl; + << std::endl + << "[-f <output-file>] [-i <iterations> | -t <execution time in sec>] [--linked-futures]" + << std::endl + << "[--max-low-load-clients <num>] [--load-switch-period-ms <num>]" << std::endl; } auto main(int argc, char* argv[]) -> int { @@ -446,6 +474,25 @@ auto main(int argc, char* argv[]) -> int { } } + char* max_low_load_clients = getOption(argc, argv, "--max-low-load-clients"); + if (max_low_load_clients) { + maxLowLoadClients = std::stoi(max_low_load_clients); + if (static_cast<size_t>(maxLowLoadClients) >= nclients) { + DIE_MSG("--max-low-load-clients " << maxLowLoadClients + << " must be smaller than the total number of clients " + << nclients); + } + } + + char* load_switch_period_ms_string = getOption(argc, argv, "--load-switch-period-ms"); + if (load_switch_period_ms_string) { + if (!max_low_load_clients) { + DIE_MSG("Can't use --load-switch-period-ms without --max-low-load-clients"); + } + int load_switch_period_ms = std::stoi(load_switch_period_ms_string); + loadSwitchPeriod = std::chrono::milliseconds(load_switch_period_ms); + } + int err = getaddrinfo(host.c_str(), port.c_str(), nullptr, &server); if (err) { if (err == EAI_SYSTEM) {