Add kb_base option to specify the base unit of a kilobyte
authorJens Axboe <jens.axboe@oracle.com>
Fri, 17 Jul 2009 20:33:32 +0000 (22:33 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 17 Jul 2009 20:33:32 +0000 (22:33 +0200)
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
fio.1
fio.h
options.c
stat.c

diff --git a/HOWTO b/HOWTO
index 2d155aa..6cdd71d 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -290,6 +290,11 @@ rw=str             Type of io pattern. Accepted values are:
                IO's, instead of for every IO. Use rw=randread:8 to specify
                that.
 
+kb_base=int    The base unit for a kilobyte. The defacto base is 2^10, 1024.
+               Storage manufacturers like to use 10^3 or 1000 as a base
+               ten unit instead, for obvious reasons. Allow values are
+               1024 or 1000, with 1024 being the default.
+
 randrepeat=bool        For random IO workloads, seed the generator in a predictable
                way so that results are repeatable across repetitions.
 
diff --git a/fio.1 b/fio.1
index f4a3293..497db53 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -172,6 +172,11 @@ to perform before getting a new offset can be specified by appending
 `:\fIint\fR' to the pattern type.  The default is 1.
 .RE
 .TP
+.BI kb_base \fR=\fPint
+The base unit for a kilobyte. The defacto base is 2^10, 1024.  Storage
+manufacturers like to use 10^3 or 1000 as a base ten unit instead, for obvious
+reasons. Allow values are 1024 or 1000, with 1024 being the default.
+.TP
 .BI randrepeat \fR=\fPbool
 Seed the random number generator in a predictable way so results are repeatable
 across runs.  Default: true.
diff --git a/fio.h b/fio.h
index fb70b46..56d3101 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -42,6 +42,7 @@ struct group_run_stats {
        unsigned long long max_bw[2], min_bw[2];
        unsigned long long io_kb[2];
        unsigned long long agg[2];
+       unsigned int kb_base;
 };
 
 /*
@@ -118,6 +119,8 @@ struct thread_stat {
        unsigned continue_on_error;
        unsigned long total_err_count;
        int first_error;
+
+       unsigned int kb_base;
 };
 
 struct bssplit {
@@ -134,6 +137,7 @@ struct thread_options {
        char *opendir;
        char *ioengine;
        enum td_ddir td_ddir;
+       unsigned int kb_base;
        unsigned int ddir_nr;
        unsigned int iodepth;
        unsigned int iodepth_low;
index 0954ccd..c273da7 100644 (file)
--- a/options.c
+++ b/options.c
@@ -627,6 +627,19 @@ static int gtod_cpu_verify(struct fio_option *o, void *data)
        return 0;
 }
 
+static int kb_base_verify(struct fio_option *o, void *data)
+{
+       struct thread_data *td = data;
+
+       if (td->o.kb_base != 1024 && td->o.kb_base != 1000) {
+               log_err("fio: kb_base set to nonsensical value: %u\n",
+                               td->o.kb_base);
+               return 1;
+       }
+
+       return 0;
+}
+
 #define __stringify_1(x)       #x
 #define __stringify(x)         __stringify_1(x)
 
@@ -661,6 +674,14 @@ static struct fio_option options[] = {
                .prio   = -1, /* must come after "directory" */
                .help   = "File(s) to use for the workload",
        },
+       {
+               .name   = "kb_base",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(kb_base),
+               .help   = "How many bytes per KB for reporting (1000 or 1024)",
+               .verify = kb_base_verify,
+               .def    = "1024",
+       },
        {
                .name   = "lockfile",
                .type   = FIO_OPT_STR,
diff --git a/stat.c b/stat.c
index 7319b9c..c52620d 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -59,13 +59,15 @@ static void show_group_stats(struct group_run_stats *rs, int id)
        log_info("\nRun status group %d (all jobs):\n", id);
 
        for (i = 0; i <= DDIR_WRITE; i++) {
+               const int i2p = is_power_of_2(rs->kb_base);
+
                if (!rs->max_run[i])
                        continue;
 
-               p1 = num2str(rs->io_kb[i], 6, 1024, 1);
-               p2 = num2str(rs->agg[i], 6, 1024, 1);
-               p3 = num2str(rs->min_bw[i], 6, 1024, 1);
-               p4 = num2str(rs->max_bw[i], 6, 1024, 1);
+               p1 = num2str(rs->io_kb[i], 6, rs->kb_base, i2p);
+               p2 = num2str(rs->agg[i], 6, rs->kb_base, i2p);
+               p3 = num2str(rs->min_bw[i], 6, rs->kb_base, i2p);
+               p4 = num2str(rs->max_bw[i], 6, rs->kb_base, i2p);
 
                log_info("%s: io=%sB, aggrb=%sB/s, minb=%sB/s, maxb=%sB/s,"
                         " mint=%llumsec, maxt=%llumsec\n", ddir_str[i], p1, p2,
@@ -153,15 +155,17 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
        unsigned long long bw, iops;
        double mean, dev;
        char *io_p, *bw_p, *iops_p;
+       int i2p;
 
        if (!ts->runtime[ddir])
                return;
 
+       i2p = is_power_of_2(rs->kb_base);
        runt = ts->runtime[ddir];
 
        bw = (1000 * ts->io_bytes[ddir]) / runt;
-       io_p = num2str(ts->io_bytes[ddir] >> 10, 6, 1024, 1);
-       bw_p = num2str(bw >> 10, 6, 1024, 1);
+       io_p = num2str(ts->io_bytes[ddir], 6, 1, i2p);
+       bw_p = num2str(bw, 6, 1, i2p);
 
        iops = (1000 * ts->total_io_u[ddir]) / runt;
        iops_p = num2str(iops, 6, 1, 0);
@@ -457,6 +461,7 @@ void show_run_stats(void)
        struct thread_data *td;
        struct thread_stat *threadstats, *ts;
        int i, j, k, l, nr_ts, last_ts, idx;
+       int kb_base_warned = 0;
 
        runstats = malloc(sizeof(struct group_run_stats) * (groupid + 1));
 
@@ -529,6 +534,12 @@ void show_run_stats(void)
                         * first pid in group, not very useful...
                         */
                        ts->pid = td->pid;
+
+                       ts->kb_base = td->o.kb_base;
+               } 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;
                }
 
                ts->continue_on_error = td->o.continue_on_error;
@@ -590,6 +601,7 @@ void show_run_stats(void)
 
                ts = &threadstats[i];
                rs = &runstats[ts->groupid];
+               rs->kb_base = ts->kb_base;
 
                for (j = 0; j <= DDIR_WRITE; j++) {
                        if (!ts->runtime[j])
@@ -603,7 +615,7 @@ void show_run_stats(void)
                        if (ts->runtime[j]) {
                                unsigned long runt;
 
-                               runt = ts->runtime[j] * 1024 / 1000;
+                               runt = ts->runtime[j];
                                bw = ts->io_bytes[j] / runt;
                        }
                        if (bw < rs->min_bw[j])
@@ -611,7 +623,7 @@ void show_run_stats(void)
                        if (bw > rs->max_bw[j])
                                rs->max_bw[j] = bw;
 
-                       rs->io_kb[j] += ts->io_bytes[j] >> 10;
+                       rs->io_kb[j] += ts->io_bytes[j] / rs->kb_base;
                }
        }
 
@@ -619,13 +631,13 @@ void show_run_stats(void)
                unsigned long max_run[2];
 
                rs = &runstats[i];
-               max_run[0] = rs->max_run[0] * 1024 / 1000;
-               max_run[1] = rs->max_run[1] * 1024 / 1000;
+               max_run[0] = rs->max_run[0];
+               max_run[1] = rs->max_run[1];
 
                if (rs->max_run[0])
-                       rs->agg[0] = (rs->io_kb[0]*1024) / max_run[0];
+                       rs->agg[0] = (rs->io_kb[0] * 1000) / max_run[0];
                if (rs->max_run[1])
-                       rs->agg[1] = (rs->io_kb[1]*1024) / max_run[1];
+                       rs->agg[1] = (rs->io_kb[1] * 1000) / max_run[1];
        }
 
        /*