Added in Q2D histograms (requires -A)
authorAlan D. Brunelle <Alan.Brunelle@hp.com>
Wed, 5 Dec 2007 23:08:10 +0000 (18:08 -0500)
committerAlan D. Brunelle <Alan.Brunelle@hp.com>
Wed, 5 Dec 2007 23:08:10 +0000 (18:08 -0500)
As an example, the buckets are in seconds:

==================== Q2D Histogram ====================

       DEV | <.005 <.010 <.025 <.050 <.075 <.100 <.250 <.500 < 1.0 >=1.0
 --------- | ===== ===== ===== ===== ===== ===== ===== ===== ===== =====
 ( 66, 80) |  61.2   7.9  12.1   7.9   3.0   1.4   1.5   0.2   0.0   4.6
 ( 65,192) |  42.3   5.0   8.7  30.0   8.9   3.0   1.8   0.1   0.0   0.1
 ( 65,128) |  34.3   5.3   8.9  32.0   9.7   3.7   5.3   0.6   0.0   0.1
 ( 66,  0) |  45.5   9.9  19.0  14.8   4.6   1.2   0.3   0.0   0.0   4.7
 ( 65, 48) |  50.2   4.6   7.2  27.6   6.9   2.1   1.1   0.0   0.0   0.1
 ( 66, 32) |  66.4   6.7  10.9   7.0   2.5   1.1   0.6   0.1   0.0   4.7
 ( 65,224) |  33.9   9.6  20.6  17.8   7.3   3.1   3.3   0.5   0.1   3.8
 ( 65,112) |  35.3   5.2   8.7  30.8   9.3   3.9   5.6   0.9   0.1   0.1
 ( 65, 80) |  57.9   4.6   6.6  25.2   4.7   0.8   0.2   0.0   0.0   0.1
 ( 65,240) |  62.6   8.1  13.1   7.7   2.3   0.6   0.5   0.0   0.0   5.1
 ( 66,112) |  59.6   8.0  13.1   8.6   3.3   1.5   1.2   0.1   0.0   4.6
 ( 65,144) |  45.8   5.1   7.9  29.3   7.8   2.5   1.4   0.0   0.0   0.1
 ( 65,176) |  43.2   5.2   8.9  30.8   8.3   2.5   1.0   0.0   0.0   0.1
 ( 66, 16) |  77.0   5.4   7.4   3.3   0.7   0.3   0.7   0.1   0.0   5.0
 ( 65, 96) |  54.6   4.9   7.2  26.6   5.3   1.0   0.2   0.0   0.0   0.1
 ( 66, 48) |  71.0   6.8  10.5   5.4   0.9   0.1   0.1   0.0   0.0   5.2
 ( 65,208) |  43.5   5.6   8.5  31.0   7.2   2.2   1.9   0.0   0.0   0.1
 ( 66,128) |  69.5   7.0  10.3   6.2   1.5   0.3   0.1   0.0   0.0   5.0
 ( 65, 64) |  59.9   4.2   6.0  24.6   4.2   0.8   0.1   0.0   0.0   0.1
 ( 66, 64) |  62.6   8.1  12.7   7.9   2.4   0.6   0.1   0.0   0.0   5.4
========== | ===== ===== ===== ===== ===== ===== ===== ===== ===== =====
       AVG |  52.9   6.2  10.0  20.1   5.3   1.7   1.4   0.2   0.0   2.1

btt/Makefile
btt/devs.c
btt/doc/btt.tex
btt/globals.h
btt/output.c
btt/q2d.c [new file with mode: 0644]
btt/trace_issue.c

index 5281a94a41c58ad9788ef36a9fa8eabd0c11e79b..094f77f8fde2a79ee14ee2c69dd1e99b305c0b18 100644 (file)
@@ -17,7 +17,7 @@ LIBS  = $(PLIBS) $(ELIBS)
 OBJS   = args.o bt_timeline.o devmap.o devs.o dip_rb.o iostat.o latency.o \
          misc.o output.o proc.o seek.o trace.o trace_complete.o trace_im.o \
          trace_issue.o trace_queue.o trace_remap.o trace_requeue.o \
-         ../rbtree.o mmap.o trace_plug.o bno_dump.o unplug_hist.o
+         ../rbtree.o mmap.o trace_plug.o bno_dump.o unplug_hist.o q2d.o
 
 all: depend $(PROGS)
 
index 449d452e1d2208b10899f0729b6f6615b66b9a2f..6a0fcfc5ebf5fd83a8239b97c3f75b74a5fd5cd0 100644 (file)
@@ -131,6 +131,8 @@ void dip_exit(void)
                seeki_exit(dip->q2q_handle);
                bno_dump_exit(dip->bno_dump_handle);
                unplug_hist_exit(dip->unplug_hist_handle);
+               if (output_all_data)
+                       q2d_release(dip->q2d_priv);
                free(dip);
        }
 }
@@ -167,6 +169,8 @@ struct d_info *dip_add(__u32 device, struct io *iop)
                list_add_tail(&dip->all_head, &all_devs);
                dip->start_time = BIT_TIME(iop->t.time);
                dip->pre_culling = 1;
+               if (output_all_data)
+                       dip->q2d_priv = q2d_init();
                n_devs++;
        }
 
index f35cf1f072dd8c01f75f546e0ff753fa1d4ccf1a..3d3abd2921af98d0c08d12556429cba8c3ecbc70 100644 (file)
@@ -336,6 +336,27 @@ pdflush       0.000000790 0.000006752 0.247231307  179791
 
   \item[Per Device Averages] The average columns from the above charts,
   are also presented in their own chart.
+
+  \item[Q2D Histogram] A display of histogram buckets for the Q to D times
+  -- basically, from where an IO enters the block IO layer for a given
+  device, and when it is dispatched. The buckets are arranged via the
+  time in seconds, as in:
+
+\begin{verbatim}
+==================== Q2D Histogram ====================
+
+       DEV | <.005 <.010 <.025 <.050 <.075 <.100 <.250 <.500 < 1.0 >=1.0
+ --------- | ===== ===== ===== ===== ===== ===== ===== ===== ===== =====
+ ( 66, 80) |  61.2   7.9  12.1   7.9   3.0   1.4   1.5   0.2   0.0   4.6
+ ( 65,192) |  42.3   5.0   8.7  30.0   8.9   3.0   1.8   0.1   0.0   0.1
+ ( 65,128) |  34.3   5.3   8.9  32.0   9.7   3.7   5.3   0.6   0.0   0.1
+...
+ ( 65, 64) |  59.9   4.2   6.0  24.6   4.2   0.8   0.1   0.0   0.0   0.1
+ ( 66, 64) |  62.6   8.1  12.7   7.9   2.4   0.6   0.1   0.0   0.0   5.4
+========== | ===== ===== ===== ===== ===== ===== ===== ===== ===== =====
+       AVG |  52.9   6.2  10.0  20.1   5.3   1.7   1.4   0.2   0.0   2.1
+\end{verbatim}
+
 \end{description}
 
 \newpage\section{\label{sec:data-files}Data Files Output}
index 5a6db048d2b09154015eec27e497476896fd2e7b..4e8edc6597d7b507fb322d03f3fe01dbdc1753d3 100644 (file)
@@ -159,6 +159,7 @@ struct d_info {
        struct region_info regions;
        struct devmap *map;
        void *q2q_handle, *seek_handle, *bno_dump_handle, *unplug_hist_handle;
+       void *q2d_priv;
        FILE *d2c_ofp, *q2c_ofp;
        struct avgs_info avgs;
        struct stats stats, all_stats;
@@ -296,6 +297,16 @@ void bno_dump_exit(void *param);
 void bno_dump_add(void *handle, struct io *iop);
 void bno_dump_clean(void);
 
+/* q2d.c */
+void q2d_histo_add(void *priv, __u64 q2d);
+void *q2d_init(void);
+void q2d_release(void *priv);
+void q2d_display_header(FILE *fp);
+void q2d_display_dashes(FILE *fp);
+void q2d_display(FILE *fp, void *priv);
+int q2d_ok(void *priv);
+void q2d_acc(void *a1, void *a2);
+
 /* seek.c */
 void *seeki_init(char *str);
 void seeki_exit(void *param);
index ebfd3d835f4556927f1332f64a86f1a49b917a08..787de7069773f8dd40a077bcb4a843af3803e1d7 100644 (file)
@@ -133,6 +133,49 @@ void output_dip_avg(FILE *ofp, char *hdr, ai_dip_t (*func)(struct d_info *))
        fprintf(ofp, "\n");
 }
 
+struct __q2d {
+       FILE *ofp;
+       void *q2d_all;
+       int n;
+};
+void __output_q2d_histo(struct d_info *dip, void *arg)
+{
+       struct __q2d *q2dp = arg;
+
+       if (q2d_ok(dip->q2d_priv)) {
+               char scratch[15];
+               FILE *ofp = q2dp->ofp;
+
+               fprintf(q2dp->ofp, "%10s | ", make_dev_hdr(scratch, 15, dip));
+               q2d_display(ofp, dip->q2d_priv);
+               q2d_acc(q2dp->q2d_all, dip->q2d_priv);
+               q2dp->n++;
+       }
+}
+
+void output_q2d_histo(FILE *ofp)
+{
+       struct __q2d __q2d = {
+               .ofp = ofp,
+               .q2d_all = q2d_init(),
+               .n = 0
+       };
+
+       fprintf(ofp, "%10s | ", "DEV");
+       q2d_display_header(ofp);
+       fprintf(ofp, "--------- | ");
+       q2d_display_dashes(ofp);
+       dip_foreach_out(__output_q2d_histo, &__q2d);
+
+       if (__q2d.n) {
+               fprintf(ofp, "========== | ");
+               q2d_display_dashes(ofp);
+               fprintf(ofp, "%10s | ", "AVG");
+               q2d_display(ofp, __q2d.q2d_all);
+               fprintf(ofp, "\n");
+       }
+}
+
 int n_merges = 0;
 struct {
        unsigned long long nq, nd, blkmin, blkmax, total;
@@ -648,6 +691,11 @@ int output_avgs(FILE *ofp)
 
        output_histos();
 
+       if (output_all_data) {
+               output_section_hdr(ofp, "Q2D Histogram");
+               output_q2d_histo(ofp);
+       }
+
        return 0;
 }
 
diff --git a/btt/q2d.c b/btt/q2d.c
new file mode 100644 (file)
index 0000000..ae61e20
--- /dev/null
+++ b/btt/q2d.c
@@ -0,0 +1,121 @@
+/*
+ * blktrace output analysis: generate a timeline & gather statistics
+ *
+ * (C) Copyright 2007 Hewlett-Packard Development Company, L.P.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "globals.h"
+
+#define Q2D_MAX_HISTO 9
+struct q2d_info {
+       unsigned long nhistos;
+       unsigned long histos[Q2D_MAX_HISTO + 1];
+};
+
+void q2d_histo_add(void *priv, __u64 q2d_in)
+{
+       int index;
+       struct q2d_info *q2dp = priv;
+       double q2d = BIT_TIME(q2d_in);
+       long msec = (long)(q2d / 0.001);
+
+       switch (msec) {
+       default:          index = 9; break;
+       case 500 ... 999: index = 8; break;
+       case 250 ... 499: index = 7; break;
+       case 100 ... 249: index = 6; break;
+       case  75 ...  99: index = 5; break;
+       case  50 ...  74: index = 4; break;
+       case  25 ...  49: index = 3; break;
+       case  10 ...  24: index = 2; break;
+       case   5 ...   9: index = 1; break;
+       case   0 ...   4: index = 0; break;
+       }
+
+       q2dp->histos[index]++;
+       q2dp->nhistos++;
+}
+
+void *q2d_init(void)
+{
+       struct q2d_info *q2dp = malloc(sizeof(*q2dp));
+
+       return memset(q2dp, 0, sizeof(*q2dp));
+}
+
+void q2d_release(void *priv)
+{
+       free(priv);
+}
+
+void q2d_display_header(FILE *fp)
+{
+       fprintf(fp, "%5s ", "<.005");
+       fprintf(fp, "%5s ", "<.010");
+       fprintf(fp, "%5s ", "<.025");
+       fprintf(fp, "%5s ", "<.050");
+       fprintf(fp, "%5s ", "<.075");
+       fprintf(fp, "%5s ", "<.100");
+       fprintf(fp, "%5s ", "<.250");
+       fprintf(fp, "%5s ", "<.500");
+       fprintf(fp, "%5s ", "< 1.0");
+       fprintf(fp, "%5s ", ">=1.0\n");
+}
+
+void q2d_display_dashes(FILE *fp)
+{
+       int i;
+
+       for (i = 0; i <= Q2D_MAX_HISTO; i++)
+               fprintf(fp, "===== ");
+       fprintf(fp, "\n");
+}
+
+void q2d_display(FILE *fp, void *priv)
+{
+       int i;
+       struct q2d_info *q2dp = priv;
+       double nh = (double)q2dp->nhistos;
+
+       for (i = 0; i <= Q2D_MAX_HISTO; i++) {
+               double p = 100.0 * (double)q2dp->histos[i] / nh;
+               fprintf(fp, "%5.1lf ", p);
+       }
+       fprintf(fp, "\n");
+}
+
+int q2d_ok(void *priv)
+{
+       struct q2d_info *q2dp = priv;
+
+       return q2dp && q2dp->nhistos > 0;
+}
+
+void q2d_acc(void *a1, void *a2)
+{
+       int i;
+       struct q2d_info *ap = a1;
+       struct q2d_info *tp = a2;
+
+       for (i = 0; i <= Q2D_MAX_HISTO; i++)
+               ap->histos[i] += tp->histos[i];
+       ap->nhistos += tp->nhistos;
+}
index fd7ea494c32f28d4f5446932051fa2f5b010aaca..418afd0f1d87fbe60d09d170118d6d605e52018d 100644 (file)
@@ -46,6 +46,10 @@ static void handle_issue(struct io *d_iop)
                q_iop->d_time = d_iop->t.time;
                q_iop->d_sec = d_iop->t.sector;
                q_iop->d_nsec = t_sec(&d_iop->t);
+
+               if (output_all_data)
+                       q2d_histo_add(q_iop->dip->q2d_priv, 
+                                               d_iop->t.time - q_iop->t.time);
        }
 
        assert(d_iop->bytes_left == 0);