Skip to content

Commit efa4c61

Browse files
Merge pull request #91 from unnatisa/logrtt-feature
Add --log-rtt and --logrtt-entries-per-flow option to rr/crr tests.
2 parents 33515f5 + 3153455 commit efa4c61

File tree

9 files changed

+119
-1
lines changed

9 files changed

+119
-1
lines changed

check_all_options.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ void check_options_rr(struct options *opts, struct callbacks *cb)
8686
"Request size must be positive.");
8787
CHECK(cb, opts->response_size > 0,
8888
"Response size must be positive.");
89+
CHECK(cb, (opts->log_rtt == NULL || opts->logrtt_entries_per_flow > 0),
90+
"Log RTT entries per flow must be positive.");
8991
}
9092

9193
void check_options_stream(struct options *opts, struct callbacks *cb)

define_all_flags.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ struct flags_parser *add_flags_rr(struct flags_parser *fp)
9595
DEFINE_FLAG_PRINTER(fp, percentiles, percentiles_print);
9696
DEFINE_FLAG(fp, int, test_length, 10, 'l', "Test length, >0 seconds, <0 transactions");
9797
DEFINE_FLAG(fp, int, buffer_size, 65536, 'B', "Number of bytes that each read()/send() can transfer at once");
98-
DEFINE_FLAG(fp, int, mark, 0, 0, "SO_MARK value; use as 32-bit unsigned");
98+
DEFINE_FLAG(fp, const char *, log_rtt, NULL, 0, "Logs per transaction rtt to txt/csv file");
99+
DEFINE_FLAG_HAS_OPTIONAL_ARGUMENT(fp, log_rtt);
100+
DEFINE_FLAG_PARSER(fp, log_rtt, parse_log_rtt);
101+
DEFINE_FLAG(fp, int, logrtt_entries_per_flow, 10000, 0, "Number of RTT entries to log per flow. Logging stops when this limit is reached.");
102+
DEFINE_FLAG(fp, int, mark, 0, 0, "SO_MARK value; use as 32-bit unsigned");
99103

100104
/* Return the updated fp */
101105
return (fp);

flow.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ struct flow {
5151
/* TCP RX zerocopy state. */
5252
void *f_rx_zerocopy_buffer;
5353
size_t f_rx_zerocopy_buffer_sz;
54+
55+
long rtt_log_count;
5456
};
5557

5658
int flow_fd(const struct flow *f)
@@ -147,6 +149,16 @@ void flow_init_rx_zerocopy(struct flow *f, int buffer_size, struct callbacks *cb
147149
f->f_rx_zerocopy_buffer_sz = buffer_size;
148150
}
149151

152+
long flow_rtt_log_count(const struct flow *f)
153+
{
154+
return f->rtt_log_count;
155+
}
156+
157+
void flow_increment_rtt_log_count(struct flow *f)
158+
{
159+
f->rtt_log_count++;
160+
}
161+
150162
struct flow *flow_create(const struct flow_create_args *args)
151163
{
152164
struct thread *t = args->thread;

flow.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ struct flow; /* note: struct is defined opaquely within flow.c */
2727
struct neper_stat;
2828
struct thread;
2929

30+
struct rtt_log {
31+
double rtt;
32+
int thread_id;
33+
int flow_id;
34+
struct timespec timestamp;
35+
};
36+
3037
typedef void (*flow_handler)(struct flow *, uint32_t);
3138

3239
/* Simple accessors. */
@@ -57,6 +64,8 @@ struct flow_create_args {
5764
};
5865

5966
struct flow *flow_create(const struct flow_create_args *);
67+
long flow_rtt_log_count(const struct flow *f);
68+
void flow_increment_rtt_log_count(struct flow *f);
6069
void flow_delete(struct flow *);
6170
/* Adds duration to f's next event time. */
6271
void flow_update_next_event(struct flow *f, uint64_t duration);

lib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ struct options {
131131

132132
/* tcp_crr */
133133
bool nostats;
134+
135+
/* rr */
136+
const char *log_rtt;
137+
int logrtt_entries_per_flow;
134138
};
135139

136140
#ifdef __cplusplus

parse.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ void parse_all_samples(const char *arg, void *out, struct callbacks *cb)
2828
*(const char **)out = "samples.csv";
2929
}
3030

31+
void parse_log_rtt(const char *arg, void *out, struct callbacks *cb)
32+
{
33+
if (arg)
34+
*(const char **)out = arg;
35+
else
36+
*(const char **)out = "rtt_samples.txt";
37+
}
38+
3139
static long long parse_rate(const char *str, struct callbacks *cb)
3240
{
3341
const struct rate_conversion *conv;

parse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define THIRD_PARTY_NEPER_PARSE_H
1919

2020
void parse_all_samples(const char *arg, void *out, struct callbacks *cb);
21+
void parse_log_rtt(const char *arg, void *out, struct callbacks *cb);
2122
void parse_max_pacing_rate(const char *arg, void *out, struct callbacks *cb);
2223
void parse_unit(const char *arg, void *out, struct callbacks *);
2324
void parse_duration(const char *arg, void *out, struct callbacks *cb);

rr.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@
2424
* as sending a message, opening a socket connection, or gathering statistics.
2525
*/
2626

27+
#include <stdio.h>
28+
#include <string.h>
2729
#include "coef.h"
2830
#include "common.h"
2931
#include "countdown_cond.h"
3032
#include "flow.h"
3133
#include "histo.h"
34+
#include "logging.h"
3235
#include "percentiles.h"
3336
#include "print.h"
3437
#include "rr.h"
@@ -202,6 +205,15 @@ static void rr_state_init(struct thread *t, int fd,
202205
};
203206

204207
flow_create(&args);
208+
209+
if (t->opts->client && t->opts->log_rtt && t->rtt_logs == NULL) {
210+
t->rtt_log_capacity = (long)t->flow_limit *
211+
t->opts->logrtt_entries_per_flow;
212+
if (t->rtt_log_capacity > 0) {
213+
t->rtt_logs = calloc_or_die(
214+
t->rtt_log_capacity, sizeof(struct rtt_log), t->cb);
215+
}
216+
}
205217
}
206218

207219
/*
@@ -327,6 +339,19 @@ static bool rr_do_compl(struct flow *f,
327339
struct neper_histo *histo = stat->histo(stat);
328340
neper_histo_event(histo, elapsed);
329341

342+
if (t->opts->client && t->rtt_logs) {
343+
long count = flow_rtt_log_count(f);
344+
if (count < t->opts->logrtt_entries_per_flow) {
345+
long offset = flow_id(f) * t->opts->logrtt_entries_per_flow;
346+
struct rtt_log *log = &t->rtt_logs[offset + count];
347+
log->rtt = elapsed;
348+
log->thread_id = t->index;
349+
log->flow_id = flow_id(f);
350+
log->timestamp = *now;
351+
flow_increment_rtt_log_count(f);
352+
}
353+
}
354+
330355
if (t->data_pending) {
331356
/* data vs time mode, last rr? */
332357
if (!countdown_cond_commit(t->data_pending)) {
@@ -497,6 +522,54 @@ fn_add(struct neper_stat *stat, void *ptr)
497522
return 0;
498523
}
499524

525+
static void rr_log_rtt(struct thread *tinfo, struct callbacks *cb,
526+
int num_transactions)
527+
{
528+
const char *sep = " ";
529+
const char *ext = strrchr(tinfo[0].opts->log_rtt, '.');
530+
if (ext && !strcmp(ext, ".csv"))
531+
sep = ",";
532+
533+
FILE *rtt_log_file = fopen(tinfo[0].opts->log_rtt, "w");
534+
if (!rtt_log_file)
535+
PLOG_FATAL(cb, "fopen %s", tinfo[0].opts->log_rtt);
536+
537+
fprintf(rtt_log_file, "%15s%s%10s%s%10s%s%12s\n", "timestamp", sep, "thread_id", sep, "flow_id", sep, "rtt");
538+
539+
long transactions_logged = 0;
540+
const struct timespec *start_time = tinfo[0].time_start;
541+
542+
for (int i = 0; i < tinfo[0].opts->num_threads; i++) {
543+
struct thread *t = &tinfo[i];
544+
if (!t->rtt_logs)
545+
continue;
546+
for (int j = 0; j < t->flow_count; j++) {
547+
struct flow *f = t->flows[j];
548+
if (!f)
549+
continue;
550+
transactions_logged += flow_rtt_log_count(f);
551+
long offset = flow_id(f) * t->opts->logrtt_entries_per_flow;
552+
for (long k = 0; k < flow_rtt_log_count(f); k++) {
553+
struct rtt_log *log = &t->rtt_logs[offset + k];
554+
double elapsed = seconds_between(start_time, &log->timestamp);
555+
fprintf(rtt_log_file, "%15.9f%s%10d%s%10d%s%12.9f\n",
556+
elapsed, sep, log->thread_id, sep,
557+
log->flow_id, sep, log->rtt);
558+
}
559+
}
560+
free(t->rtt_logs);
561+
t->rtt_logs = NULL;
562+
}
563+
fclose(rtt_log_file);
564+
PRINT(cb, "rtt_transactions_logged", "%ld", transactions_logged);
565+
566+
if (transactions_logged < num_transactions) {
567+
LOG_INFO(cb,
568+
"rtt_transactions_logged (%ld) < num_transactions (%d)",
569+
transactions_logged, num_transactions);
570+
}
571+
}
572+
500573
int rr_report_stats(struct thread *tinfo)
501574
{
502575
const struct options *opts = tinfo[0].opts;
@@ -511,6 +584,9 @@ int rr_report_stats(struct thread *tinfo)
511584
int num_events = thread_stats_events(tinfo);
512585
PRINT(cb, "num_transactions", "%d", num_events);
513586

587+
if (opts->client && tinfo[0].opts->log_rtt)
588+
rr_log_rtt(tinfo, cb, num_events);
589+
514590
struct neper_histo *sum = neper_histo_new(tinfo, DEFAULT_K_BITS);
515591
for (i = 0; i < opts->num_threads; i++)
516592
tinfo[i].stats->sumforeach(tinfo[i].stats, fn_add, sum);

thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ struct thread {
134134
int64_t rounding_ns; /* used to round to millisecond granularity */
135135
/* The duration between sends on a thread when using noburst. */
136136
int64_t gap_ns;
137+
struct rtt_log *rtt_logs;
138+
long rtt_log_capacity;
137139
};
138140

139141
int thread_stats_events(const struct thread *);

0 commit comments

Comments
 (0)