Add support for other ways of triggering intermediate result outputs
authorJens Axboe <axboe@kernel.dk>
Thu, 25 Apr 2013 02:38:54 +0000 (20:38 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 25 Apr 2013 02:38:54 +0000 (20:38 -0600)
Fio has support for using the USR1 signal to dump the current
results while continuing to run. Add a --status-interval parameter
to allow this to be configured to automatically happen every X
seconds.

There's also support for signaling fio through the file system. To
do that, simply touch /tmp/fio-dump-status. When fio sees this file,
it will unlink and dump the current results.

A small tweak is needed for the file approach to work in Windows.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
HOWTO
README
backend.c
fio.h
init.c
parse.c
parse.h
stat.c
stat.h

diff --git a/HOWTO b/HOWTO
index c7d0c9e8324b646a637ee9d55e9ebd273a6119a1..64453489175aec0346e8e8f7df9422849582fc12 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -1600,6 +1600,9 @@ util=             The disk utilization. A value of 100% means we kept the disk
 
 It is also possible to get fio to dump the current output while it is
 running, without terminating the job. To do that, send fio the USR1 signal.
 
 It is also possible to get fio to dump the current output while it is
 running, without terminating the job. To do that, send fio the USR1 signal.
+You can also get regularly timed dumps by using the --status-interval
+parameter, or by creating a file in /tmp named fio-dump-status. If fio
+sees this file, it will unlink it and dump the current output status.
 
 
 7.0 Terse output
 
 
 7.0 Terse output
@@ -1721,7 +1724,7 @@ trim       trim the given file from the given 'offset' for 'length' bytes
 
 
 9.0 CPU idleness profiling
 
 
 9.0 CPU idleness profiling
-
+--------------------------
 In some cases, we want to understand CPU overhead in a test. For example,
 we test patches for the specific goodness of whether they reduce CPU usage.
 fio implements a balloon approach to create a thread per CPU that runs at
 In some cases, we want to understand CPU overhead in a test. For example,
 we test patches for the specific goodness of whether they reduce CPU usage.
 fio implements a balloon approach to create a thread per CPU that runs at
diff --git a/README b/README
index 3782570ec2de9f71475f360e571861310252657c..15a07318ca73a35879940b8e751459b5f2f2269b 100644 (file)
--- a/README
+++ b/README
@@ -155,6 +155,7 @@ $ fio
        --eta=when              When ETA estimate should be printed
                                May be "always", "never" or "auto"
        --eta-newline=time      Force a new line for every 'time' period passed
        --eta=when              When ETA estimate should be printed
                                May be "always", "never" or "auto"
        --eta-newline=time      Force a new line for every 'time' period passed
+       --status-interval=t     Force full status dump every 't' period passed
        --section=name          Only run specified section in job file.
                                Multiple sections can be specified.
        --alloc-size=kb         Set smalloc pool to this size in kb (def 1024)
        --section=name          Only run specified section in job file.
                                Multiple sections can be specified.
        --alloc-size=kb         Set smalloc pool to this size in kb (def 1024)
index f48b43dc8f58c3794003e5fd98303a9dcb26e284..4d4e8efda0601f43e5400163b56af2e16f2e4110 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1558,6 +1558,12 @@ reaped:
                fio_terminate_threads(TERMINATE_ALL);
 }
 
                fio_terminate_threads(TERMINATE_ALL);
 }
 
+static void do_usleep(unsigned int usecs)
+{
+       check_for_running_stats();
+       usleep(usecs);
+}
+
 /*
  * Main function for kicking off and reaping jobs, as needed.
  */
 /*
  * Main function for kicking off and reaping jobs, as needed.
  */
@@ -1736,7 +1742,7 @@ static void run_threads(void)
                        if (mtime_since_now(&this_start) > JOB_START_TIMEOUT)
                                break;
 
                        if (mtime_since_now(&this_start) > JOB_START_TIMEOUT)
                                break;
 
-                       usleep(100000);
+                       do_usleep(100000);
 
                        for (i = 0; i < this_jobs; i++) {
                                td = map[i];
 
                        for (i = 0; i < this_jobs; i++) {
                                td = map[i];
@@ -1788,12 +1794,12 @@ static void run_threads(void)
                reap_threads(&nr_running, &t_rate, &m_rate);
 
                if (todo)
                reap_threads(&nr_running, &t_rate, &m_rate);
 
                if (todo)
-                       usleep(100000);
+                       do_usleep(100000);
        }
 
        while (nr_running) {
                reap_threads(&nr_running, &t_rate, &m_rate);
        }
 
        while (nr_running) {
                reap_threads(&nr_running, &t_rate, &m_rate);
-               usleep(10000);
+               do_usleep(10000);
        }
 
        fio_idle_prof_stop();
        }
 
        fio_idle_prof_stop();
diff --git a/fio.h b/fio.h
index 50a868ad71704407f33a09161c1d8b3aff4a5100..ebf6309b530f3a84f6b2cda5d9a841f70fde4488 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -362,6 +362,7 @@ extern int terse_version;
 extern int is_backend;
 extern int nr_clients;
 extern int log_syslog;
 extern int is_backend;
 extern int nr_clients;
 extern int log_syslog;
+extern int status_interval;
 extern const char fio_version_string[];
 
 extern struct thread_data *threads;
 extern const char fio_version_string[];
 
 extern struct thread_data *threads;
diff --git a/init.c b/init.c
index 634dda20afd904d71b19095c2507c4b365b69cc5..ff9b6d432e585e063b82556fca88f764c8f11105 100644 (file)
--- a/init.c
+++ b/init.c
@@ -58,6 +58,7 @@ int log_syslog = 0;
 
 int write_bw_log = 0;
 int read_only = 0;
 
 int write_bw_log = 0;
 int read_only = 0;
+int status_interval = 0;
 
 static int write_lat_log;
 
 
 static int write_lat_log;
 
@@ -123,9 +124,9 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .val            = 'c' | FIO_CLIENT_FLAG,
        },
        {
                .val            = 'c' | FIO_CLIENT_FLAG,
        },
        {
-               .name              = (char *) "enghelp",
+               .name           = (char *) "enghelp",
                .has_arg        = optional_argument,
                .has_arg        = optional_argument,
-               .val                = 'i' | FIO_CLIENT_FLAG,
+               .val            = 'i' | FIO_CLIENT_FLAG,
        },
        {
                .name           = (char *) "showcmd",
        },
        {
                .name           = (char *) "showcmd",
@@ -211,6 +212,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .has_arg        = required_argument,
                .val            = 'I',
        },
                .has_arg        = required_argument,
                .val            = 'I',
        },
+       {
+               .name           = (char *) "status-interval",
+               .has_arg        = required_argument,
+               .val            = 'L',
+       },
        {
                .name           = NULL,
        },
        {
                .name           = NULL,
        },
@@ -1361,6 +1367,8 @@ static void usage(const char *name)
        printf("            \t\tMay be \"always\", \"never\" or \"auto\"\n");
        printf("  --eta-newline=time\tForce a new line for every 'time'");
        printf(" period passed\n");
        printf("            \t\tMay be \"always\", \"never\" or \"auto\"\n");
        printf("  --eta-newline=time\tForce a new line for every 'time'");
        printf(" period passed\n");
+       printf("  --status-interval=t\tForce full status dump every");
+       printf(" 't' period passed\n");
        printf("  --readonly\t\tTurn on safety read-only checks, preventing"
                " writes\n");
        printf("  --section=name\tOnly run specified section in job file\n");
        printf("  --readonly\t\tTurn on safety read-only checks, preventing"
                " writes\n");
        printf("  --section=name\tOnly run specified section in job file\n");
@@ -1789,6 +1797,18 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                        do_exit++;
                        exit_val = fio_monotonic_clocktest();
                        break;
                        do_exit++;
                        exit_val = fio_monotonic_clocktest();
                        break;
+               case 'L': {
+                       long long val;
+
+                       if (check_str_time(optarg, &val)) {
+                               log_err("fio: failed parsing time %s\n", optarg);
+                               do_exit++;
+                               exit_val = 1;
+                               break;
+                       }
+                       status_interval = val * 1000;
+                       break;
+                       }
                case '?':
                        log_err("%s: unrecognized option '%s'\n", argv[0],
                                                        argv[optind - 1]);
                case '?':
                        log_err("%s: unrecognized option '%s'\n", argv[0],
                                                        argv[optind - 1]);
diff --git a/parse.c b/parse.c
index e8b628cee7be114d2579aa5a1d2fe75515653127..63c94e3b264fabfa473087f02c9cdc48deb4b619 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -285,7 +285,7 @@ int check_str_bytes(const char *p, long long *val, void *data)
        return str_to_decimal(p, val, 1, data);
 }
 
        return str_to_decimal(p, val, 1, data);
 }
 
-static int check_str_time(const char *p, long long *val)
+int check_str_time(const char *p, long long *val)
 {
        return str_to_decimal(p, val, 0, NULL);
 }
 {
        return str_to_decimal(p, val, 0, NULL);
 }
diff --git a/parse.h b/parse.h
index b9da7b950c2813a0bb53457179b2abd7e1257ef8..cf15ce0855fbb6efff797f7ff6a6c0cb88af6056 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -89,6 +89,7 @@ extern void strip_blank_front(char **);
 extern void strip_blank_end(char *);
 extern int str_to_decimal(const char *, long long *, int, void *);
 extern int check_str_bytes(const char *p, long long *val, void *data);
 extern void strip_blank_end(char *);
 extern int str_to_decimal(const char *, long long *, int, void *);
 extern int check_str_bytes(const char *p, long long *val, void *data);
+extern int check_str_time(const char *p, long long *val);
 extern int str_to_float(const char *str, double *val);
 
 /*
 extern int str_to_float(const char *str, double *val);
 
 /*
diff --git a/stat.c b/stat.c
index 3db06125092b5fee1cbbeaa1749d839a426cab2d..7ff7ad4d8ce42fd504e394d358c7d996102ce665 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -1420,6 +1420,40 @@ void show_running_run_stats(void)
        pthread_detach(thread);
 }
 
        pthread_detach(thread);
 }
 
+static int status_interval_init;
+static struct timeval status_time;
+
+#define FIO_STATUS_FILE                "/tmp/fio-dump-status"
+
+static int check_status_file(void)
+{
+       struct stat sb;
+
+       if (stat(FIO_STATUS_FILE, &sb))
+               return 0;
+
+       unlink(FIO_STATUS_FILE);
+       return 1;
+}
+
+void check_for_running_stats(void)
+{
+       if (status_interval) {
+               if (!status_interval_init) {
+                       fio_gettime(&status_time, NULL);
+                       status_interval_init = 1;
+               } else if (mtime_since_now(&status_time) >= status_interval) {
+                       show_running_run_stats();
+                       fio_gettime(&status_time, NULL);
+                       return;
+               }
+       }
+       if (check_status_file()) {
+               show_running_run_stats();
+               return;
+       }
+}
+
 static inline void add_stat_sample(struct io_stat *is, unsigned long data)
 {
        double val = data;
 static inline void add_stat_sample(struct io_stat *is, unsigned long data)
 {
        double val = data;
diff --git a/stat.h b/stat.h
index 0125f5762329f6887ad527382139e68e40c800ee..b1bf5dc383ac0a321fe08b823b8697eec18218a6 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -205,6 +205,7 @@ extern int calc_thread_status(struct jobs_eta *je, int force);
 extern void display_thread_status(struct jobs_eta *je);
 extern void show_run_stats(void);
 extern void show_running_run_stats(void);
 extern void display_thread_status(struct jobs_eta *je);
 extern void show_run_stats(void);
 extern void show_running_run_stats(void);
+extern void check_for_running_stats(void);
 extern void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr);
 extern void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src);
 extern void init_thread_stat(struct thread_stat *ts);
 extern void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr);
 extern void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src);
 extern void init_thread_stat(struct thread_stat *ts);