Patch to make per-thread IOPS more accurate
authorBen England <bengland@redhat.com>
Fri, 27 Feb 2015 15:14:49 +0000 (08:14 -0700)
committerJens Axboe <axboe@fb.com>
Fri, 27 Feb 2015 15:14:49 +0000 (08:14 -0700)
The following small patch to stat.c (using fio 2.2.4 from github)
outputs IOPS field in JSON format as a floating point number instead of
an integer.  This improves accuracy in case where fio --client runs use
lots of threads with single-digit IOPS per thread.  It seems to work,
here's a snippet of output from a short fio run with rate_iops=10 in the
job file.

     "write" : {
        "io_bytes" : 6464,
        "bw" : 646,
        "iops" : 10.10,
        "runtime" : 10000,

Why the patch: IOPS number is rounded to integer in stats.c calls to
num2str().  This doesn't sound like much of a problem because in many
use cases, with large IOPS number the error is negligible.  But in this
use case where we have many threads (we would like to get into the
thousands eventually), the IOPS/thread may be quite low and integer
rounding can introduce significant error.  For example, if we are doing
5,000 IOPS over 1,000 threads, average throughput is 5 IOPS and
potential error is ~20%, but some threads could have much higher error
in IOPS because of integer format.

Signed-off-by: Jens Axboe <axboe@fb.com>
stat.c

diff --git a/stat.c b/stat.c
index db4a387299bbd84badba2f59d02eca4d703bbf73..85bd728d4aaa748ae97a50b7861b43f853b2338e 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -674,9 +674,9 @@ static void add_ddir_status_json(struct thread_stat *ts,
                struct group_run_stats *rs, int ddir, struct json_object *parent)
 {
        unsigned long min, max;
-       unsigned long long bw, iops;
+       unsigned long long bw;
        unsigned int *ovals = NULL;
-       double mean, dev;
+       double mean, dev, iops;
        unsigned int len, minv, maxv;
        int i;
        const char *ddirname[] = {"read", "write", "trim"};
@@ -693,17 +693,18 @@ static void add_ddir_status_json(struct thread_stat *ts,
        json_object_add_value_object(parent,
                ts->unified_rw_rep ? "mixed" : ddirname[ddir], dir_object);
 
-       iops = bw = 0;
+       bw = 0;
+       iops = 0.0;
        if (ts->runtime[ddir]) {
                uint64_t runt = ts->runtime[ddir];
 
                bw = ((1000 * ts->io_bytes[ddir]) / runt) / 1024;
-               iops = (1000 * (uint64_t) ts->total_io_u[ddir]) / runt;
+               iops = (1000.0 * (uint64_t) ts->total_io_u[ddir]) / runt;
        }
 
        json_object_add_value_int(dir_object, "io_bytes", ts->io_bytes[ddir] >> 10);
        json_object_add_value_int(dir_object, "bw", bw);
-       json_object_add_value_int(dir_object, "iops", iops);
+       json_object_add_value_float(dir_object, "iops", iops);
        json_object_add_value_int(dir_object, "runtime", ts->runtime[ddir]);
        json_object_add_value_int(dir_object, "total_ios", ts->total_io_u[ddir]);
        json_object_add_value_int(dir_object, "short_ios", ts->short_io_u[ddir]);