X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=stat.c;h=b5ff0101b7b0feca625721bc10b351a48825a271;hp=ec87debaf61580cbff89c7049d53e1009a085c2d;hb=d175907a7bd0b78cdd18bf47882428368a448057;hpb=f2bba1820a567ac00b09916239ac8feb125cead2 diff --git a/stat.c b/stat.c index ec87deba..b5ff0101 100644 --- a/stat.c +++ b/stat.c @@ -59,15 +59,17 @@ static void show_group_stats(struct group_run_stats *rs, int id) log_info("\nRun status group %d (all jobs):\n", id); for (i = 0; i <= DDIR_WRITE; i++) { + const int i2p = is_power_of_2(rs->kb_base); + if (!rs->max_run[i]) continue; - p1 = num2str(rs->io_kb[i], 6, 1024, 1); - p2 = num2str(rs->agg[i], 6, 1024, 1); - p3 = num2str(rs->min_bw[i], 6, 1024, 1); - p4 = num2str(rs->max_bw[i], 6, 1024, 1); + p1 = num2str(rs->io_kb[i], 6, rs->kb_base, i2p); + p2 = num2str(rs->agg[i], 6, rs->kb_base, i2p); + p3 = num2str(rs->min_bw[i], 6, rs->kb_base, i2p); + p4 = num2str(rs->max_bw[i], 6, rs->kb_base, i2p); - log_info("%s: io=%siB, aggrb=%siB/s, minb=%siB/s, maxb=%siB/s," + log_info("%s: io=%sB, aggrb=%sB/s, minb=%sB/s, maxb=%sB/s," " mint=%llumsec, maxt=%llumsec\n", ddir_str[i], p1, p2, p3, p4, rs->min_run[i], rs->max_run[i]); @@ -153,20 +155,24 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts, unsigned long long bw, iops; double mean, dev; char *io_p, *bw_p, *iops_p; + int i2p; + + assert(ddir_rw(ddir)); if (!ts->runtime[ddir]) return; + i2p = is_power_of_2(rs->kb_base); runt = ts->runtime[ddir]; bw = (1000 * ts->io_bytes[ddir]) / runt; - io_p = num2str(ts->io_bytes[ddir] >> 10, 6, 1024, 1); - bw_p = num2str(bw >> 10, 6, 1024, 1); + io_p = num2str(ts->io_bytes[ddir], 6, 1, i2p); + bw_p = num2str(bw, 6, 1, i2p); iops = (1000 * ts->total_io_u[ddir]) / runt; iops_p = num2str(iops, 6, 1, 0); - log_info(" %s: io=%siB, bw=%siB/s, iops=%s, runt=%6lumsec\n", + log_info(" %s: io=%sB, bw=%sB/s, iops=%s, runt=%6lumsec\n", ddir_str[ddir], io_p, bw_p, iops_p, ts->runtime[ddir]); @@ -206,11 +212,27 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts, free(minp); free(maxp); } + if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) { + const char *base = "(usec)"; + char *minp, *maxp; + + if (!usec_to_msec(&min, &max, &mean, &dev)) + base = "(msec)"; + + minp = num2str(min, 6, 1, 0); + maxp = num2str(max, 6, 1, 0); + + log_info(" lat %s: min=%s, max=%s, avg=%5.02f," + " stdev=%5.02f\n", base, minp, maxp, mean, dev); + + free(minp); + free(maxp); + } if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) { double p_of_agg; p_of_agg = mean * 100 / (double) rs->agg[ddir]; - log_info(" bw (KiB/s) : min=%5lu, max=%5lu, per=%3.2f%%," + log_info(" bw (KB/s) : min=%5lu, max=%5lu, per=%3.2f%%," " avg=%5.02f, stdev=%5.02f\n", min, max, p_of_agg, mean, dev); } @@ -329,15 +351,19 @@ static void show_thread_status(struct thread_stat *ts, io_u_dist[1], io_u_dist[2], io_u_dist[3], io_u_dist[4], io_u_dist[5], io_u_dist[6]); - log_info(" issued r/w: total=%lu/%lu, short=%lu/%lu\n", + log_info(" issued r/w/d: total=%lu/%lu/%lu, short=%lu/%lu/%lu\n", ts->total_io_u[0], ts->total_io_u[1], - ts->short_io_u[0], ts->short_io_u[1]); + ts->total_io_u[2], + ts->short_io_u[0], ts->short_io_u[1], + ts->short_io_u[2]); stat_calc_lat_u(ts, io_u_lat_u); stat_calc_lat_m(ts, io_u_lat_m); show_latencies(io_u_lat_u, io_u_lat_m); if (ts->continue_on_error) { - log_info(" errors: total=%lu, first_error=%d\n", - ts->total_err_count, ts->first_error); + log_info(" errors : total=%lu, first_error=%d/<%s>\n", + ts->total_err_count, + ts->first_error, + strerror(ts->first_error)); } } @@ -348,6 +374,8 @@ static void show_ddir_status_terse(struct thread_stat *ts, unsigned long long bw; double mean, dev; + assert(ddir_rw(ddir)); + bw = 0; if (ts->runtime[ddir]) bw = ts->io_bytes[ddir] / ts->runtime[ddir]; @@ -365,6 +393,11 @@ static void show_ddir_status_terse(struct thread_stat *ts, else log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0); + if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) + log_info(";%lu;%lu;%f;%f", min, max, mean, dev); + else + log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0); + if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) { double p_of_agg; @@ -374,6 +407,7 @@ static void show_ddir_status_terse(struct thread_stat *ts, log_info(";%lu;%lu;%f%%;%f;%f", 0UL, 0UL, 0.0, 0.0, 0.0); } +#define FIO_TERSE_VERSION "2" static void show_thread_status_terse(struct thread_stat *ts, struct group_run_stats *rs) @@ -384,11 +418,15 @@ static void show_thread_status_terse(struct thread_stat *ts, double usr_cpu, sys_cpu; int i; - log_info("%s;%d;%d", ts->name, ts->groupid, ts->error); - + /* General Info */ + log_info("%s;%s;%d;%d", FIO_TERSE_VERSION, ts->name, ts->groupid, + ts->error); + /* Log Read Status */ show_ddir_status_terse(ts, rs, 0); + /* Log Write Status */ show_ddir_status_terse(ts, rs, 1); + /* CPU Usage */ if (ts->total_run_time) { double runt = (double) ts->total_run_time; @@ -402,22 +440,28 @@ static void show_thread_status_terse(struct thread_stat *ts, log_info(";%f%%;%f%%;%lu;%lu;%lu", usr_cpu, sys_cpu, ts->ctx, ts->majf, ts->minf); + /* Calc % distribution of IO depths, usecond, msecond latency */ stat_calc_dist(ts->io_u_map, ts_total_io_u(ts), io_u_dist); stat_calc_lat_u(ts, io_u_lat_u); stat_calc_lat_m(ts, io_u_lat_m); + /* Only show fixed 7 I/O depth levels*/ log_info(";%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%", io_u_dist[0], io_u_dist[1], io_u_dist[2], io_u_dist[3], io_u_dist[4], io_u_dist[5], io_u_dist[6]); + /* Microsecond latency */ for (i = 0; i < FIO_IO_U_LAT_U_NR; i++) log_info(";%3.2f%%", io_u_lat_u[i]); + /* Millisecond latency */ for (i = 0; i < FIO_IO_U_LAT_M_NR; i++) log_info(";%3.2f%%", io_u_lat_m[i]); + /* Additional output if continue_on_error set - default off*/ if (ts->continue_on_error) log_info(";%lu;%d", ts->total_err_count, ts->first_error); log_info("\n"); + /* Additional output if description is set */ if (ts->description) log_info(";%s", ts->description); @@ -455,6 +499,7 @@ void show_run_stats(void) struct thread_data *td; struct thread_stat *threadstats, *ts; int i, j, k, l, nr_ts, last_ts, idx; + int kb_base_warned = 0; runstats = malloc(sizeof(struct group_run_stats) * (groupid + 1)); @@ -491,6 +536,7 @@ void show_run_stats(void) memset(ts, 0, sizeof(*ts)); for (j = 0; j <= DDIR_WRITE; j++) { + ts->lat_stat[j].min_val = -1UL; ts->clat_stat[j].min_val = -1UL; ts->slat_stat[j].min_val = -1UL; ts->bw_stat[j].min_val = -1UL; @@ -527,6 +573,12 @@ void show_run_stats(void) * first pid in group, not very useful... */ ts->pid = td->pid; + + ts->kb_base = td->o.kb_base; + } else if (ts->kb_base != td->o.kb_base && !kb_base_warned) { + log_info("fio: kb_base differs for jobs in group, using" + " %u as the base\n", ts->kb_base); + kb_base_warned = 1; } ts->continue_on_error = td->o.continue_on_error; @@ -546,6 +598,7 @@ void show_run_stats(void) for (l = 0; l <= DDIR_WRITE; l++) { sum_stat(&ts->clat_stat[l], &td->ts.clat_stat[l], idx); sum_stat(&ts->slat_stat[l], &td->ts.slat_stat[l], idx); + sum_stat(&ts->lat_stat[l], &td->ts.lat_stat[l], idx); sum_stat(&ts->bw_stat[l], &td->ts.bw_stat[l], idx); ts->stat_io_bytes[l] += td->ts.stat_io_bytes[l]; @@ -573,7 +626,7 @@ void show_run_stats(void) ts->io_u_lat_m[k] += td->ts.io_u_lat_m[k]; - for (k = 0; k <= DDIR_WRITE; k++) { + for (k = 0; k <= 2; k++) { ts->total_io_u[k] += td->ts.total_io_u[k]; ts->short_io_u[k] += td->ts.short_io_u[k]; } @@ -588,6 +641,7 @@ void show_run_stats(void) ts = &threadstats[i]; rs = &runstats[ts->groupid]; + rs->kb_base = ts->kb_base; for (j = 0; j <= DDIR_WRITE; j++) { if (!ts->runtime[j]) @@ -601,7 +655,7 @@ void show_run_stats(void) if (ts->runtime[j]) { unsigned long runt; - runt = ts->runtime[j] * 1024 / 1000; + runt = ts->runtime[j]; bw = ts->io_bytes[j] / runt; } if (bw < rs->min_bw[j]) @@ -609,7 +663,7 @@ void show_run_stats(void) if (bw > rs->max_bw[j]) rs->max_bw[j] = bw; - rs->io_kb[j] += ts->io_bytes[j] >> 10; + rs->io_kb[j] += ts->io_bytes[j] / rs->kb_base; } } @@ -617,20 +671,20 @@ void show_run_stats(void) unsigned long max_run[2]; rs = &runstats[i]; - max_run[0] = rs->max_run[0] * 1024 / 1000; - max_run[1] = rs->max_run[1] * 1024 / 1000; + max_run[0] = rs->max_run[0]; + max_run[1] = rs->max_run[1]; if (rs->max_run[0]) - rs->agg[0] = (rs->io_kb[0]*1024) / max_run[0]; + rs->agg[0] = (rs->io_kb[0] * 1000) / max_run[0]; if (rs->max_run[1]) - rs->agg[1] = (rs->io_kb[1]*1024) / max_run[1]; + rs->agg[1] = (rs->io_kb[1] * 1000) / max_run[1]; } /* * don't overwrite last signal output */ if (!terse_output) - printf("\n"); + log_info("\n"); for (i = 0; i < nr_ts; i++) { ts = &threadstats[i]; @@ -696,13 +750,20 @@ static void add_log_sample(struct thread_data *td, struct io_log *iolog, unsigned long val, enum fio_ddir ddir, unsigned int bs) { + if (!ddir_rw(ddir)) + return; + __add_log_sample(iolog, val, ddir, bs, mtime_since_now(&td->epoch)); } void add_agg_sample(unsigned long val, enum fio_ddir ddir, unsigned int bs) { - struct io_log *iolog = agg_io_log[ddir]; + struct io_log *iolog; + + if (!ddir_rw(ddir)) + return; + iolog = agg_io_log[ddir]; __add_log_sample(iolog, val, ddir, bs, mtime_since_genesis()); } @@ -711,6 +772,9 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir, { struct thread_stat *ts = &td->ts; + if (!ddir_rw(ddir)) + return; + add_stat_sample(&ts->clat_stat[ddir], usec); if (ts->clat_log) @@ -722,23 +786,44 @@ void add_slat_sample(struct thread_data *td, enum fio_ddir ddir, { struct thread_stat *ts = &td->ts; + if (!ddir_rw(ddir)) + return; + add_stat_sample(&ts->slat_stat[ddir], usec); if (ts->slat_log) add_log_sample(td, ts->slat_log, usec, ddir, bs); } +void add_lat_sample(struct thread_data *td, enum fio_ddir ddir, + unsigned long usec, unsigned int bs) +{ + struct thread_stat *ts = &td->ts; + + if (!ddir_rw(ddir)) + return; + + add_stat_sample(&ts->lat_stat[ddir], usec); + + if (ts->lat_log) + add_log_sample(td, ts->lat_log, usec, ddir, bs); +} + void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs, struct timeval *t) { struct thread_stat *ts = &td->ts; - unsigned long spent = mtime_since(&ts->stat_sample_time[ddir], t); - unsigned long rate; + unsigned long spent, rate; + + if (!ddir_rw(ddir)) + return; + spent = mtime_since(&ts->stat_sample_time[ddir], t); if (spent < td->o.bw_avg_time) return; - rate = (td->this_io_bytes[ddir] - ts->stat_io_bytes[ddir]) * 1000 / spent / 1024; + rate = (td->this_io_bytes[ddir] - ts->stat_io_bytes[ddir]) * + 1000 / spent / 1024; add_stat_sample(&ts->bw_stat[ddir], rate); if (ts->bw_log)