From 06464907159baf7a1eeac654a023743e33f28d86 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Apr 2013 20:38:54 -0600 Subject: [PATCH] Add support for other ways of triggering intermediate result outputs 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 --- HOWTO | 5 ++++- README | 1 + backend.c | 12 +++++++++--- fio.h | 1 + init.c | 24 ++++++++++++++++++++++-- parse.c | 2 +- parse.h | 1 + stat.c | 34 ++++++++++++++++++++++++++++++++++ stat.h | 1 + 9 files changed, 74 insertions(+), 7 deletions(-) diff --git a/HOWTO b/HOWTO index c7d0c9e8..64453489 100644 --- 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. +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 @@ -1721,7 +1724,7 @@ trim trim the given file from the given 'offset' for 'length' bytes 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 diff --git a/README b/README index 3782570e..15a07318 100644 --- 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 + --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) diff --git a/backend.c b/backend.c index f48b43dc..4d4e8efd 100644 --- a/backend.c +++ b/backend.c @@ -1558,6 +1558,12 @@ reaped: 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. */ @@ -1736,7 +1742,7 @@ static void run_threads(void) 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]; @@ -1788,12 +1794,12 @@ static void run_threads(void) 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); - usleep(10000); + do_usleep(10000); } fio_idle_prof_stop(); diff --git a/fio.h b/fio.h index 50a868ad..ebf6309b 100644 --- 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 status_interval; extern const char fio_version_string[]; extern struct thread_data *threads; diff --git a/init.c b/init.c index 634dda20..ff9b6d43 100644 --- a/init.c +++ b/init.c @@ -58,6 +58,7 @@ int log_syslog = 0; int write_bw_log = 0; int read_only = 0; +int status_interval = 0; static int write_lat_log; @@ -123,9 +124,9 @@ static struct option l_opts[FIO_NR_OPTIONS] = { .val = 'c' | FIO_CLIENT_FLAG, }, { - .name = (char *) "enghelp", + .name = (char *) "enghelp", .has_arg = optional_argument, - .val = 'i' | FIO_CLIENT_FLAG, + .val = 'i' | FIO_CLIENT_FLAG, }, { .name = (char *) "showcmd", @@ -211,6 +212,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = { .has_arg = required_argument, .val = 'I', }, + { + .name = (char *) "status-interval", + .has_arg = required_argument, + .val = 'L', + }, { .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(" --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"); @@ -1789,6 +1797,18 @@ int parse_cmd_line(int argc, char *argv[], int client_type) 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]); diff --git a/parse.c b/parse.c index e8b628ce..63c94e3b 100644 --- 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); } -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); } diff --git a/parse.h b/parse.h index b9da7b95..cf15ce08 100644 --- 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 int check_str_time(const char *p, long long *val); extern int str_to_float(const char *str, double *val); /* diff --git a/stat.c b/stat.c index 3db06125..7ff7ad4d 100644 --- a/stat.c +++ b/stat.c @@ -1420,6 +1420,40 @@ void show_running_run_stats(void) 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; diff --git a/stat.h b/stat.h index 0125f576..b1bf5dc3 100644 --- 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 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); -- 2.25.1