Improve latency_target runs
authorJens Axboe <axboe@fb.com>
Fri, 21 Feb 2014 21:55:31 +0000 (13:55 -0800)
committerJens Axboe <axboe@fb.com>
Fri, 21 Feb 2014 21:55:31 +0000 (13:55 -0800)
Reset the stats when we have found our target, and then do
another latency_window run with those settings so that the
final results reflect the probed values.

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

diff --git a/fio.h b/fio.h
index d1180cd4809bb090e5a96e4266be0da5933c80e5..9159b0c2de3e207cd15bf73d683a9accdde72934 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -262,6 +262,7 @@ struct thread_data {
        unsigned int latency_qd_low;
        unsigned int latency_failed;
        uint64_t latency_ios;
+       int latency_end_run;
 
        /*
         * read/write mixed workload state
@@ -504,6 +505,7 @@ extern int load_blktrace(struct thread_data *, const char *, int);
  */
 extern void lat_target_check(struct thread_data *);
 extern void lat_target_init(struct thread_data *);
+extern void lat_target_reset(struct thread_data *);
 
 #define for_each_td(td, i)     \
        for ((i) = 0, (td) = &threads[0]; (i) < (int) thread_number; (i)++, (td)++)
diff --git a/io_u.c b/io_u.c
index b84b3e2307daa67f6723b1556cd9731c67ad5f36..619fa25255f84ee785eccedcf7f96bfe94b41ab4 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -1162,6 +1162,10 @@ static int __lat_target_failed(struct thread_data *td)
                return 1;
 
        td->latency_qd_high = td->latency_qd;
+
+       if (td->latency_qd == td->latency_qd_low)
+               td->latency_qd_low--;
+
        td->latency_qd = (td->latency_qd + td->latency_qd_low) / 2;
 
        dprint(FD_RATE, "Ramped down: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
@@ -1186,6 +1190,8 @@ static int lat_target_failed(struct thread_data *td)
 
 void lat_target_init(struct thread_data *td)
 {
+       td->latency_end_run = 0;
+
        if (td->o.latency_target) {
                dprint(FD_RATE, "Latency target=%llu\n", td->o.latency_target);
                fio_gettime(&td->latency_ts, NULL);
@@ -1197,9 +1203,16 @@ void lat_target_init(struct thread_data *td)
                td->latency_qd = td->o.iodepth;
 }
 
+void lat_target_reset(struct thread_data *td)
+{
+       if (!td->latency_end_run)
+               lat_target_init(td);
+}
+
 static void lat_target_success(struct thread_data *td)
 {
        const unsigned int qd = td->latency_qd;
+       struct thread_options *o = &td->o;
 
        td->latency_qd_low = td->latency_qd;
 
@@ -1208,20 +1221,32 @@ static void lat_target_success(struct thread_data *td)
         * of bisecting from highest possible queue depth. If we have set
         * a limit other than td->o.iodepth, bisect between that.
         */
-       if (td->latency_qd_high != td->o.iodepth)
+       if (td->latency_qd_high != o->iodepth)
                td->latency_qd = (td->latency_qd + td->latency_qd_high) / 2;
        else
                td->latency_qd *= 2;
 
-       if (td->latency_qd > td->o.iodepth)
-               td->latency_qd = td->o.iodepth;
+       if (td->latency_qd > o->iodepth)
+               td->latency_qd = o->iodepth;
 
        dprint(FD_RATE, "Ramped up: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
+
        /*
-        * Same as last one, we are done
+        * Same as last one, we are done. Let it run a latency cycle, so
+        * we get only the results from the targeted depth.
         */
-       if (td->latency_qd == qd)
-               td->done = 1;
+       if (td->latency_qd == qd) {
+               if (td->latency_end_run) {
+                       dprint(FD_RATE, "We are done\n");
+                       td->done = 1;
+               } else {
+                       dprint(FD_RATE, "Quiesce and final run\n");
+                       io_u_quiesce(td);
+                       td->latency_end_run = 1;
+                       reset_all_stats(td);
+                       reset_io_stats(td);
+               }
+       }
 
        lat_new_cycle(td);
 }
index 222cd16dec8fe3f039c55749af37656679977221..f4aac2efb739c6910ca37cb046e6f2ad053c00d2 100644 (file)
--- a/libfio.c
+++ b/libfio.c
@@ -135,7 +135,7 @@ void reset_all_stats(struct thread_data *td)
        memcpy(&td->epoch, &tv, sizeof(tv));
        memcpy(&td->start, &tv, sizeof(tv));
 
-       lat_target_init(td);
+       lat_target_reset(td);
 }
 
 void reset_fio_state(void)
diff --git a/stat.c b/stat.c
index bc01b5192f31a25299591b5a66dd4c0a6d3ce242..e43db8f9d075431a0d90c04b8d4fd941c05ffaf5 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -1579,6 +1579,41 @@ static inline void reset_io_stat(struct io_stat *ios)
        ios->mean.u.f = ios->S.u.f = 0;
 }
 
+void reset_io_stats(struct thread_data *td)
+{
+       struct thread_stat *ts = &td->ts;
+       int i, j;
+
+       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+               reset_io_stat(&ts->clat_stat[i]);
+               reset_io_stat(&ts->slat_stat[i]);
+               reset_io_stat(&ts->lat_stat[i]);
+               reset_io_stat(&ts->bw_stat[i]);
+               reset_io_stat(&ts->iops_stat[i]);
+
+               ts->io_bytes[i] = 0;
+               ts->runtime[i] = 0;
+
+               for (j = 0; j < FIO_IO_U_PLAT_NR; j++)
+                       ts->io_u_plat[i][j] = 0;
+       }
+
+       for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
+               ts->io_u_map[i] = 0;
+               ts->io_u_submit[i] = 0;
+               ts->io_u_complete[i] = 0;
+               ts->io_u_lat_u[i] = 0;
+               ts->io_u_lat_m[i] = 0;
+               ts->total_submit = 0;
+               ts->total_complete = 0;
+       }
+
+       for (i = 0; i < 3; i++) {
+               ts->total_io_u[i] = 0;
+               ts->short_io_u[i] = 0;
+       }
+}
+
 static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed)
 {
        /*
diff --git a/stat.h b/stat.h
index 7ad0c9df7e8d15ec9149735e4f7d13f7ef8eb08f..bc4f6da483663a2d84921083863c29f4fa92c313 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -224,6 +224,7 @@ extern unsigned int calc_clat_percentiles(unsigned int *io_u_plat, unsigned long
 extern void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat);
 extern void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat);
 extern void stat_calc_dist(unsigned int *map, unsigned long total, double *io_u_dist);
+extern void reset_io_stats(struct thread_data *);
 
 static inline int usec_to_msec(unsigned long *min, unsigned long *max,
                               double *mean, double *dev)