Allow configurable ETA intervals
authorJens Axboe <axboe@kernel.dk>
Thu, 14 Dec 2017 18:51:41 +0000 (11:51 -0700)
committerJens Axboe <axboe@kernel.dk>
Thu, 14 Dec 2017 18:51:41 +0000 (11:51 -0700)
By default, fio prints ETA output every second. For some client/server
setups, it's desirable to allow a much longer interval, to avoid
spending too much time getting and printing ETA time.

Takes a normal time input, allowing usec/msec/sec etc postfixes.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
HOWTO
client.c
eta.c
fio.1
fio.h
init.c

diff --git a/HOWTO b/HOWTO
index 563ca933e699828274de1171d512262d5be9f68c..78fa6ccf4a61e623a44c0e1137f46cc416382ee8 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -173,7 +173,16 @@ Command line options
 .. option:: --eta=when
 
        Specifies when real-time ETA estimate should be printed.  `when` may be
-       `always`, `never` or `auto`.
+       `always`, `never` or `auto`. `auto` is the default, it prints ETA
+       when requested if the output is a TTY. `always` disregards the output
+       type, and prints ETA when requested. `never` never prints ETA.
+
+.. option:: --eta-interval=time
+
+       By default, fio requests client ETA status roughly every second. With
+       this option, the interval is configurable. Fio imposes a minimum
+       allowed time to avoid flooding the console, less than 250 msec is
+       not supported.
 
 .. option:: --eta-newline=time
 
index 82e12855ca5f904943238a47ddcd0ceef5cda730..18247ef6b9bd277c0e66a980b3a49679aa4f1173 100644 (file)
--- a/client.c
+++ b/client.c
@@ -2000,7 +2000,7 @@ int fio_handle_clients(struct client_ops *ops)
                        int timeout;
 
                        fio_gettime(&ts, NULL);
-                       if (mtime_since(&eta_ts, &ts) >= 900) {
+                       if (eta_time_within_slack(mtime_since(&eta_ts, &ts))) {
                                request_client_etas(ops);
                                memcpy(&eta_ts, &ts, sizeof(ts));
 
diff --git a/eta.c b/eta.c
index 1b0b000df115d4b04ff0ed614d3f9a8660e7abfb..8b77dafaf9700b30996c1650788ec6c554598cdf 100644 (file)
--- a/eta.c
+++ b/eta.c
@@ -347,6 +347,14 @@ static void calc_iops(int unified_rw_rep, unsigned long mtime,
        }
 }
 
+/*
+ * Allow a little slack - if we're within 95% of the time, allow ETA.
+ */
+bool eta_time_within_slack(unsigned int time)
+{
+       return time > ((eta_interval_msec * 95) / 100);
+}
+
 /*
  * Print status of the jobs we know about. This includes rate estimates,
  * ETA, thread state, etc.
@@ -489,10 +497,7 @@ bool calc_thread_status(struct jobs_eta *je, int force)
 
        disp_time = mtime_since(&disp_prev_time, &now);
 
-       /*
-        * Allow a little slack, the target is to print it every 1000 msecs
-        */
-       if (!force && disp_time < 900)
+       if (!force && !eta_time_within_slack(disp_time))
                return false;
 
        calc_rate(unified_rw_rep, disp_time, io_bytes, disp_io_bytes, je->rate);
diff --git a/fio.1 b/fio.1
index 57ab66564f7800eb2fa61caec06022f3354cbc36..70eeeb0f6c8ca35634e98ed648b833df8299bb98 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -77,7 +77,14 @@ the I/O engine core to prevent writes due to unknown user space bug(s).
 .TP
 .BI \-\-eta \fR=\fPwhen
 Specifies when real\-time ETA estimate should be printed. \fIwhen\fR may
-be `always', `never' or `auto'.
+be `always', `never' or `auto'. `auto' is the default, it prints ETA when
+requested if the output is a TTY. `always' disregards the output type, and
+prints ETA when requested. `never' never prints ETA.
+.TP
+.BI \-\-eta\-interval \fR=\fPtime
+By default, fio requests client ETA status roughly every second. With this
+option, the interval is configurable. Fio imposes a minimum allowed time to
+avoid flooding the console, less than 250 msec is not supported.
 .TP
 .BI \-\-eta\-newline \fR=\fPtime
 Force a new line for every \fItime\fR period passed. When the unit is omitted,
diff --git a/fio.h b/fio.h
index 8a65646134e0d5c8916b4c88df4bb381540bf326..b3b95efb1b0ee23ad369efb2586bf87fa8edd1e0 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -505,6 +505,7 @@ extern uintptr_t page_mask, page_size;
 extern int read_only;
 extern int eta_print;
 extern int eta_new_line;
+extern unsigned int eta_interval_msec;
 extern unsigned long done_secs;
 extern int fio_gtod_offload;
 extern int fio_gtod_cpu;
@@ -525,6 +526,8 @@ extern char *aux_path;
 
 extern struct thread_data *threads;
 
+extern bool eta_time_within_slack(unsigned int time);
+
 static inline void fio_ro_check(const struct thread_data *td, struct io_u *io_u)
 {
        assert(!(io_u->ddir == DDIR_WRITE && !td_write(td)));
diff --git a/init.c b/init.c
index b77b299ef8e310ad91c5e42aecc0a71975dfdd9b..b9da71335a7fc34aece77d4678949c35a276cdd1 100644 (file)
--- a/init.c
+++ b/init.c
@@ -51,6 +51,7 @@ static int nr_job_sections;
 int exitall_on_terminate = 0;
 int output_format = FIO_OUTPUT_NORMAL;
 int eta_print = FIO_ETA_AUTO;
+unsigned int eta_interval_msec = 1000;
 int eta_new_line = 0;
 FILE *f_out = NULL;
 FILE *f_err = NULL;
@@ -153,6 +154,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .has_arg        = required_argument,
                .val            = 'e' | FIO_CLIENT_FLAG,
        },
+       {
+               .name           = (char *) "eta-interval",
+               .has_arg        = required_argument,
+               .val            = 'O' | FIO_CLIENT_FLAG,
+       },
        {
                .name           = (char *) "eta-newline",
                .has_arg        = required_argument,
@@ -2504,8 +2510,31 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                                log_err("fio: failed parsing eta time %s\n", optarg);
                                exit_val = 1;
                                do_exit++;
+                               break;
                        }
                        eta_new_line = t / 1000;
+                       if (!eta_new_line) {
+                               log_err("fio: eta new line time too short\n");
+                               exit_val = 1;
+                               do_exit++;
+                       }
+                       break;
+                       }
+               case 'O': {
+                       long long t = 0;
+
+                       if (check_str_time(optarg, &t, 1)) {
+                               log_err("fio: failed parsing eta interval %s\n", optarg);
+                               exit_val = 1;
+                               do_exit++;
+                               break;
+                       }
+                       eta_interval_msec = t / 1000;
+                       if (eta_interval_msec < DISK_UTIL_MSEC) {
+                               log_err("fio: eta interval time too short (%umsec min)\n", DISK_UTIL_MSEC);
+                               exit_val = 1;
+                               do_exit++;
+                       }
                        break;
                        }
                case 'd':