fio: allow milliseconds on all time specifiers
authorChristian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
Thu, 20 Feb 2014 13:20:01 +0000 (14:20 +0100)
committerJens Axboe <axboe@fb.com>
Thu, 20 Feb 2014 17:10:45 +0000 (09:10 -0800)
This patch allows all time specifiers to be specified down to
milliseconds.  Default will stay seconds for compatibility with old
configs.

It also adds documentation to the existing time units day, hour and
minute.

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
backend.c
eta.c
fio.1
parse.c
time.c

index 32bc2652bd0ba93793c9b12cc27ca8b4cf81aef0..b92877efd1ca8a167555cd753387df6eaf39fbc5 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -346,7 +346,7 @@ static inline int runtime_exceeded(struct thread_data *td, struct timeval *t)
                return 0;
        if (!td->o.timeout)
                return 0;
-       if (mtime_since(&td->epoch, t) >= td->o.timeout * 1000)
+       if (mtime_since(&td->epoch, t) >= td->o.timeout )
                return 1;
 
        return 0;
@@ -1783,7 +1783,7 @@ static void run_threads(void)
                        if (td->o.start_delay) {
                                spent = mtime_since_genesis();
 
-                               if (td->o.start_delay * 1000 > spent)
+                               if (td->o.start_delay > spent)
                                        continue;
                        }
 
diff --git a/eta.c b/eta.c
index 9fc6e279180a82b817552222afcdae57055af85c..e12e4fc3fe4703b5a347d743e8eccbeebdf6a6db 100644 (file)
--- a/eta.c
+++ b/eta.c
@@ -174,7 +174,8 @@ static int thread_eta(struct thread_data *td)
                        perc = 1.0;
 
                if (td->o.time_based) {
-                       perc_t = (double) elapsed / (double) td->o.timeout;
+                       perc_t = (double) elapsed /
+                                       (double) (td->o.timeout / 1000);
                        if (perc_t < perc)
                                perc = perc_t;
                }
@@ -182,8 +183,9 @@ static int thread_eta(struct thread_data *td)
                eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed;
 
                if (td->o.timeout &&
-                   eta_sec > (td->o.timeout + done_secs - elapsed))
-                       eta_sec = td->o.timeout + done_secs - elapsed;
+                   eta_sec > ( (td->o.timeout / 1000) + done_secs - elapsed))
+                       eta_sec = (td->o.timeout / 1000)  + done_secs
+                                       - elapsed;
        } else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED
                        || td->runstate == TD_INITIALIZED
                        || td->runstate == TD_SETTING_UP
@@ -197,8 +199,8 @@ static int thread_eta(struct thread_data *td)
                 * if given, otherwise assume it'll run at the specified rate.
                 */
                if (td->o.timeout) {
-                       t_eta = td->o.timeout + td->o.start_delay +
-                                       td->o.ramp_time;
+                       t_eta = (td->o.timeout + td->o.start_delay  +
+                                       td->o.ramp_time ) / 1000;
 
                        if (in_ramp_time(td)) {
                                unsigned long ramp_left;
@@ -212,7 +214,7 @@ static int thread_eta(struct thread_data *td)
                rate_bytes = ddir_rw_sum(td->o.rate);
                if (rate_bytes) {
                        r_eta = (bytes_total / 1024) / rate_bytes;
-                       r_eta += td->o.start_delay;
+                       r_eta += td->o.start_delay / 1000;
                }
 
                if (r_eta && t_eta)
diff --git a/fio.1 b/fio.1
index aadb5ce2bc84bc2a1f0c761c1e8336d68e506e11..a16d0398b2bc4c59a583dd805cacf6ba40b5aa03 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -121,12 +121,16 @@ String: a sequence of alphanumeric characters.
 SI integer: a whole number, possibly containing a suffix denoting the base unit
 of the value.  Accepted suffixes are `k', 'M', 'G', 'T', and 'P', denoting
 kilo (1024), mega (1024^2), giga (1024^3), tera (1024^4), and peta (1024^5)
-respectively. The suffix is not case sensitive. If prefixed with '0x', the
-value is assumed to be base 16 (hexadecimal). A suffix may include a trailing 'b',
-for instance 'kb' is identical to 'k'. You can specify a base 10 value
-by using 'KiB', 'MiB', 'GiB', etc. This is useful for disk drives where
-values are often given in base 10 values. Specifying '30GiB' will get you
-30*1000^3 bytes.
+respectively. If prefixed with '0x', the value is assumed to be base 16
+(hexadecimal). A suffix may include a trailing 'b', for instance 'kb' is
+identical to 'k'. You can specify a base 10 value by using 'KiB', 'MiB','GiB',
+etc. This is useful for disk drives where values are often given in base 10
+values. Specifying '30GiB' will get you 30*1000^3 bytes.
+When specifying times the default suffix meaning changes, still denoting the
+base unit of the value, but accepted suffixes are 'D' (days), 'H' (hours), 'M'
+(minutes), 'S' Seconds, 'ms' milli seconds. Time values without a unit specify
+seconds.
+The suffixes are not case sensitive.
 .TP
 .I bool
 Boolean: a true or false value. `0' denotes false, `1' denotes true.
diff --git a/parse.c b/parse.c
index e46fc14ef236e8bb59dac9fb448f2d22b92d4e92..c8bae0335a4e90365022e946d24136b1a1cc501b 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -122,21 +122,41 @@ static void show_option_help(struct fio_option *o, int is_err)
        show_option_values(o);
 }
 
-static unsigned long get_mult_time(char c)
+static unsigned long long get_mult_time(const char *str, int len)
 {
-       switch (c) {
-       case 'm':
-       case 'M':
-               return 60;
-       case 'h':
-       case 'H':
-               return 60 * 60;
-       case 'd':
-       case 'D':
-               return 24 * 60 * 60;
-       default:
-               return 1;
+       const char *p = str;
+       char *c;
+       unsigned long long mult = 1000;
+
+       /*
+         * Go forward until we hit a non-digit, or +/- sign
+         */
+       while ((p - str) <= len) {
+               if (!isdigit((int) *p) && (*p != '+') && (*p != '-'))
+                       break;
+               p++;
        }
+
+       if (!isalpha((int) *p))
+               return 1000;
+
+       c = strdup(p);
+       for (int i = 0; i < strlen(c); i++)
+               c[i] = tolower(c[i]);
+
+       if (!strncmp("ms", c, 2))
+               mult = 1;
+       else if (!strcmp("s", c))
+               mult = 1000;
+       else if (!strcmp("m", c))
+               mult = 60 * 1000;
+       else if (!strcmp("h", c))
+               mult = 60 * 60 * 1000;
+       else if (!strcmp("d", c))
+               mult = 24 * 60 * 60 * 1000;
+
+       free(c);
+       return mult;
 }
 
 static int is_separator(char c)
@@ -275,7 +295,7 @@ int str_to_decimal(const char *str, long long *val, int kilo, void *data)
                else
                        *val *= mult;
        } else
-               *val *= get_mult_time(str[len - 1]);
+               *val *= get_mult_time(str, len);
 
        return 0;
 }
diff --git a/time.c b/time.c
index 17f9f6fcd187b69feda17140ba62928d7a8f4914..b374d3e71eb976715a4ae86bd998f48108aec18d 100644 (file)
--- a/time.c
+++ b/time.c
@@ -71,7 +71,7 @@ int ramp_time_over(struct thread_data *td)
                return 1;
 
        fio_gettime(&tv, NULL);
-       if (mtime_since(&td->epoch, &tv) >= td->o.ramp_time * 1000) {
+       if (mtime_since(&td->epoch, &tv) >= td->o.ramp_time ) {
                td->ramp_time_over = 1;
                reset_all_stats(td);
                td_set_runstate(td, TD_RAMP);