From ad705bcb7e79a7cdb9891db17b4c40b13b6c30c3 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Mon, 8 Apr 2013 15:05:25 -0700 Subject: [PATCH] implement 'unit_base' option to select between KB and Kbit et. al. With network testing, it's often desirable to measure in terms of kilobits/megabits rather than kilobytes/megabytes. This adds an option named 'unit_base' which can be set to either '1' or '8', where '1' means represent in terms of bits and '8' means to represent rate in terms of bytes. Signed-off-by: Steven Noonan Signed-off-by: Jens Axboe --- client.c | 3 +++ engines/net.c | 2 +- eta.c | 3 ++- fio.h | 1 + init.c | 7 +++++++ ioengine.h | 1 + options.c | 28 ++++++++++++++++++++++++++++ server.c | 2 ++ stat.c | 15 +++++++++++---- stat.h | 3 +++ 10 files changed, 59 insertions(+), 6 deletions(-) diff --git a/client.c b/client.c index 0dc620dc..7915268f 100644 --- a/client.c +++ b/client.c @@ -651,6 +651,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) dst->total_err_count = le64_to_cpu(src->total_err_count); dst->first_error = le32_to_cpu(src->first_error); dst->kb_base = le32_to_cpu(src->kb_base); + dst->unit_base = le32_to_cpu(src->unit_base); } static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src) @@ -667,6 +668,7 @@ static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src) } dst->kb_base = le32_to_cpu(src->kb_base); + dst->unit_base = le32_to_cpu(src->unit_base); dst->groupid = le32_to_cpu(src->groupid); dst->unified_rw_rep = le32_to_cpu(src->unified_rw_rep); } @@ -774,6 +776,7 @@ static void convert_jobs_eta(struct jobs_eta *je) je->elapsed_sec = le64_to_cpu(je->elapsed_sec); je->eta_sec = le64_to_cpu(je->eta_sec); je->is_pow2 = le32_to_cpu(je->is_pow2); + je->unit_base = le32_to_cpu(je->unit_base); } static void sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je) diff --git a/engines/net.c b/engines/net.c index 624ff158..31f71510 100644 --- a/engines/net.c +++ b/engines/net.c @@ -970,7 +970,7 @@ static struct ioengine_ops ioengine_rw = { .options = options, .option_struct_size = sizeof(struct netio_options), .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR | - FIO_PIPEIO, + FIO_PIPEIO | FIO_BIT_BASED, }; static int str_hostname_cb(void *data, const char *input) diff --git a/eta.c b/eta.c index e08b5f79..50d229c4 100644 --- a/eta.c +++ b/eta.c @@ -319,6 +319,7 @@ int calc_thread_status(struct jobs_eta *je, int force) unified_rw_rep += td->o.unified_rw_rep; if (is_power_of_2(td->o.kb_base)) je->is_pow2 = 1; + je->unit_base = td->o.unit_base; if (td->o.bw_avg_time < bw_avg_time) bw_avg_time = td->o.bw_avg_time; if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING @@ -474,7 +475,7 @@ void display_thread_status(struct jobs_eta *je) for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) { rate_str[ddir] = num2str(je->rate[ddir], 5, - 1024, je->is_pow2, 8); + 1024, je->is_pow2, je->unit_base); iops_str[ddir] = num2str(je->iops[ddir], 4, 1, 0, 0); } diff --git a/fio.h b/fio.h index cc439767..e74bdb3c 100644 --- a/fio.h +++ b/fio.h @@ -108,6 +108,7 @@ struct thread_options { enum td_ddir td_ddir; unsigned int rw_seq; unsigned int kb_base; + unsigned int unit_base; unsigned int ddir_seq_nr; long ddir_seq_add; unsigned int iodepth; diff --git a/init.c b/init.c index 92b3e5b2..44c74e31 100644 --- a/init.c +++ b/init.c @@ -560,6 +560,13 @@ static int fixup_options(struct thread_data *td) } } + if (!o->unit_base) { + if (td->io_ops->flags & FIO_BIT_BASED) + o->unit_base = 1; + else + o->unit_base = 8; + } + #ifndef CONFIG_FDATASYNC if (o->fdatasync_blocks) { log_info("fio: this platform does not support fdatasync()" diff --git a/ioengine.h b/ioengine.h index 7299636d..d15d15ee 100644 --- a/ioengine.h +++ b/ioengine.h @@ -153,6 +153,7 @@ enum fio_ioengine_flags { FIO_PIPEIO = 1 << 7, /* input/output no seekable */ FIO_BARRIER = 1 << 8, /* engine supports barriers */ FIO_MEMALIGN = 1 << 9, /* engine wants aligned memory */ + FIO_BIT_BASED = 1 << 10, /* engine uses a bit base (e.g. uses Kbit as opposed to KB) */ }; /* diff --git a/options.c b/options.c index bca217f6..66099b58 100644 --- a/options.c +++ b/options.c @@ -1100,6 +1100,25 @@ static int kb_base_verify(struct fio_option *o, void *data) return 0; } +static int unit_base_verify(struct fio_option *o, void *data) +{ + struct thread_data *td = data; + + /* 0 = default, pick based on engine + * 1 = use bits + * 8 = use bytes + */ + if (td->o.unit_base != 0 && + td->o.unit_base != 1 && + td->o.unit_base != 8) { + log_err("fio: unit_base set to nonsensical value: %u\n", + td->o.unit_base); + return 1; + } + + return 0; +} + /* * Map of job/command line options */ @@ -1148,6 +1167,15 @@ static struct fio_option options[FIO_MAX_OPTS] = { .def = "1024", .help = "How many bytes per KB for reporting (1000 or 1024)", }, + { + .name = "unit_base", + .type = FIO_OPT_INT, + .off1 = td_var_offset(unit_base), + .verify = unit_base_verify, + .prio = 1, + .def = "0", + .help = "Bit multiple of result summary data (8 for byte, 1 for bit)", + }, { .name = "lockfile", .type = FIO_OPT_STR, diff --git a/server.c b/server.c index d4676dda..f239d432 100644 --- a/server.c +++ b/server.c @@ -648,6 +648,7 @@ static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src) } dst->kb_base = cpu_to_le32(src->kb_base); + dst->unit_base = cpu_to_le32(src->unit_base); dst->groupid = cpu_to_le32(src->groupid); dst->unified_rw_rep = cpu_to_le32(src->unified_rw_rep); } @@ -730,6 +731,7 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs) p.ts.total_err_count = cpu_to_le64(ts->total_err_count); p.ts.first_error = cpu_to_le32(ts->first_error); p.ts.kb_base = cpu_to_le32(ts->kb_base); + p.ts.unit_base = cpu_to_le32(ts->unit_base); convert_gs(&p.rs, rs); diff --git a/stat.c b/stat.c index 041efeb6..f2b574e9 100644 --- a/stat.c +++ b/stat.c @@ -277,9 +277,9 @@ void show_group_stats(struct group_run_stats *rs) continue; p1 = num2str(rs->io_kb[i], 6, rs->kb_base, i2p, 8); - p2 = num2str(rs->agg[i], 6, rs->kb_base, i2p, 8); - p3 = num2str(rs->min_bw[i], 6, rs->kb_base, i2p, 8); - p4 = num2str(rs->max_bw[i], 6, rs->kb_base, i2p, 8); + p2 = num2str(rs->agg[i], 6, rs->kb_base, i2p, rs->unit_base); + p3 = num2str(rs->min_bw[i], 6, rs->kb_base, i2p, rs->unit_base); + p4 = num2str(rs->max_bw[i], 6, rs->kb_base, i2p, rs->unit_base); log_info("%s: io=%s, aggrb=%s/s, minb=%s/s, maxb=%s/s," " mint=%llumsec, maxt=%llumsec\n", @@ -380,7 +380,7 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts, bw = (1000 * ts->io_bytes[ddir]) / runt; io_p = num2str(ts->io_bytes[ddir], 6, 1, i2p, 8); - bw_p = num2str(bw, 6, 1, i2p, 8); + bw_p = num2str(bw, 6, 1, i2p, ts->unit_base); iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt; iops_p = num2str(iops, 6, 1, 0, 0); @@ -1169,6 +1169,7 @@ void show_run_stats(void) struct thread_stat *threadstats, *ts; int i, j, nr_ts, last_ts, idx; int kb_base_warned = 0; + int unit_base_warned = 0; struct json_object *root = NULL; struct json_array *array = NULL; @@ -1240,11 +1241,16 @@ void show_run_stats(void) ts->pid = td->pid; ts->kb_base = td->o.kb_base; + ts->unit_base = td->o.unit_base; ts->unified_rw_rep = td->o.unified_rw_rep; } else if (ts->kb_base != td->o.kb_base && !kb_base_warned) { log_info("fio: kb_base differs for jobs in group, using" " %u as the base\n", ts->kb_base); kb_base_warned = 1; + } else if (ts->unit_base != td->o.unit_base && !unit_base_warned) { + log_info("fio: unit_base differs for jobs in group, using" + " %u as the base\n", ts->unit_base); + unit_base_warned = 1; } ts->continue_on_error = td->o.continue_on_error; @@ -1270,6 +1276,7 @@ void show_run_stats(void) ts = &threadstats[i]; rs = &runstats[ts->groupid]; rs->kb_base = ts->kb_base; + rs->unit_base = ts->unit_base; rs->unified_rw_rep += ts->unified_rw_rep; for (j = 0; j < DDIR_RWDIR_CNT; j++) { diff --git a/stat.h b/stat.h index 98ae4c8e..f23abfab 100644 --- a/stat.h +++ b/stat.h @@ -7,6 +7,7 @@ struct group_run_stats { uint64_t io_kb[DDIR_RWDIR_CNT]; uint64_t agg[DDIR_RWDIR_CNT]; uint32_t kb_base; + uint32_t unit_base; uint32_t groupid; uint32_t unified_rw_rep; }; @@ -170,6 +171,7 @@ struct thread_stat { uint32_t first_error; uint32_t kb_base; + uint32_t unit_base; }; struct jobs_eta { @@ -184,6 +186,7 @@ struct jobs_eta { uint64_t elapsed_sec; uint64_t eta_sec; uint32_t is_pow2; + uint32_t unit_base; /* * Network 'copy' of run_str[] -- 2.25.1