Add kb_base option to specify the base unit of a kilobyte
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/HOWTO b/HOWTO
index 2d155aa..6cdd71d 100644
--- a/HOWTO
+++ b/HOWTO
@@ -290,6 +290,11 @@
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
--- a/fio.1
+++ b/fio.1
@@ -172,6 +172,11 @@
`:\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
--- a/fio.h
+++ b/fio.h
@@ -42,6 +42,7 @@
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 @@
unsigned continue_on_error;
unsigned long total_err_count;
int first_error;
+
+ unsigned int kb_base;
};
struct bssplit {
@@ -134,6 +137,7 @@
char *opendir;
char *ioengine;
enum td_ddir td_ddir;
+ unsigned int kb_base;
unsigned int ddir_nr;
unsigned int iodepth;
unsigned int iodepth_low;
diff --git a/options.c b/options.c
index 0954ccd..c273da7 100644
--- a/options.c
+++ b/options.c
@@ -627,6 +627,19 @@
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)
@@ -662,6 +675,14 @@
.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,
.cb = str_lockfile_cb,
diff --git a/stat.c b/stat.c
index 7319b9c..c52620d 100644
--- a/stat.c
+++ b/stat.c
@@ -59,13 +59,15 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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];
}
/*