diff options
author | Jan Kara <jack@suse.cz> | 2012-09-01 23:31:46 +0200 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-09-10 20:53:05 -0400 |
commit | 26871fde0abba867abdf43c490e9e64da55b5284 (patch) | |
tree | 8f2cf37f21a65ba3a4d84b5d90312b7373cd45a6 | |
parent | 9d8523da087da8ddb87e72a4a008725a2cd7e0c8 (diff) | |
download | iowatcher-26871fde0abba867abdf43c490e9e64da55b5284.tar.gz |
Add support for limitting IO graph offset from below
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r-- | blkparse.c | 41 | ||||
-rw-r--r-- | blkparse.h | 6 | ||||
-rw-r--r-- | main.c | 32 | ||||
-rw-r--r-- | plot.c | 18 | ||||
-rw-r--r-- | plot.h | 3 |
5 files changed, 59 insertions, 41 deletions
@@ -413,11 +413,11 @@ out: return -1; } -void find_highest_offset(struct trace *trace, u64 *max_ret, u64 *max_bank_ret, - u64 *max_offset_ret) +void find_extreme_offsets(struct trace *trace, u64 *min_ret, u64 *max_ret, u64 *max_bank_ret, + u64 *max_offset_ret) { u64 found = 0; - u64 max = 0; + u64 max = 0, min = ~(u64)0; u64 max_bank = 0; u64 max_bank_offset = 0; u64 num_banks = 0; @@ -425,11 +425,12 @@ void find_highest_offset(struct trace *trace, u64 *max_ret, u64 *max_bank_ret, while (1) { if (!(trace->io->action & BLK_TC_ACT(BLK_TC_NOTIFY))) { found = trace->io->sector << 9; - found += trace->io->bytes; + if (found < min) + min = found; - if (max < found) { + found += trace->io->bytes; + if (max < found) max = found; - } } else { u64 bank; u64 offset; @@ -445,31 +446,41 @@ void find_highest_offset(struct trace *trace, u64 *max_ret, u64 *max_bank_ret, break; } first_record(trace); + *min_ret = min; *max_ret = max; *max_bank_ret = max_bank; *max_offset_ret = max_bank_offset; } -int filter_outliers(struct trace *trace, u64 max_offset, +int filter_outliers(struct trace *trace, u64 min_offset, u64 max_offset, u64 *yzoom_min, u64 *yzoom_max) { int hits[11]; u64 max_per_bucket[11]; - u64 bytes_per_bucket = max_offset / 10; + u64 min_per_bucket[11]; + u64 bytes_per_bucket = (max_offset - min_offset + 1) / 10; int slot; int fat_count = 0; memset(hits, 0, sizeof(int) * 11); memset(max_per_bucket, 0, sizeof(u64) * 11); + memset(min_per_bucket, 0xff, sizeof(u64) * 11); first_record(trace); while (1) { if (!(trace->io->action & BLK_TC_ACT(BLK_TC_NOTIFY)) && (trace->io->action & BLK_TA_MASK) == __BLK_TA_QUEUE) { - u64 top = (trace->io->sector << 9) + trace->io->bytes; - slot = (int)(top / bytes_per_bucket); + u64 off = (trace->io->sector << 9) - min_offset; + + slot = (int)(off / bytes_per_bucket); + hits[slot]++; + if (off < min_per_bucket[slot]) + min_per_bucket[slot] = off; + + off += trace->io->bytes; + slot = (int)(off / bytes_per_bucket); hits[slot]++; - if (top > max_per_bucket[slot]) - max_per_bucket[slot] = top; + if (off > max_per_bucket[slot]) + max_per_bucket[slot] = off; } if (next_record(trace)) break; @@ -486,17 +497,17 @@ int filter_outliers(struct trace *trace, u64 max_offset, double d = hits[slot]; if (d >= (double)fat_count * .05) { - *yzoom_max = max_per_bucket[slot]; + *yzoom_max = max_per_bucket[slot] + min_offset; break; } } - *yzoom_min = 0; + *yzoom_min = min_offset; for (slot = 0; slot < 10; slot++) { double d = hits[slot]; if (d >= (double)fat_count * .05) { - *yzoom_min = slot * bytes_per_bucket; + *yzoom_min = min_per_bucket[slot] + min_offset; break; } } @@ -63,9 +63,9 @@ static inline unsigned int MINOR(unsigned int dev) void init_io_hash_table(void); struct trace *open_trace(char *filename); u64 find_last_time(struct trace *trace); -void find_highest_offset(struct trace *trace, u64 *max_ret, u64 *max_bank_ret, - u64 *max_offset_ret); -int filter_outliers(struct trace *trace, u64 max_offset, +void find_extreme_offsets(struct trace *trace, u64 *min_ret, u64 *max_ret, + u64 *max_bank_ret, u64 *max_offset_ret); +int filter_outliers(struct trace *trace, u64 min_offset, u64 max_offset, u64 *yzoom_min, u64 *yzoom_max); void add_iop(struct trace *trace, struct graph_line_data *gld); void check_record(struct trace *trace); @@ -163,6 +163,7 @@ struct trace_file { struct trace *trace; int seconds; int stop_seconds; + u64 min_offset; u64 max_offset; char *read_color; @@ -283,8 +284,8 @@ static void setup_trace_file_graphs(void) tf->latency_gld = alloc_line_data(tf->seconds, tf->stop_seconds); tf->queue_depth_gld = alloc_line_data(tf->seconds, tf->stop_seconds); tf->iop_gld = alloc_line_data(tf->seconds, tf->stop_seconds); - tf->gdd_writes = alloc_dot_data(tf->seconds, tf->max_offset, tf->stop_seconds); - tf->gdd_reads = alloc_dot_data(tf->seconds, tf->max_offset, tf->stop_seconds); + tf->gdd_writes = alloc_dot_data(tf->seconds, tf->min_offset, tf->max_offset, tf->stop_seconds); + tf->gdd_reads = alloc_dot_data(tf->seconds, tf->min_offset, tf->max_offset, tf->stop_seconds); if (tf->trace->mpstat_num_cpus == 0) continue; @@ -318,9 +319,10 @@ static void read_traces(void) tf->trace = trace; tf->seconds = SECONDS(last_time); tf->stop_seconds = SECONDS(last_time); - find_highest_offset(trace, &tf->max_offset, &max_bank, - &max_bank_offset); - filter_outliers(trace, tf->max_offset, &ymin, &ymax); + find_extreme_offsets(trace, &tf->min_offset, &tf->max_offset, + &max_bank, &max_bank_offset); + filter_outliers(trace, tf->min_offset, tf->max_offset, &ymin, &ymax); + tf->min_offset = ymin; tf->max_offset = ymax; read_mpstat(trace, tf->filename); @@ -450,20 +452,23 @@ static void set_blktrace_outfile(char *arg) } -static void compare_max_tf(struct trace_file *tf, int *seconds, u64 *max_offset) +static void compare_minmax_tf(struct trace_file *tf, int *seconds, u64 *min_offset, u64 *max_offset) { if (tf->seconds > *seconds) *seconds = tf->seconds; if (tf->max_offset > *max_offset) *max_offset = tf->max_offset; + if (tf->min_offset < *min_offset) + *min_offset = tf->min_offset; } -static void set_all_max_tf(int seconds, u64 max_offset) +static void set_all_minmax_tf(int seconds, u64 min_offset, u64 max_offset) { struct trace_file *tf; list_for_each_entry(tf, &all_traces, list) { tf->seconds = seconds; + tf->min_offset = min_offset; tf->max_offset = max_offset; } } @@ -545,7 +550,7 @@ static void free_all_plot_history(struct list_head *head) } } -static void plot_io(struct plot *plot, int seconds, u64 max_offset) +static void plot_io(struct plot *plot, int seconds, u64 min_offset, u64 max_offset) { struct trace_file *tf; @@ -558,7 +563,8 @@ static void plot_io(struct plot *plot, int seconds, u64 max_offset) set_plot_label(plot, "Device IO"); set_ylabel(plot, "Offset (MB)"); - set_yticks(plot, 4, 0, max_offset / (1024 * 1024), ""); + set_yticks(plot, 4, min_offset / (1024 * 1024), + max_offset / (1024 * 1024), ""); set_xticks(plot, num_xticks, 0, seconds); list_for_each_entry(tf, &all_traces, list) { @@ -1120,6 +1126,7 @@ int main(int ac, char **av) struct plot *plot; int seconds = 0; u64 max_offset = 0; + u64 min_offset = ~(u64)0; struct trace_file *tf; int ret; int rows, cols; @@ -1185,10 +1192,9 @@ int main(int ac, char **av) /* step two, find the maxes for time and offset */ list_for_each_entry(tf, &all_traces, list) - compare_max_tf(tf, &seconds, &max_offset); - + compare_minmax_tf(tf, &seconds, &min_offset, &max_offset); /* push the max we found into all the tfs */ - set_all_max_tf(seconds, max_offset); + set_all_minmax_tf(seconds, min_offset, max_offset); /* alloc graphing structs for all the traces */ setup_trace_file_graphs(); @@ -1217,7 +1223,7 @@ int main(int ac, char **av) plot->add_xlabel = 1; set_plot_title(plot, graph_title); - plot_io(plot, seconds, max_offset); + plot_io(plot, seconds, min_offset, max_offset); plot->add_xlabel = 0; if (columns > 1) { @@ -90,7 +90,7 @@ void free_line_data(struct graph_line_data *gld) free(gld); } -struct graph_dot_data *alloc_dot_data(int seconds, u64 max_offset, int stop_seconds) +struct graph_dot_data *alloc_dot_data(int seconds, u64 min_offset, u64 max_offset, int stop_seconds) { int size; int arr_size; @@ -115,6 +115,7 @@ struct graph_dot_data *alloc_dot_data(int seconds, u64 max_offset, int stop_seco gdd->stop_seconds = stop_seconds; gdd->rows = rows; gdd->cols = cols; + gdd->min_offset = min_offset; gdd->max_offset = max_offset; return gdd; } @@ -126,8 +127,7 @@ void free_dot_data(struct graph_dot_data *gdd) void set_gdd_bit(struct graph_dot_data *gdd, u64 offset, double bytes, double time) { - double bytes_per_row = (double)gdd->max_offset / gdd->rows; - + double bytes_per_row = (double)(gdd->max_offset - gdd->min_offset + 1) / gdd->rows; double secs_per_col = (double)gdd->seconds / gdd->cols; double col; double row; @@ -138,13 +138,13 @@ void set_gdd_bit(struct graph_dot_data *gdd, u64 offset, double bytes, double ti int bit_mod; double mod = bytes_per_row; - if (offset > gdd->max_offset) + if (offset > gdd->max_offset || offset < gdd->min_offset) return; gdd->total_ios++; time = time / 1000000000.0; while (bytes > 0) { - row = (double)offset / bytes_per_row; + row = (double)(offset - gdd->min_offset) / bytes_per_row; col = time / secs_per_col; col_int = floor(col); @@ -561,7 +561,7 @@ void set_yticks(struct plot *plot, int num_ticks, int first, int last, char *uni "fill=\"black\" style=\"text-anchor: %s\">%d%s</text>\n", text_x, axis_y_off(tick_y - tick_font_size / 2), - font_family, tick_font_size, anchor, step * i, units); + font_family, tick_font_size, anchor, first + step * i, units); write(plot->fd, line, strlen(line)); tick_y += pixels_per_tick; } @@ -904,13 +904,13 @@ int svg_io_graph_movie(struct graph_dot_data *gdd, struct plot_history *ph, int unsigned char val; int bit_index; int bit_mod; - double blocks_per_row = gdd->max_offset / gdd->rows; - double movie_blocks_per_cell = gdd->max_offset / (graph_width * graph_height); + double blocks_per_row = (gdd->max_offset - gdd->min_offset + 1) / gdd->rows; + double movie_blocks_per_cell = (gdd->max_offset - gdd->min_offset + 1) / (graph_width * graph_height); double cell_index; int margin_orig = graph_inner_y_margin; graph_inner_y_margin += 5; - ph->history_max = gdd->max_offset / movie_blocks_per_cell; + ph->history_max = (gdd->max_offset - gdd->min_offset + 1) / movie_blocks_per_cell; for (row = gdd->rows - 1; row >= 0; row--) { bit_index = row * gdd->cols + col; @@ -82,6 +82,7 @@ struct graph_line_data { }; struct graph_dot_data { + u64 min_offset; u64 max_offset; u64 max_bank; u64 max_bank_offset; @@ -120,7 +121,7 @@ int svg_io_graph(struct plot *plot, struct graph_dot_data *gdd, char *color); 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 seconds, int stop_seconds); void free_line_data(struct graph_line_data *gld); -struct graph_dot_data *alloc_dot_data(int seconds, u64 max_offset, int stop_seconds); +struct graph_dot_data *alloc_dot_data(int seconds, u64 min_offset, u64 max_offset, int stop_seconds); 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); |