diff options
author | Chris Mason <clm@fb.com> | 2014-01-08 17:04:26 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-01-08 17:04:26 -0500 |
commit | 4748783e170b168013bf157679faa10f49eb8000 (patch) | |
tree | ab5733e97896be512a23a3837280eaa6053e44d3 | |
parent | 5d845e37b509032a3154b419e2b332a3bf6101f6 (diff) | |
parent | 283ee99d31561ccd16ec20841eaa0417bf739bac (diff) | |
download | iowatcher-4748783e170b168013bf157679faa10f49eb8000.tar.gz |
Merge Jan Kara's fixes
-rw-r--r-- | README | 9 | ||||
-rw-r--r-- | blkparse.c | 28 | ||||
-rw-r--r-- | blkparse.h | 13 | ||||
-rw-r--r-- | fio.c | 2 | ||||
-rw-r--r-- | fio.h | 2 | ||||
-rw-r--r-- | main.c | 59 | ||||
-rw-r--r-- | plot.c | 18 | ||||
-rw-r--r-- | plot.h | 14 |
8 files changed, 81 insertions, 64 deletions
@@ -32,6 +32,10 @@ The basic options: If you want more than one trace in a given graph, you can specify -t more than once. + -F Add a fio bandwidth log graph. You need to run fio --bandwidth-log + to get one of these, and then pass either the read log or the write + log into iowatcher. + -l Sets a label in the graph for a trace file. The labels are added in the same order the trace files are added. @@ -55,6 +59,9 @@ The basic options: current second with seconds from the past. Longer numbers here give you flatter graphs. + -P add per-process tags to the IO. Each process responsible for + submitting the IO gets a different color. + -O add a single graph to the output. By default all the graphs are included, but with -O you get only the graphs you ask for. -O may be used more than once. @@ -63,7 +70,7 @@ The basic options: than once. Choices for -O and -N are: - io, tput, latency, queue_depth, iops, cpu-sys, cpu-io, + io, fio, tput, latency, queue_depth, iops, cpu-sys, cpu-io, cpu-irq, cpu-user, cpu-soft Examples: @@ -181,12 +181,10 @@ struct pid_map { char name[0]; }; -#define MINORBITS 20 -#define MINORMASK ((1 << MINORBITS) - 1) -#define SECONDS(x) ((unsigned long long)(x) / 1000000000) -#define NANO_SECONDS(x) ((unsigned long long)(x) % 1000000000) -#define DOUBLE_TO_NANO_ULL(d) ((unsigned long long)((d) * 1000000000)) -#define CHECK_MAGIC(t) (((t)->magic & 0xffffff00) == BLK_IO_TRACE_MAGIC) +u64 get_record_time(struct trace *trace) +{ + return trace->io->time; +} void init_io_hash_table(void) { @@ -960,9 +958,6 @@ void add_tput(struct trace *trace, struct graph_line_data *writes_gld, gld = writes_gld; seconds = SECONDS(io->time); - if (seconds > gld->max_seconds) - return; - gld->data[seconds].sum += io->bytes; gld->data[seconds].count = 1; @@ -1043,7 +1038,7 @@ void add_io(struct trace *trace, struct trace_file *tf) void add_pending_io(struct trace *trace, struct graph_line_data *gld) { - int seconds; + unsigned int seconds; struct blk_io_trace *io = trace->io; int action = io->action & BLK_TA_MASK; double avg; @@ -1057,11 +1052,12 @@ void add_pending_io(struct trace *trace, struct graph_line_data *gld) hash_queued_io(trace->io); return; } - if (action != __BLK_TA_ISSUE) + if (action == __BLK_TA_REQUEUE) { + if (ios_in_flight > 0) + ios_in_flight--; return; - - seconds = SECONDS(io->time); - if (seconds > gld->max_seconds) + } + if (action != __BLK_TA_ISSUE) return; pio = hash_dispatched_io(trace->io); @@ -1075,6 +1071,7 @@ void add_pending_io(struct trace *trace, struct graph_line_data *gld) ios_in_flight++; + seconds = SECONDS(io->time); gld->data[seconds].sum += ios_in_flight; gld->data[seconds].count++; @@ -1138,9 +1135,6 @@ void add_iop(struct trace *trace, struct graph_line_data *gld) return; seconds = SECONDS(io->time); - if (seconds > gld->max_seconds) - return; - gld->data[seconds].sum += 1; gld->data[seconds].count = 1; if (gld->data[seconds].sum > gld->max) @@ -72,9 +72,9 @@ struct trace_file { char *filename; char *label; struct trace *trace; - int stop_seconds; /* Time when trace stops */ - int min_seconds; /* Beginning of the interval we should plot */ - int max_seconds; /* End of the interval we should plot */ + unsigned int stop_seconds; /* Time when trace stops */ + unsigned int min_seconds; /* Beginning of the interval we should plot */ + unsigned int max_seconds; /* End of the interval we should plot */ u64 min_offset; u64 max_offset; @@ -99,9 +99,9 @@ struct trace_file { struct graph_dot_data **gdd_writes; struct graph_dot_data **gdd_reads; - int mpstat_min_seconds; - int mpstat_max_seconds; - int mpstat_stop_seconds; + unsigned int mpstat_min_seconds; + unsigned int mpstat_max_seconds; + unsigned int mpstat_stop_seconds; struct graph_line_data **mpstat_gld; }; @@ -133,5 +133,6 @@ void add_tput(struct trace *trace, struct graph_line_data *writes_gld, struct graph_line_data *reads_gld); void add_pending_io(struct trace *trace, struct graph_line_data *gld); int next_record(struct trace *trace); +u64 get_record_time(struct trace *trace); void first_record(struct trace *trace); #endif @@ -198,7 +198,7 @@ int read_fio_event(struct trace *trace, int *time_ret, u64 *bw_ret, int *dir_ret return 0; } -int add_fio_gld(int time, u64 bw, struct graph_line_data *gld) +int add_fio_gld(unsigned int time, u64 bw, struct graph_line_data *gld) { double val; @@ -18,7 +18,7 @@ #define __FIO__ int read_fio_event(struct trace *trace, int *time, u64 *bw, int *dir); -int add_fio_gld(int time, u64 bw, struct graph_line_data *gld); +int add_fio_gld(unsigned int time, u64 bw, struct graph_line_data *gld); int next_fio_line(struct trace *trace); struct trace *open_fio_trace(char *path); char *first_fio(struct trace *trace); @@ -53,7 +53,7 @@ static int opt_graph_width = 0; static int opt_graph_height = 0; static int columns = 1; -static int num_xticks = 7; +static int num_xticks = 9; static int num_yticks = 4; static double min_time = 0; @@ -414,7 +414,7 @@ static void read_trace_events(void) struct trace *trace; int ret; int i; - int time; + unsigned int time; double user, sys, iowait, irq, soft; double max_user = 0, max_sys = 0, max_iowait = 0, max_irq = 0, max_soft = 0; @@ -426,17 +426,16 @@ static void read_trace_events(void) trace = tf->trace; first_record(trace); - while (1) { + do { + if (SECONDS(get_record_time(trace)) > tf->max_seconds) + continue; check_record(trace); add_tput(trace, tf->tput_writes_gld, tf->tput_reads_gld); add_iop(trace, tf->iop_gld); add_io(trace, tf); add_pending_io(trace, tf->queue_depth_gld); add_completed_io(trace, tf->latency_gld); - ret = next_record(trace); - if (ret) - break; - } + } while (!(ret = next_record(trace))); } list_for_each_entry(tf, &all_traces, list) { trace = tf->trace; @@ -446,7 +445,7 @@ static void read_trace_events(void) first_mpstat(trace); - for (time = 0; time < tf->mpstat_stop_seconds; time ++) { + for (time = 0; time < tf->mpstat_stop_seconds; time++) { for (i = 0; i < (trace->mpstat_num_cpus + 1) * MPSTAT_GRAPHS; i += MPSTAT_GRAPHS) { ret = read_mpstat_event(trace, &user, &sys, &iowait, &irq, &soft); @@ -532,7 +531,8 @@ static void set_blktrace_outfile(char *arg) } -static void compare_minmax_tf(struct trace_file *tf, int *max_seconds, u64 *min_offset, u64 *max_offset) +static void compare_minmax_tf(struct trace_file *tf, unsigned int *max_seconds, + u64 *min_offset, u64 *max_offset) { if (tf->max_seconds > *max_seconds) *max_seconds = tf->max_seconds; @@ -542,7 +542,9 @@ static void compare_minmax_tf(struct trace_file *tf, int *max_seconds, u64 *min_ *min_offset = tf->min_offset; } -static void set_all_minmax_tf(int min_seconds, int max_seconds, u64 min_offset, u64 max_offset) +static void set_all_minmax_tf(unsigned int min_seconds, + unsigned int max_seconds, + u64 min_offset, u64 max_offset) { struct trace_file *tf; struct list_head *traces = &all_traces; @@ -722,7 +724,8 @@ static int count_io_plot_types(void) return total_io_types; } -static void plot_io(struct plot *plot, int min_seconds, int max_seconds, u64 min_offset, u64 max_offset) +static void plot_io(struct plot *plot, unsigned int min_seconds, + unsigned int max_seconds, u64 min_offset, u64 max_offset) { struct trace_file *tf; int i; @@ -776,8 +779,8 @@ static void plot_io(struct plot *plot, int min_seconds, int max_seconds, u64 min close_plot(plot); } -static void plot_tput(struct plot *plot, int min_seconds, int max_seconds, - int with_legend) +static void plot_tput(struct plot *plot, unsigned int min_seconds, + unsigned int max_seconds, int with_legend) { struct trace_file *tf; char *units; @@ -837,7 +840,8 @@ static void plot_tput(struct plot *plot, int min_seconds, int max_seconds, total_graphs_written++; } -static void plot_fio_tput(struct plot *plot, int min_seconds, int max_seconds) +static void plot_fio_tput(struct plot *plot, + unsigned int min_seconds, unsigned int max_seconds) { struct trace_file *tf; char *units; @@ -888,13 +892,13 @@ static void plot_fio_tput(struct plot *plot, int min_seconds, int max_seconds) total_graphs_written++; } -static void plot_cpu(struct plot *plot, int max_seconds, char *label, +static void plot_cpu(struct plot *plot, unsigned int max_seconds, char *label, int active_index, int gld_index) { struct trace_file *tf; int max = 0; int i; - int gld_i; + unsigned int gld_i; char *color; double avg = 0; int ymax; @@ -931,11 +935,11 @@ static void plot_cpu(struct plot *plot, int max_seconds, char *label, list_for_each_entry(tf, &all_traces, list) { if (tf->mpstat_gld == 0) break; - for (i = tf->mpstat_gld[0]->min_seconds; - i < tf->mpstat_gld[0]->stop_seconds; i++) { - if (tf->mpstat_gld[gld_index]->data[i].count) { - avg += (tf->mpstat_gld[gld_index]->data[i].sum / - tf->mpstat_gld[gld_index]->data[i].count); + for (gld_i = tf->mpstat_gld[0]->min_seconds; + gld_i < tf->mpstat_gld[0]->stop_seconds; gld_i++) { + if (tf->mpstat_gld[gld_index]->data[gld_i].count) { + avg += (tf->mpstat_gld[gld_index]->data[gld_i].sum / + tf->mpstat_gld[gld_index]->data[gld_i].count); } } avg /= tf->mpstat_gld[gld_index]->stop_seconds - @@ -991,7 +995,8 @@ static void plot_cpu(struct plot *plot, int max_seconds, char *label, total_graphs_written++; } -static void plot_queue_depth(struct plot *plot, int min_seconds, int max_seconds) +static void plot_queue_depth(struct plot *plot, unsigned int min_seconds, + unsigned int max_seconds) { struct trace_file *tf; @@ -1192,7 +1197,8 @@ static void plot_io_movie(struct plot *plot) free(movie_dir); } -static void plot_latency(struct plot *plot, int min_seconds, int max_seconds) +static void plot_latency(struct plot *plot, unsigned int min_seconds, + unsigned int max_seconds) { struct trace_file *tf; char *units; @@ -1238,7 +1244,8 @@ static void plot_latency(struct plot *plot, int min_seconds, int max_seconds) total_graphs_written++; } -static void plot_iops(struct plot *plot, int min_seconds, int max_seconds) +static void plot_iops(struct plot *plot, unsigned int min_seconds, + unsigned int max_seconds) { struct trace_file *tf; char *units; @@ -1568,8 +1575,8 @@ static void dest_mkdir(char *dir) int main(int ac, char **av) { struct plot *plot; - int min_seconds = 0; - int max_seconds = 0; + unsigned int min_seconds = 0; + unsigned int max_seconds = 0; u64 max_offset = 0; u64 min_offset = ~(u64)0; struct trace_file *tf; @@ -127,7 +127,9 @@ void reset_cpu_color(void) cpu_color_index = 0; } -struct graph_line_data *alloc_line_data(int min_seconds, int max_seconds, int stop_seconds) +struct graph_line_data *alloc_line_data(unsigned int min_seconds, + unsigned int max_seconds, + unsigned int stop_seconds) { int size = sizeof(struct graph_line_data) + (stop_seconds + 1) * sizeof(struct graph_line_pair); struct graph_line_data *gld; @@ -149,7 +151,11 @@ void free_line_data(struct graph_line_data *gld) free(gld); } -struct graph_dot_data *alloc_dot_data(int min_seconds, int max_seconds, u64 min_offset, u64 max_offset, int stop_seconds, char *color, char *label) +struct graph_dot_data *alloc_dot_data(unsigned int min_seconds, + unsigned int max_seconds, + u64 min_offset, u64 max_offset, + unsigned int stop_seconds, + char *color, char *label) { int size; int arr_size; @@ -206,8 +212,10 @@ void set_gdd_bit(struct graph_dot_data *gdd, u64 offset, double bytes, double ti if (offset > gdd->max_offset || offset < gdd->min_offset) return; - gdd->total_ios++; time = time / 1000000000.0; + if (time < gdd->min_seconds || time > gdd->max_seconds) + return; + gdd->total_ios++; while (bytes > 0 && offset <= gdd->max_offset) { row = (double)(offset - gdd->min_offset) / bytes_per_row; col = (time - gdd->min_seconds) / secs_per_col; @@ -563,7 +571,7 @@ void set_xticks(struct plot *plot, int num_ticks, int first, int last) * We don't want last two ticks to be too close together so subtract * 20% of the step from the interval */ - num_ticks = (double)(last - first - step / 5) / step + 1; + num_ticks = (double)(last - first - step) / step + 1; pixels_per_tick = graph_width * step / (double)(last - first); for (i = 0; i < num_ticks; i++) { @@ -807,7 +815,7 @@ void scale_line_graph_time(u64 *max, char **units) int svg_line_graph(struct plot *plot, struct graph_line_data *gld, char *color, int thresh1, int thresh2) { - int i; + unsigned int i; double val; double avg; int rolling; @@ -69,12 +69,12 @@ struct graph_line_pair { struct graph_line_data { /* beginning of an interval displayed by this graph */ - int min_seconds; + unsigned int min_seconds; /* end of an interval displayed by this graph */ - int max_seconds; + unsigned int max_seconds; - int stop_seconds; + unsigned int stop_seconds; /* Y max */ u64 max; @@ -103,8 +103,8 @@ struct graph_dot_data { int min_seconds; /* end of an interval displayed by this graph */ - int max_seconds; - int stop_seconds; + unsigned int max_seconds; + unsigned int stop_seconds; /* label for the legend */ char *label; @@ -138,9 +138,9 @@ char *pick_cpu_color(void); void reset_cpu_color(void); int svg_io_graph(struct plot *plot, struct graph_dot_data *gdd); int svg_line_graph(struct plot *plot, struct graph_line_data *gld, char *color, int thresh1, int thresh2); -struct graph_line_data *alloc_line_data(int min_seconds, int max_seconds, int stop_seconds); +struct graph_line_data *alloc_line_data(unsigned int min_seconds, unsigned int max_seconds, unsigned int stop_seconds); void free_line_data(struct graph_line_data *gld); -struct graph_dot_data *alloc_dot_data(int min_seconds, int max_seconds, u64 min_offset, u64 max_offset, int stop_seconds, char *color, char *label); +struct graph_dot_data *alloc_dot_data(unsigned int min_seconds, unsigned int max_seconds, u64 min_offset, u64 max_offset, unsigned int stop_seconds, char *color, char *label); void free_dot_data(struct graph_dot_data *gdd); void set_gdd_bit(struct graph_dot_data *gdd, u64 offset, double bytes, double time); void print_gdd(struct graph_dot_data *gdd); |