X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=steadystate.c;h=224995d1d26899a8b4fcf4f719a66924969dbd78;hp=c7a7e4c70195ac193ce7742adab8044f9cd745b9;hb=17df7023156b50ee7288eea0f118f1ac20b21ea2;hpb=f0c50c66a602fa964b2aa2de416deb515dd39ac9 diff --git a/steadystate.c b/steadystate.c index c7a7e4c7..224995d1 100644 --- a/steadystate.c +++ b/steadystate.c @@ -10,11 +10,13 @@ static void steadystate_alloc(struct thread_data *td) { int i; - td->ss.bw_data = malloc(td->ss.dur * sizeof(unsigned long)); - td->ss.iops_data = malloc(td->ss.dur * sizeof(unsigned long)); + td->ss.bw_data = malloc(td->ss.dur * sizeof(uint64_t)); + td->ss.iops_data = malloc(td->ss.dur * sizeof(uint64_t)); /* initialize so that it is obvious if the cache is not full in the output */ for (i = 0; i < td->ss.dur; i++) td->ss.iops_data[i] = td->ss.bw_data[i] = 0; + + td->ss.state |= __FIO_SS_DATA; } void steadystate_setup(void) @@ -33,7 +35,7 @@ void steadystate_setup(void) prev_groupid = -1; prev_td = NULL; for_each_td(td, i) { - if (td->ts.ss == NULL) + if (!td->ss.dur) continue; if (!td->o.group_reporting) { @@ -43,7 +45,6 @@ void steadystate_setup(void) if (prev_groupid != td->groupid) { if (prev_td != NULL) { - prev_td->ss.last_in_group = 1; steadystate_alloc(prev_td); } prev_groupid = td->groupid; @@ -52,7 +53,6 @@ void steadystate_setup(void) } if (prev_td != NULL && prev_td->o.group_reporting) { - prev_td->ss.last_in_group = 1; steadystate_alloc(prev_td); } } @@ -68,33 +68,33 @@ static bool steadystate_slope(unsigned long iops, unsigned long bw, ss->bw_data[ss->tail] = bw; ss->iops_data[ss->tail] = iops; - if (ss->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_IOPS) new_val = iops; else new_val = bw; - 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->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_BUFFER_FULL || ss->tail - ss->head == ss->dur - 1) { + if (!(ss->state & __FIO_SS_BUFFER_FULL)) { + /* first time through */ + for(i = 0, ss->sum_y = 0; i < ss->dur; i++) { + if (ss->state & __FIO_SS_IOPS) ss->sum_y += ss->iops_data[i]; else ss->sum_y += ss->bw_data[i]; - j = ss->head + i; - if (j >= ss->dur) - j -= ss->dur; - if (ss->mode & __FIO_SS_IOPS) - ss->sum_xy += ss->iops_data[j]; + j = (ss->head + i) % ss->dur; + if (ss->state & __FIO_SS_IOPS) + ss->sum_xy += i * ss->iops_data[j]; else - ss->sum_xy += ss->bw_data[j]; + ss->sum_xy += i * ss->bw_data[j]; } + ss->state |= __FIO_SS_BUFFER_FULL; } else { /* easy to update the sums */ ss->sum_y -= ss->oldest_y; ss->sum_y += new_val; ss->sum_xy = ss->sum_xy - ss->sum_y + ss->dur * new_val; } - if (ss->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_IOPS) ss->oldest_y = ss->iops_data[ss->head]; else ss->oldest_y = ss->bw_data[ss->head]; @@ -107,7 +107,7 @@ static bool steadystate_slope(unsigned long iops, unsigned long bw, */ ss->slope = (ss->sum_xy - (double) ss->sum_x * ss->sum_y / ss->dur) / (ss->sum_x_sq - (double) ss->sum_x * ss->sum_x / ss->dur); - if (ss->pct) + if (ss->state & __FIO_SS_PCT) ss->criterion = 100.0 * ss->slope / (ss->sum_y / ss->dur); else ss->criterion = ss->slope; @@ -141,22 +141,24 @@ static bool steadystate_deviation(unsigned long iops, unsigned long bw, 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->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_BUFFER_FULL || ss->tail - ss->head == ss->dur - 1) { + if (!(ss->state & __FIO_SS_BUFFER_FULL)) { + /* first time through */ + for(i = 0, ss->sum_y = 0; i < ss->dur; i++) + if (ss->state & __FIO_SS_IOPS) ss->sum_y += ss->iops_data[i]; else ss->sum_y += ss->bw_data[i]; + ss->state |= __FIO_SS_BUFFER_FULL; } else { /* easy to update the sum */ ss->sum_y -= ss->oldest_y; - if (ss->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_IOPS) ss->sum_y += ss->iops_data[ss->tail]; else ss->sum_y += ss->bw_data[ss->tail]; } - if (ss->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_IOPS) ss->oldest_y = ss->iops_data[ss->head]; else ss->oldest_y = ss->bw_data[ss->head]; @@ -165,14 +167,14 @@ static bool steadystate_deviation(unsigned long iops, unsigned long bw, ss->deviation = 0.0; for (i = 0; i < ss->dur; i++) { - if (ss->mode & __FIO_SS_IOPS) + if (ss->state & __FIO_SS_IOPS) diff = ss->iops_data[i] - mean; else diff = ss->bw_data[i] - mean; ss->deviation = max(ss->deviation, diff * (diff < 0.0 ? -1.0 : 1.0)); } - if (ss->pct) + if (ss->state & __FIO_SS_PCT) ss->criterion = 100.0 * ss->deviation / mean; else ss->criterion = ss->deviation; @@ -209,7 +211,7 @@ void steadystate_check(void) struct steadystate_data *ss = &td->ss; if (!ss->dur || td->runstate <= TD_SETTING_UP || - td->runstate >= TD_EXITED || ss->attained) + td->runstate >= TD_EXITED || (ss->state & __FIO_SS_ATTAINED)) continue; td_iops = 0; @@ -223,13 +225,14 @@ void steadystate_check(void) prev_groupid = td->groupid; fio_gettime(&now, NULL); - if (ss->ramp_time && !ss->ramp_time_over) + if (ss->ramp_time && !(ss->state & __FIO_SS_RAMP_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; + ss->state |= __FIO_SS_RAMP_OVER; + } td_io_u_lock(td); for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) { @@ -248,7 +251,7 @@ void steadystate_check(void) * prev_iops/bw the first time through after ss->ramp_time * is done. */ - if (ss->ramp_time_over) { + if (ss->state & __FIO_SS_RAMP_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; @@ -256,7 +259,7 @@ void steadystate_check(void) ss->prev_iops = td_iops; ss->prev_bytes = td_bytes; - if (td->o.group_reporting && !ss->last_in_group) + if (td->o.group_reporting && !(ss->state & __FIO_SS_DATA)) continue; /* @@ -281,41 +284,82 @@ void steadystate_check(void) if (td->o.group_reporting) { for_each_td(td2, j) { if (td2->groupid == td->groupid) { - td2->ss.attained = 1; + td2->ss.state |= __FIO_SS_ATTAINED; fio_mark_td_terminate(td2); } } } else { - ss->attained = 1; + ss->state |= __FIO_SS_ATTAINED; fio_mark_td_terminate(td); } } } } -void td_steadystate_init(struct thread_data *td) +int td_steadystate_init(struct thread_data *td) { struct steadystate_data *ss = &td->ss; struct thread_options *o = &td->o; + struct thread_data *td2; + int j; memset(ss, 0, sizeof(*ss)); - if (!o->ss_dur) - return; + if (o->ss_dur) { + steadystate_enabled = true; + o->ss_dur /= 1000000L; + + /* put all steady state info in one place */ + ss->dur = o->ss_dur; + ss->limit = o->ss_limit.u.f; + ss->ramp_time = o->ss_ramp_time; + + ss->state = o->ss; + if (!td->ss.ramp_time) + ss->state |= __FIO_SS_RAMP_OVER; + + ss->sum_x = o->ss_dur * (o->ss_dur - 1) / 2; + ss->sum_x_sq = (o->ss_dur - 1) * (o->ss_dur) * (2*o->ss_dur - 1) / 6; + } + + /* make sure that ss options are consistent within reporting group */ + for_each_td(td2, j) { + if (td2->groupid == td->groupid) { + struct steadystate_data *ss2 = &td2->ss; + + if (ss2->dur != ss->dur || + ss2->limit != ss->limit || + ss2->ramp_time != ss->ramp_time || + ss2->state != ss->state || + ss2->sum_x != ss->sum_x || + ss2->sum_x_sq != ss->sum_x_sq) { + td_verror(td, EINVAL, "job rejected: steadystate options must be consistent within reporting groups"); + return 1; + } + } + } + + return 0; +} + +unsigned long long steadystate_bw_mean(struct thread_stat *ts) +{ + int i; + unsigned long long sum; + + for (i = 0, sum = 0; i < ts->ss_dur; i++) + sum += ts->ss_bw_data[i]; - steadystate_enabled = true; - o->ss_dur /= 1000000L; + return sum / ts->ss_dur; +} - /* put all steady state info in one place */ - ss->dur = o->ss_dur; - ss->limit = o->ss_limit.u.f; - ss->ramp_time = o->ss_ramp_time; - ss->pct = o->ss_pct; - ss->mode = o->ss; +unsigned long long steadystate_iops_mean(struct thread_stat *ts) +{ + int i; + unsigned long long sum; - ss->ramp_time_over = (td->ss.ramp_time == 0); - ss->sum_x = o->ss_dur * (o->ss_dur - 1) / 2; - ss->sum_x_sq = (o->ss_dur - 1) * (o->ss_dur) * (2*o->ss_dur - 1) / 6; + for (i = 0, sum = 0; i < ts->ss_dur; i++) + sum += ts->ss_iops_data[i]; - td->ts.ss = ss; + return sum / ts->ss_dur; }