Add ramp_time option
authorJens Axboe <jens.axboe@oracle.com>
Wed, 10 Sep 2008 07:46:16 +0000 (09:46 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Wed, 10 Sep 2008 07:46:16 +0000 (09:46 +0200)
Sometimes it's useful to let a job settle for a little while
before taking any measurements on latency and throughput, since
the initial rate on eg a write workload may be much higher than
the longer sustained rate.

So add a ramp_time option that allows the user to specify a lead
ramp time that must have passed before fio takes any performance
numbers into account.

Suggested by "Jenkins, Lee" <Lee.Jenkins@hp.com>

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

diff --git a/HOWTO b/HOWTO
index 7a65aa1..dd2f84a 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -574,6 +574,11 @@ time_based If set, fio will run for the duration of the runtime
                written. It will simply loop over the same workload
                as many times as the runtime allows.
 
+ramp_time      If set, fio will run the specified workload for this amount
+               of time before logging any performance numbers. Useful for
+               letting performance settle before logging results, thus
+               minimizing the runtime required for stable results.
+
 invalidate=bool        Invalidate the buffer/page cache parts for this file prior
                to starting io. Defaults to true.
 
diff --git a/fio.c b/fio.c
index ee752e1..2a09fbe 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -619,15 +619,17 @@ sync_done:
                 * of completions except the very first one which may look
                 * a little bursty
                 */
-               usec = utime_since(&s, &comp_time);
+               if (ramp_time_over(td)) {
+                       usec = utime_since(&s, &comp_time);
 
-               rate_throttle(td, usec, bytes_done);
+                       rate_throttle(td, usec, bytes_done);
 
-               if (check_min_rate(td, &comp_time)) {
-                       if (exitall_on_terminate)
-                               terminate_threads(td->groupid);
-                       td_verror(td, EIO, "check_min_rate");
-                       break;
+                       if (check_min_rate(td, &comp_time)) {
+                               if (exitall_on_terminate)
+                                       terminate_threads(td->groupid);
+                               td_verror(td, EIO, "check_min_rate");
+                               break;
+                       }
                }
 
                if (td->o.thinktime) {
diff --git a/fio.h b/fio.h
index 22aaf34..a0c1109 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -473,6 +473,7 @@ struct thread_options {
        unsigned int fsync_blocks;
        unsigned int start_delay;
        unsigned long long timeout;
+       unsigned long long ramp_time;
        unsigned int overwrite;
        unsigned int bw_avg_time;
        unsigned int loops;
@@ -609,6 +610,7 @@ struct thread_data {
        struct timeval rw_end[2];
        struct timeval last_issue;
        unsigned int rw_end_set[2];
+       unsigned int ramp_time_over;
 
        /*
         * read/write mixed workload state
@@ -817,6 +819,7 @@ extern void rate_throttle(struct thread_data *, unsigned long, unsigned int);
 extern void fill_start_time(struct timeval *);
 extern void fio_gettime(struct timeval *, void *);
 extern void set_genesis_time(void);
+extern int ramp_time_over(struct thread_data *);
 
 /*
  * Init/option functions
diff --git a/io_u.c b/io_u.c
index 1dff88f..17db16b 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -903,24 +903,29 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
        if (!io_u->error) {
                unsigned int bytes = io_u->buflen - io_u->resid;
                const enum fio_ddir idx = io_u->ddir;
-               int ret;
+               int ret, ramp_done;
 
-               td->io_blocks[idx]++;
-               td->io_bytes[idx] += bytes;
-               td->this_io_bytes[idx] += bytes;
+               ramp_done = ramp_time_over(td);
 
-               usec = utime_since(&io_u->issue_time, &icd->time);
+               if (ramp_done) {
+                       td->io_blocks[idx]++;
+                       td->io_bytes[idx] += bytes;
+                       td->this_io_bytes[idx] += bytes;
 
-               add_clat_sample(td, idx, usec);
-               add_bw_sample(td, idx, &icd->time);
-               io_u_mark_latency(td, usec);
+                       usec = utime_since(&io_u->issue_time, &icd->time);
+
+                       add_clat_sample(td, idx, usec);
+                       add_bw_sample(td, idx, &icd->time);
+                       io_u_mark_latency(td, usec);
+               }
 
                if (td_write(td) && idx == DDIR_WRITE &&
                    td->o.do_verify &&
                    td->o.verify != VERIFY_NONE)
                        log_io_piece(td, io_u);
 
-               icd->bytes_done[idx] += bytes;
+               if (ramp_done)
+                       icd->bytes_done[idx] += bytes;
 
                if (io_u->end_io) {
                        ret = io_u->end_io(td, io_u);
index 0608e7b..8723adf 100644 (file)
--- a/options.c
+++ b/options.c
@@ -831,6 +831,12 @@ static struct fio_option options[] = {
                .off1   = td_var_offset(time_based),
                .help   = "Keep running until runtime/timeout is met",
        },
+       {
+               .name   = "ramp_time",
+               .type   = FIO_OPT_STR_VAL_TIME,
+               .off1   = td_var_offset(ramp_time),
+               .help   = "Ramp up time before measuring performance",
+       },
        {
                .name   = "mem",
                .alias  = "iomem",
diff --git a/time.c b/time.c
index 505058f..4f1c13a 100644 (file)
--- a/time.c
+++ b/time.c
@@ -164,6 +164,23 @@ unsigned long mtime_since_genesis(void)
        return mtime_since_now(&genesis);
 }
 
+int ramp_time_over(struct thread_data *td)
+{
+       struct timeval tv;
+
+       if (!td->o.ramp_time || td->ramp_time_over)
+               return 1;
+
+       fio_gettime(&tv, NULL);
+       if (mtime_since(&td->epoch, &tv) >= td->o.ramp_time * 1000) {
+               td->ramp_time_over = 1;
+               memcpy(&td->start, &tv, sizeof(tv));
+               return 1;
+       }
+
+       return 0;
+}
+
 static void fio_init time_init(void)
 {
        int i;