gfio: add latency bucket display
authorJens Axboe <axboe@kernel.dk>
Mon, 5 Mar 2012 20:38:12 +0000 (21:38 +0100)
committerJens Axboe <axboe@kernel.dk>
Mon, 5 Mar 2012 20:38:12 +0000 (21:38 +0100)
Signed-off-by: Jens Axboe <axboe@kernel.dk>
gfio.c
stat.c
stat.h

diff --git a/gfio.c b/gfio.c
index 3602aa335b8f95596bf7ca1582e2c38af109635c..2c0c2cc5981b9153b31a72595764eb2156c7e638 100644 (file)
--- a/gfio.c
+++ b/gfio.c
@@ -472,6 +472,95 @@ static void gfio_show_ddir_status(GtkWidget *mbox, struct group_run_stats *rs,
        free(iops_p);
 }
 
+static GtkWidget *gfio_output_lat_buckets(double *lat, unsigned int num,
+                                         const char **labels)
+{
+       GtkWidget *tree_view;
+       GtkTreeSelection *selection;
+       GtkListStore *model;
+       GtkTreeIter iter;
+       GType *types;
+       int i, skipped;
+
+       /*
+        * Check if all are empty, in which case don't bother
+        */
+       for (i = 0, skipped = 0; i < num; i++)
+               if (lat[i] <= 0.0)
+                       skipped++;
+
+       if (skipped == num)
+               return NULL;
+
+       types = malloc(num * sizeof(GType));
+
+       for (i = 0; i < num; i++)
+               types[i] = G_TYPE_STRING;
+
+       model = gtk_list_store_newv(num, types);
+       free(types);
+       types = NULL;
+
+       tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
+       gtk_widget_set_can_focus(tree_view, FALSE);
+
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+       gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
+
+       for (i = 0; i < num; i++)
+               tree_view_column(tree_view, i, labels[i], ALIGN_RIGHT | UNSORTABLE);
+
+       gtk_list_store_append(model, &iter);
+
+       for (i = 0; i < num; i++) {
+               char fbuf[32];
+
+               if (lat[i] <= 0.0)
+                       sprintf(fbuf, "0.00");
+               else
+                       sprintf(fbuf, "%3.2f%%", lat[i]);
+
+               gtk_list_store_set(model, &iter, i, fbuf, -1);
+       }
+
+       return tree_view;
+}
+
+static void gfio_show_latency_buckets(GtkWidget *vbox, struct thread_stat *ts)
+{
+       GtkWidget *box, *frame, *tree_view;
+       double io_u_lat_u[FIO_IO_U_LAT_U_NR];
+       double io_u_lat_m[FIO_IO_U_LAT_M_NR];
+       const char *uranges[] = { "2", "4", "10", "20", "50", "100",
+                                 "250", "500", "750", "1000", };
+       const char *mranges[] = { "2", "4", "10", "20", "50", "100",
+                                 "250", "500", "750", "1000", "2000",
+                                 ">= 2000", };
+
+       stat_calc_lat_u(ts, io_u_lat_u);
+       stat_calc_lat_m(ts, io_u_lat_m);
+
+       tree_view = gfio_output_lat_buckets(io_u_lat_u, FIO_IO_U_LAT_U_NR, uranges);
+       if (tree_view) {
+               frame = gtk_frame_new("Latency buckets (usec)");
+               gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
+
+               box = gtk_hbox_new(FALSE, 3);
+               gtk_container_add(GTK_CONTAINER(frame), box);
+               gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 3);
+       }
+
+       tree_view = gfio_output_lat_buckets(io_u_lat_m, FIO_IO_U_LAT_M_NR, mranges);
+       if (tree_view) {
+               frame = gtk_frame_new("Latency buckets (msec)");
+               gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
+
+               box = gtk_hbox_new(FALSE, 3);
+               gtk_container_add(GTK_CONTAINER(frame), box);
+               gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 3);
+       }
+}
+
 static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
                            struct group_run_stats *rs)
 {
@@ -516,6 +605,8 @@ static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
        if (ts->io_bytes[DDIR_WRITE])
                gfio_show_ddir_status(vbox, rs, ts, DDIR_WRITE);
 
+       gfio_show_latency_buckets(vbox, ts);
+
        gtk_widget_show_all(dialog);
 
        gdk_threads_leave();
diff --git a/stat.c b/stat.c
index e4ddfa8c54455a43a696f136143511179a215cdc..0fd8b72587e6eef5882f3041d1db04b40bbb2ca4 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -327,12 +327,12 @@ static void stat_calc_lat(struct thread_stat *ts, double *dst,
        }
 }
 
-static void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat)
+void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat)
 {
        stat_calc_lat(ts, io_u_lat, ts->io_u_lat_u, FIO_IO_U_LAT_U_NR);
 }
 
-static void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat)
+void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat)
 {
        stat_calc_lat(ts, io_u_lat, ts->io_u_lat_m, FIO_IO_U_LAT_M_NR);
 }
diff --git a/stat.h b/stat.h
index 78e46711f355b2a06a0cd3d561140fa2dbfc471a..fb1bafde91dcd28a0b62c7d938816ab426fd7f13 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -200,6 +200,8 @@ extern void init_group_run_stat(struct group_run_stats *gs);
 extern void eta_to_str(char *str, unsigned long eta_sec);
 extern int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max, double *mean, double *dev);
 extern unsigned int calc_clat_percentiles(unsigned int *io_u_plat, unsigned long nr, fio_fp64_t *plist, unsigned int **output, unsigned int *maxv, unsigned int *minv);
+extern void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat);
+extern void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat);
 
 static inline int usec_to_msec(unsigned long *min, unsigned long *max,
                               double *mean, double *dev)