aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnkit Kumar <ankit.kumar@samsung.com>2024-01-25 16:31:23 +0530
committerVincent Fu <vincent.fu@samsung.com>2024-01-25 08:46:15 -0500
commit0e14633ce541b7c5f29155a7edee208fb79311d0 (patch)
tree0a80689630ebd36cba70b761a5a587562842aa87
parent7f250f7514bacef1a3cea24a22ecce8bd30378bd (diff)
downloadfio-0e14633ce541b7c5f29155a7edee208fb79311d0.tar.gz
stat: log out both average and max over the window
Add option log_window_value alias of log_max_value which reports average, max or both the values. Retain backward compatibility by allowing =0 and =1 values to specify avg and max values respectively. There is no change to existing log formats while reporting only average or max values. Signed-off-by: Ankit Kumar <ankit.kumar@samsung.com> Link: https://lore.kernel.org/r/20240125110124.55137-2-ankit.kumar@samsung.com Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
-rw-r--r--client.c6
-rw-r--r--iolog.c74
-rw-r--r--iolog.h21
-rw-r--r--options.c34
-rw-r--r--server.c6
-rw-r--r--stat.c32
6 files changed, 128 insertions, 45 deletions
diff --git a/client.c b/client.c
index 699a2e5b9..4cb7dffed 100644
--- a/client.c
+++ b/client.c
@@ -1718,8 +1718,10 @@ static struct cmd_iolog_pdu *convert_iolog(struct fio_net_cmd *cmd,
s = (struct io_sample *)((char *)s + sizeof(struct io_u_plat_entry) * i);
s->time = le64_to_cpu(s->time);
- if (ret->log_type != IO_LOG_TYPE_HIST)
- s->data.val = le64_to_cpu(s->data.val);
+ if (ret->log_type != IO_LOG_TYPE_HIST) {
+ s->data.val.val0 = le64_to_cpu(s->data.val.val0);
+ s->data.val.val1 = le64_to_cpu(s->data.val.val1);
+ }
s->__ddir = __le32_to_cpu(s->__ddir);
s->bs = le64_to_cpu(s->bs);
s->priority = le16_to_cpu(s->priority);
diff --git a/iolog.c b/iolog.c
index 5213c60f1..b4c7a8f13 100644
--- a/iolog.c
+++ b/iolog.c
@@ -862,6 +862,8 @@ void setup_log(struct io_log **log, struct log_params *p,
l->log_ddir_mask = LOG_OFFSET_SAMPLE_BIT;
if (l->log_prio)
l->log_ddir_mask |= LOG_PRIO_SAMPLE_BIT;
+ if (l->td->o.log_max == IO_LOG_SAMPLE_BOTH)
+ l->log_ddir_mask |= LOG_AVG_MAX_SAMPLE_BIT;
INIT_FLIST_HEAD(&l->chunk_list);
@@ -988,7 +990,7 @@ static void flush_hist_samples(FILE *f, int hist_coarseness, void *samples,
void flush_samples(FILE *f, void *samples, uint64_t sample_size)
{
struct io_sample *s;
- int log_offset, log_prio;
+ int log_offset, log_prio, log_avg_max;
uint64_t i, nr_samples;
unsigned int prio_val;
const char *fmt;
@@ -999,17 +1001,32 @@ void flush_samples(FILE *f, void *samples, uint64_t sample_size)
s = __get_sample(samples, 0, 0);
log_offset = (s->__ddir & LOG_OFFSET_SAMPLE_BIT) != 0;
log_prio = (s->__ddir & LOG_PRIO_SAMPLE_BIT) != 0;
+ log_avg_max = (s->__ddir & LOG_AVG_MAX_SAMPLE_BIT) != 0;
if (log_offset) {
- if (log_prio)
- fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, %llu, 0x%04x\n";
- else
- fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, %llu, %u\n";
+ if (log_prio) {
+ if (log_avg_max)
+ fmt = "%" PRIu64 ", %" PRId64 ", %" PRId64 ", %u, %llu, %llu, 0x%04x\n";
+ else
+ fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, %llu, 0x%04x\n";
+ } else {
+ if (log_avg_max)
+ fmt = "%" PRIu64 ", %" PRId64 ", %" PRId64 ", %u, %llu, %llu, %u\n";
+ else
+ fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, %llu, %u\n";
+ }
} else {
- if (log_prio)
- fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, 0x%04x\n";
- else
- fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, %u\n";
+ if (log_prio) {
+ if (log_avg_max)
+ fmt = "%" PRIu64 ", %" PRId64 ", %" PRId64 ", %u, %llu, 0x%04x\n";
+ else
+ fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, 0x%04x\n";
+ } else {
+ if (log_avg_max)
+ fmt = "%" PRIu64 ", %" PRId64 ", %" PRId64 ", %u, %llu, %u\n";
+ else
+ fmt = "%" PRIu64 ", %" PRId64 ", %u, %llu, %u\n";
+ }
}
nr_samples = sample_size / __log_entry_sz(log_offset);
@@ -1023,20 +1040,37 @@ void flush_samples(FILE *f, void *samples, uint64_t sample_size)
prio_val = ioprio_value_is_class_rt(s->priority);
if (!log_offset) {
- fprintf(f, fmt,
- s->time,
- s->data.val,
- io_sample_ddir(s), (unsigned long long) s->bs,
- prio_val);
+ if (log_avg_max)
+ fprintf(f, fmt,
+ s->time,
+ s->data.val.val0,
+ s->data.val.val1,
+ io_sample_ddir(s), (unsigned long long) s->bs,
+ prio_val);
+ else
+ fprintf(f, fmt,
+ s->time,
+ s->data.val.val0,
+ io_sample_ddir(s), (unsigned long long) s->bs,
+ prio_val);
} else {
struct io_sample_offset *so = (void *) s;
- fprintf(f, fmt,
- s->time,
- s->data.val,
- io_sample_ddir(s), (unsigned long long) s->bs,
- (unsigned long long) so->offset,
- prio_val);
+ if (log_avg_max)
+ fprintf(f, fmt,
+ s->time,
+ s->data.val.val0,
+ s->data.val.val1,
+ io_sample_ddir(s), (unsigned long long) s->bs,
+ (unsigned long long) so->offset,
+ prio_val);
+ else
+ fprintf(f, fmt,
+ s->time,
+ s->data.val.val0,
+ io_sample_ddir(s), (unsigned long long) s->bs,
+ (unsigned long long) so->offset,
+ prio_val);
}
}
}
diff --git a/iolog.h b/iolog.h
index 62cbd1b02..26dd5cca8 100644
--- a/iolog.h
+++ b/iolog.h
@@ -26,13 +26,23 @@ struct io_hist {
struct flist_head list;
};
+enum {
+ IO_LOG_SAMPLE_AVG = 0,
+ IO_LOG_SAMPLE_MAX,
+ IO_LOG_SAMPLE_BOTH,
+};
+
+struct io_sample_value {
+ uint64_t val0;
+ uint64_t val1;
+};
union io_sample_data {
- uint64_t val;
+ struct io_sample_value val;
struct io_u_plat_entry *plat_entry;
};
-#define sample_val(value) ((union io_sample_data) { .val = value })
+#define sample_val(value) ((union io_sample_data) { .val.val0 = value })
#define sample_plat(plat) ((union io_sample_data) { .plat_entry = plat })
/*
@@ -154,8 +164,13 @@ struct io_log {
* If the bit following the upper bit is set, then we have the priority
*/
#define LOG_PRIO_SAMPLE_BIT 0x40000000U
+/*
+ * If the bit following prioity sample vit is set, we report both avg and max
+ */
+#define LOG_AVG_MAX_SAMPLE_BIT 0x20000000U
-#define LOG_SAMPLE_BITS (LOG_OFFSET_SAMPLE_BIT | LOG_PRIO_SAMPLE_BIT)
+#define LOG_SAMPLE_BITS (LOG_OFFSET_SAMPLE_BIT | LOG_PRIO_SAMPLE_BIT |\
+ LOG_AVG_MAX_SAMPLE_BIT)
#define io_sample_ddir(io) ((io)->__ddir & ~LOG_SAMPLE_BITS)
static inline void io_sample_set_ddir(struct io_log *log,
diff --git a/options.c b/options.c
index 53df03de9..1da4de781 100644
--- a/options.c
+++ b/options.c
@@ -4540,14 +4540,38 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.group = FIO_OPT_G_INVALID,
},
{
- .name = "log_max_value",
- .lname = "Log maximum instead of average",
- .type = FIO_OPT_BOOL,
+ .name = "log_window_value",
+ .alias = "log_max_value",
+ .lname = "Log maximum, average or both values",
+ .type = FIO_OPT_STR,
.off1 = offsetof(struct thread_options, log_max),
- .help = "Log max sample in a window instead of average",
- .def = "0",
+ .help = "Log max, average or both sample in a window",
+ .def = "avg",
.category = FIO_OPT_C_LOG,
.group = FIO_OPT_G_INVALID,
+ .posval = {
+ { .ival = "avg",
+ .oval = IO_LOG_SAMPLE_AVG,
+ .help = "Log average value over the window",
+ },
+ { .ival = "max",
+ .oval = IO_LOG_SAMPLE_MAX,
+ .help = "Log maximum value in the window",
+ },
+ { .ival = "both",
+ .oval = IO_LOG_SAMPLE_BOTH,
+ .help = "Log both average and maximum values over the window"
+ },
+ /* Compatibility with former boolean values */
+ { .ival = "0",
+ .oval = IO_LOG_SAMPLE_AVG,
+ .help = "Alias for 'avg'",
+ },
+ { .ival = "1",
+ .oval = IO_LOG_SAMPLE_MAX,
+ .help = "Alias for 'max'",
+ },
+ },
},
{
.name = "log_offset",
diff --git a/server.c b/server.c
index b9f0e2ac3..afaeb3482 100644
--- a/server.c
+++ b/server.c
@@ -2288,8 +2288,10 @@ int fio_send_iolog(struct thread_data *td, struct io_log *log, const char *name)
struct io_sample *s = get_sample(log, cur_log, i);
s->time = cpu_to_le64(s->time);
- if (log->log_type != IO_LOG_TYPE_HIST)
- s->data.val = cpu_to_le64(s->data.val);
+ if (log->log_type != IO_LOG_TYPE_HIST) {
+ s->data.val.val0 = cpu_to_le64(s->data.val.val0);
+ s->data.val.val1 = cpu_to_le64(s->data.val.val1);
+ }
s->__ddir = __cpu_to_le32(s->__ddir);
s->bs = cpu_to_le64(s->bs);
diff --git a/stat.c b/stat.c
index 7cf6bee19..11b586268 100644
--- a/stat.c
+++ b/stat.c
@@ -3149,7 +3149,7 @@ void reset_io_stats(struct thread_data *td)
}
static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
- unsigned long elapsed, bool log_max)
+ unsigned long elapsed, int log_max)
{
/*
* Note an entry in the log. Use the mean from the logged samples,
@@ -3159,10 +3159,16 @@ static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
if (iolog->avg_window[ddir].samples) {
union io_sample_data data;
- if (log_max)
- data.val = iolog->avg_window[ddir].max_val;
- else
- data.val = iolog->avg_window[ddir].mean.u.f + 0.50;
+ if (log_max == IO_LOG_SAMPLE_AVG) {
+ data.val.val0 = iolog->avg_window[ddir].mean.u.f + 0.50;
+ data.val.val1 = 0;
+ } else if (log_max == IO_LOG_SAMPLE_MAX) {
+ data.val.val0 = iolog->avg_window[ddir].max_val;
+ data.val.val1 = 0;
+ } else {
+ data.val.val0 = iolog->avg_window[ddir].mean.u.f + 0.50;
+ data.val.val1 = iolog->avg_window[ddir].max_val;
+ }
__add_log_sample(iolog, data, ddir, 0, elapsed, 0, 0);
}
@@ -3171,7 +3177,7 @@ static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
}
static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed,
- bool log_max)
+ int log_max)
{
enum fio_ddir ddir;
@@ -3205,7 +3211,7 @@ static unsigned long add_log_sample(struct thread_data *td,
* Add the sample. If the time period has passed, then
* add that entry to the log and clear.
*/
- add_stat_sample(&iolog->avg_window[ddir], data.val);
+ add_stat_sample(&iolog->avg_window[ddir], data.val.val0);
/*
* If period hasn't passed, adding the above sample is all we
@@ -3221,7 +3227,7 @@ static unsigned long add_log_sample(struct thread_data *td,
return diff;
}
- __add_stat_to_log(iolog, ddir, elapsed, td->o.log_max != 0);
+ __add_stat_to_log(iolog, ddir, elapsed, td->o.log_max);
iolog->avg_last[ddir] = elapsed - (elapsed % iolog->avg_msec);
@@ -3235,15 +3241,15 @@ void finalize_logs(struct thread_data *td, bool unit_logs)
elapsed = mtime_since_now(&td->epoch);
if (td->clat_log && unit_logs)
- _add_stat_to_log(td->clat_log, elapsed, td->o.log_max != 0);
+ _add_stat_to_log(td->clat_log, elapsed, td->o.log_max);
if (td->slat_log && unit_logs)
- _add_stat_to_log(td->slat_log, elapsed, td->o.log_max != 0);
+ _add_stat_to_log(td->slat_log, elapsed, td->o.log_max);
if (td->lat_log && unit_logs)
- _add_stat_to_log(td->lat_log, elapsed, td->o.log_max != 0);
+ _add_stat_to_log(td->lat_log, elapsed, td->o.log_max);
if (td->bw_log && (unit_logs == per_unit_log(td->bw_log)))
- _add_stat_to_log(td->bw_log, elapsed, td->o.log_max != 0);
+ _add_stat_to_log(td->bw_log, elapsed, td->o.log_max);
if (td->iops_log && (unit_logs == per_unit_log(td->iops_log)))
- _add_stat_to_log(td->iops_log, elapsed, td->o.log_max != 0);
+ _add_stat_to_log(td->iops_log, elapsed, td->o.log_max);
}
void add_agg_sample(union io_sample_data data, enum fio_ddir ddir,