X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=eta.c;h=aed61ecca935b1406985e9bdd64039d25a890664;hp=b0501029c2b29c2e0ea6925be1d39b66e6cd17d5;hb=263775ad3c26a76f05cdf8b204c466af09c8adda;hpb=0de5b26f6e177aacac0683306c47e0cbaf58b0b6 diff --git a/eta.c b/eta.c index b0501029..aed61ecc 100644 --- a/eta.c +++ b/eta.c @@ -6,15 +6,35 @@ #include #include "fio.h" +#include "lib/pow2.h" -static char run_str[REAL_MAX_JOBS + 1]; +static char __run_str[REAL_MAX_JOBS + 1]; +static char run_str[__THREAD_RUNSTR_SZ(REAL_MAX_JOBS)]; + +static void update_condensed_str(char *rstr, char *run_str_condensed) +{ + if (*rstr) { + while (*rstr) { + int nr = 1; + + *run_str_condensed++ = *rstr++; + while (*(rstr - 1) == *rstr) { + rstr++; + nr++; + } + run_str_condensed += sprintf(run_str_condensed, "(%u),", nr); + } + run_str_condensed--; + } + *run_str_condensed = '\0'; +} /* * Sets the status of the 'td' in the printed status map. */ static void check_str_update(struct thread_data *td) { - char c = run_str[td->thread_number - 1]; + char c = __run_str[td->thread_number - 1]; switch (td->runstate) { case TD_REAPED: @@ -74,6 +94,9 @@ static void check_str_update(struct thread_data *td) case TD_FSYNCING: c = 'F'; break; + case TD_FINISHING: + c = 'f'; + break; case TD_CREATED: c = 'C'; break; @@ -88,7 +111,8 @@ static void check_str_update(struct thread_data *td) log_err("state %d\n", td->runstate); } - run_str[td->thread_number - 1] = c; + __run_str[td->thread_number - 1] = c; + update_condensed_str(__run_str, run_str); } /* @@ -99,6 +123,11 @@ void eta_to_str(char *str, unsigned long eta_sec) unsigned int d, h, m, s; int disp_hour = 0; + if (eta_sec == -1) { + sprintf(str, "--"); + return; + } + s = eta_sec % 60; eta_sec /= 60; m = eta_sec % 60; @@ -122,7 +151,7 @@ void eta_to_str(char *str, unsigned long eta_sec) /* * Best effort calculation of the estimated pending runtime of a job. */ -static int thread_eta(struct thread_data *td) +static unsigned long thread_eta(struct thread_data *td) { unsigned long long bytes_total, bytes_done; unsigned long eta_sec = 0; @@ -134,6 +163,9 @@ static int thread_eta(struct thread_data *td) bytes_total = td->total_io_size; + if (td->flags & TD_F_NO_PROGRESS) + return -1; + if (td->o.fill_device && td->o.size == -1ULL) { if (!td->fill_device_size || td->fill_device_size == -1ULL) return 0; @@ -171,14 +203,26 @@ static int thread_eta(struct thread_data *td) double perc, perc_t; bytes_done = ddir_rw_sum(td->io_bytes); - perc = (double) bytes_done / (double) bytes_total; - if (perc > 1.0) - perc = 1.0; + + if (bytes_total) { + perc = (double) bytes_done / (double) bytes_total; + if (perc > 1.0) + perc = 1.0; + } else + perc = 0.0; if (td->o.time_based) { - perc_t = (double) elapsed / (double) timeout; - if (perc_t < perc) - perc = perc_t; + if (timeout) { + perc_t = (double) elapsed / (double) timeout; + if (perc_t < perc) + perc = perc_t; + } else { + /* + * Will never hit, we can't have time_based + * without a timeout set. + */ + perc = 0.0; + } } eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed; @@ -199,11 +243,11 @@ static int thread_eta(struct thread_data *td) * if given, otherwise assume it'll run at the specified rate. */ if (td->o.timeout) { - uint64_t timeout = td->o.timeout; + uint64_t __timeout = td->o.timeout; uint64_t start_delay = td->o.start_delay; uint64_t ramp_time = td->o.ramp_time; - t_eta = timeout + start_delay + ramp_time; + t_eta = __timeout + start_delay + ramp_time; t_eta /= 1000000ULL; if (in_ramp_time(td)) { @@ -331,7 +375,8 @@ int calc_thread_status(struct jobs_eta *je, int force) bw_avg_time = td->o.bw_avg_time; if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING || td->runstate == TD_FSYNCING - || td->runstate == TD_PRE_READING) { + || td->runstate == TD_PRE_READING + || td->runstate == TD_FINISHING) { je->nr_running++; if (td_read(td)) { je->t_rate[0] += td->o.rate[DDIR_READ]; @@ -356,10 +401,9 @@ int calc_thread_status(struct jobs_eta *je, int force) } else if (td->runstate == TD_RAMP) { je->nr_running++; je->nr_ramp++; - } else if (td->runstate == TD_SETTING_UP) { - je->nr_running++; + } else if (td->runstate == TD_SETTING_UP) je->nr_setting_up++; - } else if (td->runstate < TD_RUNNING) + else if (td->runstate < TD_RUNNING) je->nr_pending++; if (je->elapsed_sec >= 3) @@ -430,7 +474,8 @@ int calc_thread_status(struct jobs_eta *je, int force) return 0; je->nr_threads = thread_number; - memcpy(je->run_str, run_str, thread_number * sizeof(char)); + update_condensed_str(__run_str, run_str); + memcpy(je->run_str, run_str, strlen(run_str)); return 1; } @@ -476,7 +521,8 @@ void display_thread_status(struct jobs_eta *je) int l; int ddir; - if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running) + if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running || + je->eta_sec == -1) strcpy(perc_str, "-.-% done"); else { double mult = 100.0; @@ -519,8 +565,7 @@ void display_thread_status(struct jobs_eta *je) if (!eta_new_line_init) { fio_gettime(&disp_eta_new_line, NULL); eta_new_line_init = 1; - } else if (eta_new_line && - mtime_since_now(&disp_eta_new_line) > eta_new_line * 1000) { + } else if (eta_new_line && mtime_since_now(&disp_eta_new_line) > eta_new_line) { fio_gettime(&disp_eta_new_line, NULL); eta_new_line_pending = 1; } @@ -528,19 +573,35 @@ void display_thread_status(struct jobs_eta *je) fflush(stdout); } -void print_thread_status(void) +struct jobs_eta *get_jobs_eta(int force, size_t *size) { struct jobs_eta *je; - size_t size; if (!thread_number) - return; + return NULL; + + *size = sizeof(*je) + THREAD_RUNSTR_SZ; + je = malloc(*size); + if (!je) + return NULL; + memset(je, 0, *size); + + if (!calc_thread_status(je, force)) { + free(je); + return NULL; + } + + *size = sizeof(*je) + strlen((char *) je->run_str) + 1; + return je; +} - size = sizeof(*je) + thread_number * sizeof(char) + 1; - je = malloc(size); - memset(je, 0, size); +void print_thread_status(void) +{ + struct jobs_eta *je; + size_t size; - if (calc_thread_status(je, 0)) + je = get_jobs_eta(0, &size); + if (je) display_thread_status(je); free(je); @@ -548,5 +609,6 @@ void print_thread_status(void) void print_status_init(int thr_number) { - run_str[thr_number] = 'P'; + __run_str[thr_number] = 'P'; + update_condensed_str(__run_str, run_str); }