X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=stat.c;h=bc01b5192f31a25299591b5a66dd4c0a6d3ce242;hb=e7f5de90cbc0b51d4300a9fc0d080275b2730a32;hp=7ff7ad4d8ce42fd504e394d358c7d996102ce665;hpb=06464907159baf7a1eeac654a023743e33f28d86;p=fio.git diff --git a/stat.c b/stat.c index 7ff7ad4d..bc01b519 100644 --- a/stat.c +++ b/stat.c @@ -14,6 +14,8 @@ #include "lib/getrusage.h" #include "idletime.h" +static struct fio_mutex *stat_mutex; + void update_rusage_stat(struct thread_data *td) { struct thread_stat *ts = &td->ts; @@ -241,15 +243,13 @@ out: int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max, double *mean, double *dev) { - double n = is->samples; + double n = (double) is->samples; - if (is->samples == 0) + if (n == 0) return 0; *min = is->min_val; *max = is->max_val; - - n = (double) is->samples; *mean = is->mean.u.f; if (n > 1.0) @@ -497,7 +497,7 @@ static void show_latencies(struct thread_stat *ts) show_lat_m(io_u_lat_m); } -void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs) +void show_thread_status_normal(struct thread_stat *ts, struct group_run_stats *rs) { double usr_cpu, sys_cpu; unsigned long runtime; @@ -586,6 +586,13 @@ void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs) ts->first_error, strerror(ts->first_error)); } + if (ts->latency_depth) { + log_info(" latency : target=%llu, window=%llu, percentile=%.2f%%, depth=%u\n", + (unsigned long long)ts->latency_target, + (unsigned long long)ts->latency_window, + ts->latency_percentile.u.f, + ts->latency_depth); + } } static void show_ddir_status_terse(struct thread_stat *ts, @@ -883,7 +890,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts, log_info(";%3.2f%%", io_u_lat_m[i]); /* disk util stats, if any */ - show_disk_util(1, NULL); + if (is_backend) + show_disk_util(1, NULL); /* Additional output if continue_on_error set - default off*/ if (ts->continue_on_error) @@ -970,7 +978,14 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts, /* Additional output if continue_on_error set - default off*/ if (ts->continue_on_error) { json_object_add_value_int(root, "total_err", ts->total_err_count); - json_object_add_value_int(root, "total_err", ts->first_error); + json_object_add_value_int(root, "first_error", ts->first_error); + } + + if (ts->latency_depth) { + json_object_add_value_int(root, "latency_depth", ts->latency_depth); + json_object_add_value_int(root, "latency_target", ts->latency_target); + json_object_add_value_float(root, "latency_percentile", ts->latency_percentile.u.f); + json_object_add_value_int(root, "latency_window", ts->latency_window); } /* Additional output if description is set */ @@ -991,6 +1006,18 @@ static void show_thread_status_terse(struct thread_stat *ts, log_err("fio: bad terse version!? %d\n", terse_version); } +struct json_object *show_thread_status(struct thread_stat *ts, + struct group_run_stats *rs) +{ + if (output_format == FIO_OUTPUT_TERSE) + show_thread_status_terse(ts, rs); + else if (output_format == FIO_OUTPUT_JSON) + return(show_thread_status_json(ts, rs)); + else + show_thread_status_normal(ts, rs); + return NULL; +} + static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr) { double mean, S; @@ -1141,7 +1168,7 @@ void init_thread_stat(struct thread_stat *ts) ts->groupid = -1; } -void show_run_stats(void) +static void __show_run_stats(void) { struct group_run_stats *runstats, *rs; struct thread_data *td; @@ -1251,6 +1278,11 @@ void show_run_stats(void) } } + ts->latency_depth = td->latency_qd; + ts->latency_target = td->o.latency_target; + ts->latency_percentile = td->o.latency_percentile; + ts->latency_window = td->o.latency_window; + sum_thread_stats(ts, &td->ts, idx); } @@ -1324,7 +1356,7 @@ void show_run_stats(void) struct json_object *tmp = show_thread_status_json(ts, rs); json_array_add_value_object(array, tmp); } else - show_thread_status(ts, rs); + show_thread_status_normal(ts, rs); } if (output_format == FIO_OUTPUT_JSON) { /* disk util stats, if any */ @@ -1354,10 +1386,28 @@ void show_run_stats(void) show_idle_prof_stats(FIO_OUTPUT_NORMAL, NULL); } + if ( !(output_format == FIO_OUTPUT_TERSE) && append_terse_output) { + log_info("\nAdditional Terse Output:\n"); + + for (i = 0; i < nr_ts; i++) { + ts = &threadstats[i]; + rs = &runstats[ts->groupid]; + show_thread_status_terse(ts, rs); + } + } + + log_info_flush(); free(runstats); free(threadstats); } +void show_run_stats(void) +{ + fio_mutex_down(stat_mutex); + __show_run_stats(); + fio_mutex_up(stat_mutex); +} + static void *__show_running_run_stats(void fio_unused *arg) { struct thread_data *td; @@ -1392,7 +1442,7 @@ static void *__show_running_run_stats(void fio_unused *arg) td->update_rusage = 0; } - show_run_stats(); + __show_run_stats(); for_each_td(td, i) { if (td_read(td) && td->io_bytes[DDIR_READ]) @@ -1404,6 +1454,7 @@ static void *__show_running_run_stats(void fio_unused *arg) } free(rt); + fio_mutex_up(stat_mutex); return NULL; } @@ -1416,8 +1467,14 @@ void show_running_run_stats(void) { pthread_t thread; - pthread_create(&thread, NULL, __show_running_run_stats, NULL); - pthread_detach(thread); + fio_mutex_down(stat_mutex); + + if (!pthread_create(&thread, NULL, __show_running_run_stats, NULL)) { + pthread_detach(thread); + return; + } + + fio_mutex_up(stat_mutex); } static int status_interval_init; @@ -1428,11 +1485,21 @@ static struct timeval status_time; static int check_status_file(void) { struct stat sb; + const char *temp_dir; + char fio_status_file_path[PATH_MAX]; - if (stat(FIO_STATUS_FILE, &sb)) + temp_dir = getenv("TMPDIR"); + if (temp_dir == NULL) + temp_dir = getenv("TEMP"); + if (temp_dir == NULL) + temp_dir = "/tmp"; + + snprintf(fio_status_file_path, sizeof(fio_status_file_path), "%s/%s", temp_dir, FIO_STATUS_FILE); + + if (stat(fio_status_file_path, &sb)) return 0; - unlink(FIO_STATUS_FILE); + unlink(fio_status_file_path); return 1; } @@ -1479,13 +1546,23 @@ static void __add_log_sample(struct io_log *iolog, unsigned long val, { const int nr_samples = iolog->nr_samples; + if (iolog->disabled) + return; + if (!iolog->nr_samples) iolog->avg_last = t; if (iolog->nr_samples == iolog->max_samples) { int new_size = sizeof(struct io_sample) * iolog->max_samples*2; + void *new_log; - iolog->log = realloc(iolog->log, new_size); + new_log = realloc(iolog->log, new_size); + if (!new_log) { + log_err("fio: failed extending iolog! Will stop logging.\n"); + iolog->disabled = 1; + return; + } + iolog->log = new_log; iolog->max_samples <<= 1; } @@ -1502,6 +1579,37 @@ static inline void reset_io_stat(struct io_stat *ios) ios->mean.u.f = ios->S.u.f = 0; } +static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed) +{ + /* + * Note an entry in the log. Use the mean from the logged samples, + * making sure to properly round up. Only write a log entry if we + * had actual samples done. + */ + if (iolog->avg_window[DDIR_READ].samples) { + unsigned long mr; + + mr = iolog->avg_window[DDIR_READ].mean.u.f + 0.50; + __add_log_sample(iolog, mr, DDIR_READ, 0, elapsed); + } + if (iolog->avg_window[DDIR_WRITE].samples) { + unsigned long mw; + + mw = iolog->avg_window[DDIR_WRITE].mean.u.f + 0.50; + __add_log_sample(iolog, mw, DDIR_WRITE, 0, elapsed); + } + if (iolog->avg_window[DDIR_TRIM].samples) { + unsigned long mw; + + mw = iolog->avg_window[DDIR_TRIM].mean.u.f + 0.50; + __add_log_sample(iolog, mw, DDIR_TRIM, 0, elapsed); + } + + reset_io_stat(&iolog->avg_window[DDIR_READ]); + reset_io_stat(&iolog->avg_window[DDIR_WRITE]); + reset_io_stat(&iolog->avg_window[DDIR_TRIM]); +} + static void add_log_sample(struct thread_data *td, struct io_log *iolog, unsigned long val, enum fio_ddir ddir, unsigned int bs) @@ -1535,35 +1643,27 @@ static void add_log_sample(struct thread_data *td, struct io_log *iolog, if (this_window < iolog->avg_msec) return; - /* - * Note an entry in the log. Use the mean from the logged samples, - * making sure to properly round up. Only write a log entry if we - * had actual samples done. - */ - if (iolog->avg_window[DDIR_READ].samples) { - unsigned long mr; - - mr = iolog->avg_window[DDIR_READ].mean.u.f + 0.50; - __add_log_sample(iolog, mr, DDIR_READ, 0, elapsed); - } - if (iolog->avg_window[DDIR_WRITE].samples) { - unsigned long mw; + _add_stat_to_log(iolog, elapsed); - mw = iolog->avg_window[DDIR_WRITE].mean.u.f + 0.50; - __add_log_sample(iolog, mw, DDIR_WRITE, 0, elapsed); - } - if (iolog->avg_window[DDIR_TRIM].samples) { - unsigned long mw; + iolog->avg_last = elapsed; +} - mw = iolog->avg_window[DDIR_TRIM].mean.u.f + 0.50; - __add_log_sample(iolog, mw, DDIR_TRIM, 0, elapsed); - } +void finalize_logs(struct thread_data *td) +{ + unsigned long elapsed; + elapsed = mtime_since_now(&td->epoch); - reset_io_stat(&iolog->avg_window[DDIR_READ]); - reset_io_stat(&iolog->avg_window[DDIR_WRITE]); - reset_io_stat(&iolog->avg_window[DDIR_TRIM]); - iolog->avg_last = elapsed; + if (td->clat_log) + _add_stat_to_log(td->clat_log, elapsed); + if (td->slat_log) + _add_stat_to_log(td->slat_log, elapsed); + if (td->lat_log) + _add_stat_to_log(td->lat_log, elapsed); + if (td->bw_log) + _add_stat_to_log(td->bw_log, elapsed); + if (td->iops_log) + _add_stat_to_log(td->iops_log, elapsed); } void add_agg_sample(unsigned long val, enum fio_ddir ddir, unsigned int bs) @@ -1666,7 +1766,7 @@ void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs, fio_gettime(&td->bw_sample_time, NULL); } -void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, +void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs, struct timeval *t) { struct thread_stat *ts = &td->ts; @@ -1693,10 +1793,25 @@ void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, add_stat_sample(&ts->iops_stat[ddir], iops); if (td->iops_log) - add_log_sample(td, td->iops_log, iops, ddir, 0); + add_log_sample(td, td->iops_log, iops, ddir, bs); td->stat_io_blocks[ddir] = td->this_io_blocks[ddir]; } fio_gettime(&td->iops_sample_time, NULL); } + +void stat_init(void) +{ + stat_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED); +} + +void stat_exit(void) +{ + /* + * When we have the mutex, we know out-of-band access to it + * have ended. + */ + fio_mutex_down(stat_mutex); + fio_mutex_remove(stat_mutex); +}