implement 'unit_base' option to select between KB and Kbit et. al.
authorSteven Noonan <steven@uplinklabs.net>
Mon, 8 Apr 2013 22:05:25 +0000 (15:05 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 9 Apr 2013 18:00:35 +0000 (20:00 +0200)
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 <steven@uplinklabs.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
client.c
engines/net.c
eta.c
fio.h
init.c
ioengine.h
options.c
server.c
stat.c
stat.h

index 0dc620d..7915268 100644 (file)
--- 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)
index 624ff15..31f7151 100644 (file)
@@ -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 e08b5f7..50d229c 100644 (file)
--- 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 cc43976..e74bdb3 100644 (file)
--- 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 92b3e5b..44c74e3 100644 (file)
--- 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()"
index 7299636..d15d15e 100644 (file)
@@ -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) */
 };
 
 /*
index bca217f..66099b5 100644 (file)
--- 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,
index d4676dd..f239d43 100644 (file)
--- 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 041efeb..f2b574e 100644 (file)
--- 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 98ae4c8..f23abfa 100644 (file)
--- 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[]