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 7a65aa1540338c32bc2d43ef5b862b6c68b5b7ab..dd2f84a8f8fd850fa4fc6d088ea2e5675014ee3e 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.
 
                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.
 
 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 ee752e1266aaf88350eb10eb3ee4d757945b0066..2a09fbe2d71b68fe40eaa0f7fb4f77056219d81f 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
                 */
                 * 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) {
                }
 
                if (td->o.thinktime) {
diff --git a/fio.h b/fio.h
index 22aaf345ae8daa093df160a7f10523702d0c5e1c..a0c1109ab97a8a9d4bb96c8ad9910408a9615266 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 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;
        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];
        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
 
        /*
         * 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 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
 
 /*
  * Init/option functions
diff --git a/io_u.c b/io_u.c
index 1dff88f1edf64a5a10d9ea296ee1f5ae51e72288..17db16b1cb3ad13a29a7d4c8e905b564f3e88573 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;
        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);
 
 
                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);
 
                if (io_u->end_io) {
                        ret = io_u->end_io(td, io_u);
index 0608e7b2d928b5bf38385926639ffb406cd6a4d1..8723adff589321729e5501d458174ccdef5ad830 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",
        },
                .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",
        {
                .name   = "mem",
                .alias  = "iomem",
diff --git a/time.c b/time.c
index 505058f53b270f973482bdd839245d6239d69e99..4f1c13a08a5c6a77d07bb1fe9cc26bb4f84ba868 100644 (file)
--- a/time.c
+++ b/time.c
@@ -164,6 +164,23 @@ unsigned long mtime_since_genesis(void)
        return mtime_since_now(&genesis);
 }
 
        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;
 static void fio_init time_init(void)
 {
        int i;