aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-09-01 23:31:46 +0200
committerChris Mason <chris.mason@oracle.com>2012-09-10 20:53:05 -0400
commit26871fde0abba867abdf43c490e9e64da55b5284 (patch)
tree8f2cf37f21a65ba3a4d84b5d90312b7373cd45a6
parent9d8523da087da8ddb87e72a4a008725a2cd7e0c8 (diff)
downloadiowatcher-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.c41
-rw-r--r--blkparse.h6
-rw-r--r--main.c32
-rw-r--r--plot.c18
-rw-r--r--plot.h3
5 files changed, 59 insertions, 41 deletions
diff --git a/blkparse.c b/blkparse.c
index 3aa44a6..ddcf204 100644
--- a/blkparse.c
+++ b/blkparse.c
@@ -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;
}
}
diff --git a/blkparse.h b/blkparse.h
index a78a8b7..2eff331 100644
--- a/blkparse.h
+++ b/blkparse.h
@@ -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);
diff --git a/main.c b/main.c
index 8adeacc..8ff2b65 100644
--- a/main.c
+++ b/main.c
@@ -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) {
diff --git a/plot.c b/plot.c
index 74bcb59..ec597ff 100644
--- a/plot.c
+++ b/plot.c
@@ -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;
diff --git a/plot.h b/plot.h
index 2d9d891..d70abcb 100644
--- a/plot.h
+++ b/plot.h
@@ -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);