From 6f8cfd22facfe73475d793aad9785162c9ad0a0f Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Tue, 9 Sep 2014 22:15:50 +0200 Subject: [PATCH] Gets speed and ETA stats using the last 100 seconds. --- HISTORY | 4 ++- cmdline/state.c | 96 ++++++++++++++++++++++++++++++++++++++----------- cmdline/state.h | 21 ++++++++--- 3 files changed, 96 insertions(+), 25 deletions(-) diff --git a/HISTORY b/HISTORY index 4be9c6c7..7be333e5 100644 --- a/HISTORY +++ b/HISTORY @@ -3,7 +3,9 @@ SnapRAID HISTORY 6.4 2014/9 ========== - * Keeps and print time spent waiting for each disk also in 'scrub'. + * Keeps and print the time spent waiting for each disk also in 'scrub'. + * The speed and ETA estimations are now based on the last 100 + seconds rather than from the start. 6.3 2014/7 ========== diff --git a/cmdline/state.c b/cmdline/state.c index 47abd3f4..8b5f06a6 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -4251,9 +4251,11 @@ int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, b now = time(0); - state->progress_start = now; - state->progress_last = now; - state->progress_subtract = 0; + state->progress_whole_start = now; + + state->progress_tick = 0; + state->progress_ptr = 0; + state->progress_wasted = 0; } /* stop if requested */ @@ -4284,7 +4286,7 @@ void state_progress_end(struct snapraid_state* state, block_off_t countpos, bloc now = time(0); - elapsed = now - state->progress_start - state->progress_subtract; + elapsed = now - state->progress_whole_start - state->progress_wasted; if (countmax) { printf("%u%% completed, %u MiB processed", countpos * 100 / countmax, countsize_MiB); @@ -4316,8 +4318,12 @@ void state_progress_restart(struct snapraid_state* state) now = time(0); + /* reset the progress counter */ + state->progress_tick = 0; + state->progress_ptr = 0; + if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */ - state->progress_subtract += now - state->progress_interruption; + state->progress_wasted += now - state->progress_interruption; } int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize) @@ -4329,19 +4335,21 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off time_t now; tommy_node* i; unsigned l; + int pred; now = time(0); - if (state->progress_last != now) { + /* previous position */ + pred = state->progress_ptr + PROGRESS_MAX - 1; + if (pred >= PROGRESS_MAX) + pred -= PROGRESS_MAX; + + /* if the previous measure is different */ + if (state->progress_tick == 0 || state->progress_time[pred] != now) { uint64_t tick_total; - time_t delta = now - state->progress_start - state->progress_subtract; printf("%u%%, %u MiB", countpos * 100 / countmax, (unsigned)(countsize / (1024*1024))); - if (delta != 0) { - printf(", %u MiB/s", (unsigned)(countsize / (1024*1024) / delta)); - } - tick_total = state->tick_cpu; for(i=state->disklist;i!=0;i=i->next) { struct snapraid_disk* disk = i->data; @@ -4349,23 +4357,71 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off } for(l=0;llevel;++l) tick_total += state->tick[l]; - if (tick_total) + if (tick_total != 0) printf(", CPU %"PRIu64"%%", state->tick_cpu * 100U / tick_total); - if (delta > 5 && countpos > 0) { - unsigned m, h; - data_off_t to_do = countmax - countpos; + /* if we have at least 5 measures */ + if (state->progress_tick >= 5) { + int oldest; + int past; + time_t delta_time; + block_off_t delta_pos; + data_off_t delta_size; - m = to_do * delta / (60 * countpos); + /* number of past measures */ + past = state->progress_tick; - h = m / 60; - m = m % 60; + /* drop the oldest ones, to promptly */ + /* skip the startup phase */ + past -= past / 5; - printf(", %u:%02u ETA%s", h, m, PROGRESS_CLEAR); + /* check how much we can go in the past */ + if (past >= PROGRESS_MAX) { + /* the vector is filled, so we are already in position */ + /* to get the possible oldest one */ + oldest = state->progress_ptr; + } else { + /* go backward the number of positions selected */ + oldest = state->progress_ptr + PROGRESS_MAX - past; + if (oldest >= PROGRESS_MAX) + oldest -= PROGRESS_MAX; + } + + delta_time = now - state->progress_time[oldest]; + delta_pos = countpos - state->progress_pos[oldest]; + delta_size = countsize - state->progress_size[oldest]; + + if (delta_time != 0) + printf(", %u MiB/s", (unsigned)(delta_size / (1024*1024) / delta_time)); + + /* estimate the remaining time */ + if (delta_pos != 0) { + unsigned m, h; + data_off_t to_do = countmax - countpos; + + m = to_do * delta_time / (60 * delta_pos); + + h = m / 60; + m = m % 60; + + printf(", %u:%02u ETA%s", h, m, PROGRESS_CLEAR); + } } printf("\r"); fflush(stdout); - state->progress_last = now; + + /* store the new measure */ + state->progress_time[state->progress_ptr] = now; + state->progress_pos[state->progress_ptr] = countpos; + state->progress_size[state->progress_ptr] = countsize; + + /* next position */ + ++state->progress_ptr; + if (state->progress_ptr >= PROGRESS_MAX) + state->progress_ptr -= PROGRESS_MAX; + + /* one more measure */ + ++state->progress_tick; } } diff --git a/cmdline/state.h b/cmdline/state.h index 88f4021d..0a3063cc 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -92,6 +92,11 @@ struct snapraid_option { int force_content_text; /**< Force the use of text version of content file. */ }; +/** + * Number of measures of the operation progress. + */ +#define PROGRESS_MAX 100 + struct snapraid_state { struct snapraid_option opt; /**< Setup options. */ int filter_hidden; /**< Filter out hidden files. */ @@ -153,10 +158,18 @@ struct snapraid_state { block_off_t loaded_paritymax; int clear_past_hash; /**< Clear all the hash from CHG and DELETED blocks when reading the state from an incomplete sync. */ - time_t progress_start; /**< Start of processing for progress visualization. */ - time_t progress_last; /**< Last update of progress visualization. */ - time_t progress_interruption; /**< Start of the measure interruption. */ - time_t progress_subtract; /**< Time to subtract for the interruptions. */ + + time_t progress_whole_start; /**< Initial start of the whole process. */ + time_t progress_interruption; /**< Time of the start of the progress interruption. */ + time_t progress_wasted; /**< Time wasted in interruptions. */ + + time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */ + block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */ + data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */ + + int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */ + int progress_tick; /**< Number of measures done. */ + int no_conf; /**< Automatically add missing info. Used to load content without a configuration file. */ };