From 4cd5b75b028aa9f91c303c947c839eb59d5b762d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 13 Aug 2016 08:39:57 -0600 Subject: [PATCH] steadystate: cleanups - Make this more localized - Get rid of ->evaluate() pointer, towards making the steadystate_data appropriate for wire transfer. - Move more things to steadystate.[ch] Signed-off-by: Jens Axboe --- fio.h | 8 -- init.c | 12 +-- steadystate.c | 213 ++++++++++++++++++++++++++------------------------ steadystate.h | 26 +++++- 4 files changed, 136 insertions(+), 123 deletions(-) diff --git a/fio.h b/fio.h index 4ab056aa..d099da82 100644 --- a/fio.h +++ b/fio.h @@ -791,14 +791,6 @@ enum { FIO_CPUS_SPLIT, }; -enum { - FIO_STEADYSTATE_IOPS = 0, - FIO_STEADYSTATE_IOPS_SLOPE, - FIO_STEADYSTATE_BW, - FIO_STEADYSTATE_BW_SLOPE, -}; - - extern void exec_trigger(const char *); extern void check_trigger_file(void); diff --git a/init.c b/init.c index e9bf3a2b..91138650 100644 --- a/init.c +++ b/init.c @@ -81,8 +81,6 @@ unsigned int *fio_debug_jobp = NULL; static char cmd_optstr[256]; static int did_arg; -bool steadystate = false; - #define FIO_CLIENT_FLAG (1 << 16) /* @@ -1590,13 +1588,10 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, td->ss.ramp_time = o->ss_ramp_time; td->ss.pct = o->ss_pct; - if (o->ss == FIO_STEADYSTATE_IOPS_SLOPE || o->ss == FIO_STEADYSTATE_BW_SLOPE) { + if (steadystate_check_slope(o)) td->ss.check_slope = true; - td->ss.evaluate = &steadystate_slope; - } else { + else td->ss.check_slope = false; - td->ss.evaluate = &steadystate_deviation; - } if (o->ss == FIO_STEADYSTATE_IOPS || o->ss == FIO_STEADYSTATE_IOPS_SLOPE) td->ss.check_iops = true; @@ -1620,8 +1615,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, td->ss.slope = 0.0; td->ss.deviation = 0.0; td->ts.ss = &td->ss; - } - else + } else td->ts.ss = NULL; /* diff --git a/steadystate.c b/steadystate.c index 85e259a0..6cd7c13f 100644 --- a/steadystate.c +++ b/steadystate.c @@ -4,7 +4,9 @@ #include "steadystate.h" #include "helper_thread.h" -void steadystate_setup() +bool steadystate = false; + +void steadystate_setup(void) { int i, prev_groupid; struct thread_data *td, *prev_td; @@ -55,95 +57,8 @@ void steadystate_alloc(struct thread_data *td) td->ss.iops_data[i] = td->ss.bw_data[i] = 0; } -void steadystate_check() -{ - int i, j, ddir, prev_groupid, group_ramp_time_over = 0; - unsigned long rate_time; - struct thread_data *td, *td2; - struct timeval now; - unsigned long group_bw = 0, group_iops = 0; - unsigned long long td_iops; - unsigned long long td_bytes; - - prev_groupid = -1; - for_each_td(td, i) { - struct steadystate_data *ss = &td->ss; - - if (!ss->dur || td->runstate <= TD_SETTING_UP || td->runstate >= TD_EXITED || ss->attained) - continue; - - td_iops = 0; - td_bytes = 0; - if (!td->o.group_reporting || - (td->o.group_reporting && td->groupid != prev_groupid)) { - group_bw = 0; - group_iops = 0; - group_ramp_time_over = 0; - } - prev_groupid = td->groupid; - - fio_gettime(&now, NULL); - if (ss->ramp_time && !ss->ramp_time_over) - /* - * Begin recording data one second after ss->ramp_time - * has elapsed - */ - if (utime_since(&td->epoch, &now) >= (ss->ramp_time + 1000000L)) - ss->ramp_time_over = 1; - - td_io_u_lock(td); - for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) { - td_iops += td->io_blocks[ddir]; - td_bytes += td->io_bytes[ddir]; - } - td_io_u_unlock(td); - - rate_time = mtime_since(&ss->prev_time, &now); - memcpy(&ss->prev_time, &now, sizeof(now)); - - /* - * Begin monitoring when job starts but don't actually use - * data in checking stopping criterion until ss->ramp_time is - * over. This ensures that we will have a sane value in - * prev_iops/bw the first time through after ss->ramp_time - * is done. - */ - if (ss->ramp_time_over) { - group_bw += 1000 * (td_bytes - ss->prev_bytes) / rate_time; - group_iops += 1000 * (td_iops - ss->prev_iops) / rate_time; - ++group_ramp_time_over; - } - ss->prev_iops = td_iops; - ss->prev_bytes = td_bytes; - - if (td->o.group_reporting && !ss->last_in_group) - continue; - - /* don't begin checking criterion until ss->ramp_time is over for at least one thread in group */ - if (!group_ramp_time_over) - continue; - - dprint(FD_STEADYSTATE, "steadystate_check() thread: %d, groupid: %u, rate_msec: %ld, iops: %lu, bw: %lu, head: %d, tail: %d\n", - i, td->groupid, rate_time, group_iops, group_bw, ss->head, ss->tail); - - if (ss->evaluate(group_iops, group_bw, td)) - { - if (td->o.group_reporting) - for_each_td(td2, j) { - if (td2->groupid == td->groupid) { - td2->ss.attained = 1; - fio_mark_td_terminate(td2); - } - } - else { - ss->attained = 1; - fio_mark_td_terminate(td); - } - } - } -} - -bool steadystate_slope(unsigned long iops, unsigned long bw, struct thread_data *td) +static bool steadystate_slope(unsigned long iops, unsigned long bw, + struct thread_data *td) { int i, j; double result; @@ -153,12 +68,9 @@ bool steadystate_slope(unsigned long iops, unsigned long bw, struct thread_data ss->bw_data[ss->tail] = bw; ss->iops_data[ss->tail] = iops; - if (ss->tail < ss->head || (ss->tail - ss->head == ss->dur - 1)) - { - if (ss->sum_y == 0) /* first time through */ - { - for(i = 0; i < ss->dur; i++) - { + if (ss->tail < ss->head || (ss->tail - ss->head == ss->dur - 1)) { + if (ss->sum_y == 0) { /* first time through */ + for(i = 0; i < ss->dur; i++) { ss->sum_y += ss->check_iops ? ss->iops_data[i] : ss->bw_data[i]; j = ss->head + i; if (j >= ss->dur) @@ -193,10 +105,12 @@ bool steadystate_slope(unsigned long iops, unsigned long bw, struct thread_data ss->tail = (ss->tail + 1) % ss->dur; if (ss->tail <= ss->head) ss->head = (ss->head + 1) % ss->dur; + return false; } -bool steadystate_deviation(unsigned long iops, unsigned long bw, struct thread_data *td) +static bool steadystate_deviation(unsigned long iops, unsigned long bw, + struct thread_data *td) { int i; double diff; @@ -207,10 +121,8 @@ bool steadystate_deviation(unsigned long iops, unsigned long bw, struct thread_d ss->bw_data[ss->tail] = bw; ss->iops_data[ss->tail] = iops; - if (ss->tail < ss->head || (ss->tail - ss->head == ss->dur - 1)) - { - if (ss->sum_y == 0) /* first time through */ - { + if (ss->tail < ss->head || (ss->tail - ss->head == ss->dur - 1)) { + if (ss->sum_y == 0) { /* first time through */ for(i = 0; i < ss->dur; i++) ss->sum_y += ss->check_iops ? ss->iops_data[i] : ss->bw_data[i]; } else { /* easy to update the sum */ @@ -222,8 +134,7 @@ bool steadystate_deviation(unsigned long iops, unsigned long bw, struct thread_d mean = (double) ss->sum_y / ss->dur; ss->deviation = 0.0; - for (i = 0; i < ss->dur; i++) - { + for (i = 0; i < ss->dur; i++) { diff = (double) (ss->check_iops ? ss->iops_data[i] : ss->bw_data[i]) - mean; ss->deviation = max(ss->deviation, diff * (diff < 0.0 ? -1.0 : 1.0)); } @@ -239,5 +150,101 @@ bool steadystate_deviation(unsigned long iops, unsigned long bw, struct thread_d ss->tail = (ss->tail + 1) % ss->dur; if (ss->tail <= ss->head) ss->head = (ss->head + 1) % ss->dur; + return false; } + +void steadystate_check(void) +{ + int i, j, ddir, prev_groupid, group_ramp_time_over = 0; + unsigned long rate_time; + struct thread_data *td, *td2; + struct timeval now; + unsigned long group_bw = 0, group_iops = 0; + unsigned long long td_iops; + unsigned long long td_bytes; + bool ret; + + prev_groupid = -1; + for_each_td(td, i) { + struct steadystate_data *ss = &td->ss; + + if (!ss->dur || td->runstate <= TD_SETTING_UP || td->runstate >= TD_EXITED || ss->attained) + continue; + + td_iops = 0; + td_bytes = 0; + if (!td->o.group_reporting || + (td->o.group_reporting && td->groupid != prev_groupid)) { + group_bw = 0; + group_iops = 0; + group_ramp_time_over = 0; + } + prev_groupid = td->groupid; + + fio_gettime(&now, NULL); + if (ss->ramp_time && !ss->ramp_time_over) + /* + * Begin recording data one second after ss->ramp_time + * has elapsed + */ + if (utime_since(&td->epoch, &now) >= (ss->ramp_time + 1000000L)) + ss->ramp_time_over = 1; + + td_io_u_lock(td); + for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) { + td_iops += td->io_blocks[ddir]; + td_bytes += td->io_bytes[ddir]; + } + td_io_u_unlock(td); + + rate_time = mtime_since(&ss->prev_time, &now); + memcpy(&ss->prev_time, &now, sizeof(now)); + + /* + * Begin monitoring when job starts but don't actually use + * data in checking stopping criterion until ss->ramp_time is + * over. This ensures that we will have a sane value in + * prev_iops/bw the first time through after ss->ramp_time + * is done. + */ + if (ss->ramp_time_over) { + group_bw += 1000 * (td_bytes - ss->prev_bytes) / rate_time; + group_iops += 1000 * (td_iops - ss->prev_iops) / rate_time; + ++group_ramp_time_over; + } + ss->prev_iops = td_iops; + ss->prev_bytes = td_bytes; + + if (td->o.group_reporting && !ss->last_in_group) + continue; + + /* don't begin checking criterion until ss->ramp_time is over for at least one thread in group */ + if (!group_ramp_time_over) + continue; + + dprint(FD_STEADYSTATE, "steadystate_check() thread: %d, groupid: %u, rate_msec: %ld, iops: %lu, bw: %lu, head: %d, tail: %d\n", + i, td->groupid, rate_time, group_iops, group_bw, ss->head, ss->tail); + + if (steadystate_check_slope(&td->o)) + ret = steadystate_slope(group_iops, group_bw, td); + else + ret = steadystate_deviation(group_iops, group_bw, td); + + if (ret) { + if (td->o.group_reporting) { + for_each_td(td2, j) { + if (td2->groupid == td->groupid) { + td2->ss.attained = 1; + fio_mark_td_terminate(td2); + } + } + } else { + ss->attained = 1; + fio_mark_td_terminate(td); + } + } + } +} + + diff --git a/steadystate.h b/steadystate.h index 6cd29409..aa31112b 100644 --- a/steadystate.h +++ b/steadystate.h @@ -1,11 +1,13 @@ #ifndef FIO_STEADYSTATE_H #define FIO_STEADYSTATE_H +#include "thread_options.h" + extern void steadystate_check(void); extern void steadystate_setup(void); extern void steadystate_alloc(struct thread_data *); -extern bool steadystate_deviation(unsigned long, unsigned long, struct thread_data *); -extern bool steadystate_slope(unsigned long, unsigned long, struct thread_data *); + +extern bool steadystate; /* * For steady state detection @@ -14,7 +16,6 @@ struct steadystate_data { double limit; unsigned long long dur; unsigned long long ramp_time; - bool (*evaluate)(unsigned long, unsigned long, struct thread_data *); bool check_iops; bool check_slope; bool pct; @@ -43,4 +44,23 @@ struct steadystate_data { unsigned long long prev_bytes; }; +enum { + FIO_STEADYSTATE_IOPS = 0, + FIO_STEADYSTATE_IOPS_SLOPE, + FIO_STEADYSTATE_BW, + FIO_STEADYSTATE_BW_SLOPE, +}; + +static inline bool steadystate_check_slope(struct thread_options *o) +{ + return o->ss == FIO_STEADYSTATE_IOPS_SLOPE || + o->ss == FIO_STEADYSTATE_BW_SLOPE; +} + +static inline bool steadystate_check_iops(struct thread_options *o) +{ + return o->ss == FIO_STEADYSTATE_IOPS || + o->ss == FIO_STEADYSTATE_IOPS_SLOPE; +} + #endif -- 2.25.1