numam/util/memloadgen.cc

235 lines
5.8 KiB
C++
Raw Normal View History

2022-11-11 21:11:50 +00:00
#include <sys/endian.h>
2023-03-05 15:48:54 +00:00
#include <sys/select.h>
2023-03-05 14:58:06 +00:00
#include <sys/signal.h>
2022-06-22 15:40:48 +00:00
#include "gen.hh"
2023-03-05 14:58:06 +00:00
#include <array>
#include <atomic>
#include <cstdlib>
2022-11-01 10:01:23 +00:00
#include <cstring>
2022-11-16 07:44:43 +00:00
#include <list>
2022-11-01 10:01:23 +00:00
#include <iostream>
#include <fstream>
2022-02-21 13:41:40 +00:00
#include "ntr.h"
2022-11-01 10:01:23 +00:00
#include "nms.h"
2022-02-21 13:41:40 +00:00
#include <getopt.h>
2023-03-05 14:58:06 +00:00
#include <pthread.h>
2022-02-21 13:41:40 +00:00
#include <unistd.h>
2022-06-22 15:40:48 +00:00
#include <topo.h>
2022-02-21 13:41:40 +00:00
static void
usage()
{
fprintf(stdout,
"Usage:\n"
" -v: verbose mode\n"
2022-11-11 21:11:50 +00:00
" -b: buffer size\n"
" -q: bytes per second\n"
2022-11-01 10:01:23 +00:00
" -d: destination domain index\n"
" -s: worker threads cpu list\n"
2022-11-11 21:11:50 +00:00
" -S: enable shared buffer\n"
2022-11-01 10:01:23 +00:00
" -t: time to run\n"
2022-11-11 21:11:50 +00:00
" -T: transaction size\n"
" -i: inter arrival time distribution\n"
2022-11-16 07:44:43 +00:00
" -o: output file path\n"
" -H: history size for pct adjustment\n"
2023-03-05 14:15:13 +00:00
" -M: print this string when threads are ready to run\n");
2022-02-21 13:41:40 +00:00
fflush(stdout);
}
2022-11-01 10:01:23 +00:00
2023-03-05 15:48:54 +00:00
static char output_file[256] = "memloadgen_samples.txt";
2023-03-05 14:58:06 +00:00
2022-02-21 13:41:40 +00:00
int main(int argc, char * argv[])
{
ntr_init();
ntr_set_level(NTR_DEP_USER1, NTR_LEVEL_WARNING);
2022-11-16 07:44:43 +00:00
size_t arr_sz = 64 * 1024 * 1024;
2022-11-01 10:01:23 +00:00
uint32_t time = -1;
2022-11-11 21:11:50 +00:00
uint64_t bps = 0;
2022-11-16 07:44:43 +00:00
uint64_t transaction_size = arr_sz;
2022-06-22 15:40:48 +00:00
cpuset_t threads;
2023-03-05 14:15:13 +00:00
char magic[256] = {0};
2022-11-01 10:01:23 +00:00
CPU_ZERO(&threads);
CPU_SET(0, &threads);
2022-11-11 21:11:50 +00:00
char ia_dist[32] = "fixed";
2023-03-05 14:58:06 +00:00
int history_sz = 5;
2022-11-16 07:44:43 +00:00
std::list<uint64_t> history;
2022-11-01 10:01:23 +00:00
2022-06-22 15:40:48 +00:00
int shared_buffer = 0;
2023-03-05 15:48:54 +00:00
int rate_ctrl = 0;
2022-06-22 15:40:48 +00:00
cpuset_t domain_mask;
2022-11-01 10:01:23 +00:00
CPU_ZERO(&domain_mask);
CPU_SET(0, &domain_mask);
2022-02-21 13:41:40 +00:00
{
int c;
// parse arguments
2023-03-05 15:48:54 +00:00
while ((c = getopt(argc, argv, "vhb:d:s:So:T:t:q:i:H:M:")) != -1) {
2022-02-21 13:41:40 +00:00
switch (c) {
case 'v':
2022-11-01 10:01:23 +00:00
ntr_set_level(NTR_DEP_USER1, ntr_get_level(NTR_DEP_USER1) + 1);
2022-02-21 13:41:40 +00:00
break;
case 'h':
usage();
exit(0);
case 'b':
2022-06-22 15:40:48 +00:00
arr_sz = strtoull(optarg, nullptr, 10);
break;
2022-11-01 10:01:23 +00:00
case 'd':
2022-06-22 15:40:48 +00:00
cpulist_to_cpuset(optarg, &domain_mask);
2022-02-21 13:41:40 +00:00
break;
2022-11-01 10:01:23 +00:00
case 's':
2022-06-22 15:40:48 +00:00
cpulist_to_cpuset(optarg, &threads);
break;
case 'S':
shared_buffer = 1;
2022-02-21 13:41:40 +00:00
break;
2022-11-01 10:01:23 +00:00
case 'o':
strncpy(output_file, optarg, 256);
break;
case 't':
2022-11-11 21:11:50 +00:00
time = strtoul(optarg, nullptr, 10);
break;
case 'T':
transaction_size = strtoul(optarg, nullptr, 10);
break;
case 'q':
bps = (uint64_t)strtoull(optarg, nullptr, 10);
break;
case 'i':
strncpy(ia_dist, optarg, sizeof(ia_dist));
2022-11-01 10:27:34 +00:00
break;
2022-11-16 07:44:43 +00:00
case 'H':
history_sz = strtol(optarg, nullptr, 10);
break;
2023-03-05 14:15:13 +00:00
case 'M':
strncpy(magic, optarg, sizeof(magic));
break;
2022-02-21 13:41:40 +00:00
default:
usage();
exit(0);
}
}
}
2022-11-11 21:11:50 +00:00
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "Configruation:\n"
" buffer size: %ld\n"
" num threads: %d\n"
" target domain: %ld\n"
" bytes per second: %lu\n"
" interarrival distribution: %s\n"
" shared buffer: %d\n"
" transaction time: %lu\n"
2022-11-16 07:44:43 +00:00
" runtime: %d\n"
" history: %d\n"
2023-03-05 14:58:06 +00:00
" magic: %s\n",
2022-11-16 07:44:43 +00:00
arr_sz, CPU_COUNT(&threads),
CPU_FFS(&domain_mask) - 1, bps,
2023-03-05 15:48:54 +00:00
ia_dist, shared_buffer,
2023-03-05 14:58:06 +00:00
transaction_size,time, history_sz, magic);
2022-02-21 13:41:40 +00:00
2022-06-22 15:40:48 +00:00
// init topo
2022-11-01 10:01:23 +00:00
if (topo_init(ntr_get_level(NTR_DEP_USER1) != NTR_LEVEL_DEFAULT)) {
2022-06-22 15:40:48 +00:00
fprintf(stderr, "libtopo init failed!\n");
2022-02-21 13:41:40 +00:00
exit(1);
}
2022-11-01 10:01:23 +00:00
// init
if (nms_init(ntr_get_level(NTR_DEP_USER1) != NTR_LEVEL_DEFAULT)) {
fprintf(stderr, "libnms init failed!\n");
exit(1);
}
2023-03-05 15:48:54 +00:00
2022-02-21 13:41:40 +00:00
bool success = false;
2022-06-22 15:40:48 +00:00
memload_generator::memload_generator_options opts;
2022-11-11 21:11:50 +00:00
opts.buffer_size = arr_sz;
2022-11-16 07:44:43 +00:00
opts.trans_per_second = bps / transaction_size;
2022-06-22 15:40:48 +00:00
opts.shared_buffer = shared_buffer;
2022-11-11 21:11:50 +00:00
opts.transaction_size = transaction_size;
2022-11-01 10:01:23 +00:00
opts.verbose = ntr_get_level(NTR_DEP_USER1) != NTR_LEVEL_DEFAULT;
2022-11-11 21:11:50 +00:00
strncpy(opts.ia_dist, ia_dist, sizeof(opts.ia_dist));
2022-11-01 10:01:23 +00:00
std::ofstream ofile;
ofile.open(output_file, std::ios::out | std::ios::trunc);
2022-02-21 13:41:40 +00:00
2022-06-22 15:40:48 +00:00
auto mgen = new memload_generator(&threads, &domain_mask, &opts, &success);
2023-03-05 14:15:13 +00:00
if (strlen(magic) > 0) {
fprintf(stdout, "%s\n", magic);
fflush(stdout);
}
2022-11-01 10:01:23 +00:00
if (!mgen->start()) {
fprintf(stderr, "failed to start memloadgen!\n");
exit(1);
2022-02-21 13:41:40 +00:00
}
2023-03-05 15:48:54 +00:00
struct timeval stval;
stval.tv_sec = 0;
stval.tv_usec = 0;
char pct_line[64] = {0};
2022-11-01 10:01:23 +00:00
uint64_t prev_ts = topo_uptime_ns();
uint64_t prev_trans = mgen->get_transactions();
uint32_t cur_time = 0;
while(cur_time < time) {
usleep(S2US);
uint64_t cur_ts = topo_uptime_ns();
uint64_t trans = mgen->get_transactions();
2022-11-11 21:11:50 +00:00
uint64_t bps = (uint64_t)((double)((trans - prev_trans) * transaction_size) / ((double)(cur_ts - prev_ts) / (double)S2NS));
2022-11-16 07:44:43 +00:00
2023-03-05 14:59:42 +00:00
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "%ldB,%ldM\n", bps, bps / 1024 / 1024);
2023-03-17 20:13:05 +00:00
ofile << "s," << cur_time << "," << bps << std::endl;
ofile.flush();
2022-11-16 07:44:43 +00:00
2022-11-01 10:01:23 +00:00
prev_ts = cur_ts;
prev_trans = trans;
cur_time++;
2022-11-16 07:44:43 +00:00
2023-03-05 15:48:54 +00:00
if (rate_ctrl == 0) {
// keep history
history.emplace_back(bps);
if ((int)history.size() > history_sz) {
history.pop_front();
}
2022-11-16 07:44:43 +00:00
2023-03-05 15:48:54 +00:00
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(STDIN_FILENO, &fdset);
int ret = select(1, &fdset, NULL, NULL, &stval);
if (ret < 0) {
if (errno != EINTR) {
fprintf(stderr, "select() failed with %d\n", errno);
exit(1);
}
} else if (ret > 0) {
if (FD_ISSET(STDIN_FILENO, &fdset)) {
ret = read(STDIN_FILENO, pct_line, sizeof(pct_line) - 1);
if (ret < 0) {
fprintf(stderr, "read() failed with %d\n", errno);
exit(1);
}
unsigned int pct = strtoul(pct_line, NULL, 10);
2023-03-05 14:58:06 +00:00
uint64_t sum = 0;
size_t sz = history.size();
while (history.size() > 0) {
sum += history.front();
history.pop_front();
}
uint64_t newbps = ((sum / sz) * (double)pct / 100.0);
mgen->set_transactions(newbps / transaction_size);
2023-03-05 15:48:54 +00:00
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "adjusted target bps to %u%% = %ldB ~= %ldM\n", pct, newbps, newbps / 1024 / 1024);
2023-03-17 20:13:05 +00:00
ofile << "p," << cur_time << "," << pct << std::endl;
ofile.flush();
2023-03-05 15:48:54 +00:00
rate_ctrl = 1;
2023-03-05 14:58:06 +00:00
}
2023-03-05 15:48:54 +00:00
}
2022-11-16 07:44:43 +00:00
}
2022-11-01 10:01:23 +00:00
}
mgen->stop();
2022-06-22 15:40:48 +00:00
delete mgen;
2022-11-01 10:01:23 +00:00
ofile.close();
2022-06-22 15:40:48 +00:00
2022-02-21 13:41:40 +00:00
return 0;
}