[PATCH] Include io depth distribution statistics
authorJens Axboe <jens.axboe@oracle.com>
Sat, 13 Jan 2007 22:56:33 +0000 (23:56 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Sat, 13 Jan 2007 22:56:33 +0000 (23:56 +0100)
Calculate the distribution of io depths for the job run.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
fio.h
io_u.c
stat.c

diff --git a/HOWTO b/HOWTO
index 40f974cba7fdfce741c3ca641ef9975c8cd9b61c..95d059e766e6399f29d8097331a076db4df29161 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -539,6 +539,7 @@ Client1 (g=0): err= 0:
     clat (msec): min=    0, max=  631, avg=48.50, stdev=86.82
     bw (KiB/s) : min=    0, max= 1196, per=51.00%, avg=664.02, stdev=681.68
   cpu        : usr=1.49%, sys=0.25%, ctx=7969
     clat (msec): min=    0, max=  631, avg=48.50, stdev=86.82
     bw (KiB/s) : min=    0, max= 1196, per=51.00%, avg=664.02, stdev=681.68
   cpu        : usr=1.49%, sys=0.25%, ctx=7969
+  IO depths    : 1=0.1%, 2=0.3%, 4=0.5%, 8=99.0%, 16=0.0%, 32=0.0%, >32=0.0%
 
 The client number is printed, along with the group id and error of that
 thread. Below is the io statistics, here for writes. In the order listed,
 
 The client number is printed, along with the group id and error of that
 thread. Below is the io statistics, here for writes. In the order listed,
@@ -563,6 +564,11 @@ runt=              The runtime of that thread
                same disk, since they are then competing for disk access.
 cpu=           CPU usage. User and system time, along with the number
                of context switches this thread went through.
                same disk, since they are then competing for disk access.
 cpu=           CPU usage. User and system time, along with the number
                of context switches this thread went through.
+IO depths=     The distribution of io depths over the job life time. The
+               numbers are divided into powers of 2, so for example the
+               16= entries includes depths up to that value but higher
+               than the previous entry. In other words, it covers the
+               range from 16 to 31.
 
 After each client has been listed, the group statistics are printed. They
 will look like this:
 
 After each client has been listed, the group statistics are printed. They
 will look like this:
diff --git a/fio.h b/fio.h
index e85d6cc1f0ac2011fb79780adb838039cd8b56a0..c21440667a51bf6c09db8c39b799901dbdf97446 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -167,6 +167,11 @@ struct fio_file {
        unsigned int unlink;
 };
 
        unsigned int unlink;
 };
 
+/*
+ * How many depth levels to log
+ */
+#define FIO_IO_U_MAP_NR        8
+
 /*
  * This describes a single thread/process executing a fio job.
  */
 /*
  * This describes a single thread/process executing a fio job.
  */
@@ -264,6 +269,8 @@ struct thread_data {
         * Current IO depth and list of free and busy io_u's.
         */
        unsigned int cur_depth;
         * Current IO depth and list of free and busy io_u's.
         */
        unsigned int cur_depth;
+       unsigned int io_u_map[FIO_IO_U_MAP_NR];
+       unsigned long total_io_u;
        struct list_head io_u_freelist;
        struct list_head io_u_busylist;
 
        struct list_head io_u_freelist;
        struct list_head io_u_busylist;
 
diff --git a/io_u.c b/io_u.c
index 834e5d214d5da390365858f36d67ed3fd67127a6..5e53b81443cda688bdb42163dc2a5af4cc28fe04 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -227,6 +227,31 @@ static int fill_io_u(struct thread_data *td, struct fio_file *f,
        return 1;
 }
 
        return 1;
 }
 
+static void io_u_mark_depth(struct thread_data *td)
+{
+       int index = 0;
+
+       switch (td->cur_depth) {
+       default:
+               index++;
+       case 32 ... 63:
+               index++;
+       case 16 ... 31:
+               index++;
+       case 8 ... 15:
+               index++;
+       case 4 ... 7:
+               index++;
+       case 2 ... 3:
+               index++;
+       case 1:
+               break;
+       }
+
+       td->io_u_map[index]++;
+       td->total_io_u++;
+}
+
 struct io_u *__get_io_u(struct thread_data *td)
 {
        struct io_u *io_u = NULL;
 struct io_u *__get_io_u(struct thread_data *td)
 {
        struct io_u *io_u = NULL;
@@ -240,6 +265,7 @@ struct io_u *__get_io_u(struct thread_data *td)
                list_del(&io_u->list);
                list_add(&io_u->list, &td->io_u_busylist);
                td->cur_depth++;
                list_del(&io_u->list);
                list_add(&io_u->list, &td->io_u_busylist);
                td->cur_depth++;
+               io_u_mark_depth(td);
        }
 
        return io_u;
        }
 
        return io_u;
diff --git a/stat.c b/stat.c
index e7ffd8ccf1f7bc6de8241a2e26b25035d0a8169d..b4806e0e8c48dfb5557be2f4abcdf31bf4ed41e1 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -375,6 +375,8 @@ static void show_thread_status(struct thread_data *td,
 {
        double usr_cpu, sys_cpu;
        unsigned long runtime;
 {
        double usr_cpu, sys_cpu;
        unsigned long runtime;
+       double io_u_dist[FIO_IO_U_MAP_NR];
+       int i;
 
        if (!(td->io_bytes[0] + td->io_bytes[1]) && !td->error)
                return;
 
        if (!(td->io_bytes[0] + td->io_bytes[1]) && !td->error)
                return;
@@ -397,6 +399,16 @@ static void show_thread_status(struct thread_data *td,
        }
 
        fprintf(f_out, "  cpu          : usr=%3.2f%%, sys=%3.2f%%, ctx=%lu\n", usr_cpu, sys_cpu, td->ctx);
        }
 
        fprintf(f_out, "  cpu          : usr=%3.2f%%, sys=%3.2f%%, ctx=%lu\n", usr_cpu, sys_cpu, td->ctx);
+
+       /*
+        * Do depth distribution calculations
+        */
+       for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
+               io_u_dist[i] = (double) td->io_u_map[i] / (double) td->total_io_u;
+               io_u_dist[i] *= 100.0;
+       }
+
+       fprintf(f_out, "  IO depths    : 1=%3.1f%%, 2=%3.1f%%, 4=%3.1f%%, 8=%3.1f%%, 16=%3.1f%%, 32=%3.1f%%, >32=%3.1f%%\n", io_u_dist[0], io_u_dist[1], io_u_dist[2], io_u_dist[3], io_u_dist[4], io_u_dist[5], io_u_dist[6]);
 }
 
 static void show_ddir_status_terse(struct thread_data *td,
 }
 
 static void show_ddir_status_terse(struct thread_data *td,