Added -X option - generate easily parseable file
authorAlan D. Brunelle <alan.brunelle@hp.com>
Thu, 8 May 2008 19:28:32 +0000 (15:28 -0400)
committerAlan D. Brunelle <alan.brunelle@hp.com>
Thu, 8 May 2008 19:28:32 +0000 (15:28 -0400)
Writes a portion of the default output into a separate file that more
easily parsed.

btt/args.c
btt/bt_timeline.c
btt/doc/btt.tex
btt/globals.h
btt/output.c

index 5930f14ba60683ab088658affdede21a10ab4544..6003f43471dfdc82cb8d99ca37bd38a7eb13fcee 100644 (file)
@@ -29,7 +29,7 @@
 
 #define SETBUFFER_SIZE (64 * 1024)
 
-#define S_OPTS "aAB:d:D:e:hi:I:l:M:o:p:q:s:S:t:T:u:Vv"
+#define S_OPTS "aAB:d:D:e:hi:I:l:M:o:p:q:s:S:t:T:u:VvX"
 static struct option l_opts[] = {
        {
                .name = "seek-absolute",
@@ -157,6 +157,12 @@ static struct option l_opts[] = {
                .flag = NULL,
                .val = 'v'
        },
+       {
+               .name = "easy-parse-avgs",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'X'
+       },
        {
                .name = NULL,
        }
@@ -181,9 +187,11 @@ static char usage_str[] = \
        "[ -S <interval>    | --iostat-interval=<interval> ]\n" \
        "[ -t <sec>         | --time-start=<sec> ]\n" \
        "[ -T <sec>         | --time-end=<sec> ]\n" \
-       "[ -u <output name> | --unplug-hist=<output name> ] \n" \
+       "[ -u <output name> | --unplug-hist=<output name> ]\n" \
        "[ -V               | --version ]\n" \
-       "[ -v               | --verbose ]\n\n";
+       "[ -v               | --verbose ]\n" \
+       "[ -X               | --easy-parse-avgs ]\n" \
+       "\n";
 
 static struct file_info *arg_files = NULL;
 
@@ -295,6 +303,9 @@ void handle_args(int argc, char *argv[])
                case 'V':
                        printf("%s version %s\n", argv[0], bt_timeline_version);
                        exit(0);
+               case 'X':
+                       easy_parse_avgs++;
+                       break;
                default:
                        usage(argv[0]);
                        exit(1);
@@ -308,8 +319,10 @@ void handle_args(int argc, char *argv[])
 
        setup_ifile(input_name);
 
-       if (output_name == NULL)
+       if (output_name == NULL) {
                ranges_ofp = avgs_ofp = stdout;
+               easy_parse_avgs = 0;
+       }
        else {
                char *fname = malloc(strlen(output_name) + 32);
 
@@ -320,7 +333,7 @@ void handle_args(int argc, char *argv[])
                        exit(1);
                }
                if (verbose)
-                       printf("Sending range data to %s.dat\n", output_name);
+                       printf("Sending range data to %s\n", fname);
 
                sprintf(fname, "%s.avg", output_name);
                avgs_ofp = fopen(fname, "w");
@@ -329,7 +342,18 @@ void handle_args(int argc, char *argv[])
                        exit(1);
                }
                if (verbose)
-                       printf("Sending stats data to %s.avg\n", output_name);
+                       printf("Sending stats data to %s\n", fname);
+
+               if (easy_parse_avgs) {
+                       sprintf(fname, "%s.xvg", output_name);
+                       xavgs_ofp = fopen(fname, "w");
+                       if (avgs_ofp == NULL) {
+                               perror(fname);
+                               exit(1);
+                       }
+                       if (verbose)
+                               printf("Sending X stats data to %s\n", fname);
+               }
 
                free(fname);
        }
index 30b1e6e8d07e592aebf7406cb26f5a4b1c7cade6..f3483f0c52ffc14248d18d5221e57fac8ab1a81a 100644 (file)
 #include <time.h>
 #include "globals.h"
 
-char bt_timeline_version[] = "2.02";
+char bt_timeline_version[] = "2.03";
 
 char *devices, *exes, *input_name, *output_name, *seek_name, *bno_dump_name;
 char *d2c_name, *q2c_name, *per_io_name, *unplug_hist_name;
-FILE *ranges_ofp, *avgs_ofp, *per_io_ofp;
+FILE *ranges_ofp, *avgs_ofp, *xavgs_ofp, *per_io_ofp;
 int verbose, done, time_bounded, output_all_data, seek_absolute;
+int easy_parse_avgs;
 double t_astart, t_aend;
 unsigned long n_traces;
 struct avgs_info all_avgs;
index f549e73696e4d98df06a73c6342f5c66108098c4..4adcbbafe7d3115ac55a24f392fb99570c00ea07 100644 (file)
@@ -439,10 +439,16 @@ pdflush       0.000000790 0.000006752 0.247231307  179791
 
 \end{description}
 
-  Besides the default data files output, there are optional data files
-  which can be generated by btt. These include:
+  In addition to the default data files output, there are optional data
+  files which can be generated by btt. These include:
 
   \begin{description}
+    \item[subset of \texttt{.avg} data, easily parsed ] When the
+    \texttt{-X} option is specified \emph{and} the \texttt{-o} has also
+    been specified, then a subset of the data produced by default is
+    copied to another file that is \emph{more easily parsed.} Refer to
+    section~\ref{sec:o-X} for full details.
+
     \item[iostat] iostat-like data can be distilled by btt, and is
     described in section~\ref{sec:iostat}.
 
@@ -754,7 +760,7 @@ Device:       rrqm/s   wrqm/s     r/s     w/s    rsec/s    wsec/s
 \newpage\section{\label{sec:cmd-line}Command Line}
 
 \begin{verbatim}
-Usage: btt 2.01
+Usage: btt 2.03
 [ -a               | --seek-absolute ]
 [ -A               | --all-data ]
 [ -B <output name> | --dump-blocknos=<output name> ]
@@ -776,6 +782,7 @@ Usage: btt 2.01
 [ -u <output name> | --unplug-hist=<output name> ]
 [ -V               | --version ]
 [ -v               | --verbose ]
+[ -X               | --easy-parse-avgs ]
 \end{verbatim}
 
 \subsection{\label{sec:o-a}\texttt{--seek-absolute}/\texttt{-a}}
@@ -958,6 +965,49 @@ Sending stats data to bttX.avg
 16.379036+0.000005=16.379041
 \end{verbatim}
 
+\subsection{\label{sec:o-X}\texttt{--easy-parse-avgs}/\texttt{-X}}
+
+  \emph{Some} of the data produced by default can also be shipped
+  simultaneously to another file in an easy to parse form. When
+  the \texttt{-o} option is selected (thus producing a file with a
+  \texttt{.avg} exentsion), \emph{and} the \texttt{-X} flag is present,
+  then \texttt{btt} will generate this file.
+
+  The format is space-delimited values starting with a 3-character
+  \emph{record} indicator, then the device information (either major,minor
+  or the device name when \texttt{-M} is specified), and then a number of
+  fields representing data values. The following table shows the record
+  identifiers and the fields provided:
+
+  \bigskip
+  \begin{tabular}{|l|l|}\hline
+  \textbf{Record} & \textbf{Description}\\\hline
+  \texttt{DMI} & Device Merge Information:\\
+               & \#Q \#D Ratio BLKmin BLKavg BLKmax Total\\\hline
+  \texttt{QSK} & Device Q2Q Seek Information:\\
+               & NSEEKS MEAN MEDIAN MODE N-MODE mode\ldots\\\hline
+  \texttt{DSK} & Device D2D Seek Information:\\
+               & NSEEKS MEAN MEDIAN MODE N-MODE mode\ldots\\\hline
+  \texttt{PLG} & Plug Information:\\
+               & \#Plugs \#TimerUnplugs \%TimeQPlugged\\\hline
+  \texttt{UPG} & Unplug Information:\\
+               & IOsPerUnplug IOsPerUnplugTimeout\\\hline
+  \texttt{ARQ} & Active Requests at Q Information:\\
+               & AvgReqs@Q\\\hline
+  \end{tabular}
+
+  \bigskip
+  A sample output file would look like:
+
+  \begin{verbatim}
+DMI 8,16 310407 106729 2.908366049 0 182 1024 19504768
+QSK 8,16 310407 167141.958551192 0 0 235753
+DSK 8,16 106729 433247.436563633 0 0 33974
+PLG 8,16 40824 382 0.008882101
+UPG 8,16 1.993361748 1.866492147
+ARQ 8,16 22.863331046
+  \end{verbatim}
+
 \newpage\section{\label{sec:bno_plot}bno\_plot.py}
 
 Included with the distribution is a simple 3D plotting utility based
index 52fb8b0332d169b7c37f88aaecc039882a63265e..887353d2216a085fd86d9705060d8c05cbd3ec65 100644 (file)
@@ -179,8 +179,9 @@ extern char bt_timeline_version[], *devices, *exes, *input_name, *output_name;
 extern char *seek_name, *iostat_name, *d2c_name, *q2c_name, *per_io_name;
 extern char *bno_dump_name, *unplug_hist_name;
 extern double range_delta;
-extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp, *per_io_ofp;
+extern FILE *ranges_ofp, *avgs_ofp, *xavgs_ofp, *iostat_ofp, *per_io_ofp;
 extern int verbose, done, time_bounded, output_all_data, seek_absolute;
+extern int easy_parse_avgs;
 extern unsigned int n_devs;
 extern unsigned long n_traces;
 extern struct list_head all_devs, all_procs;
index a3c887f5a240318088010a7692f0688811ce6ea8..3de9cce6ed6c6f957ca0cd4808e48dc3b0d74ae7 100644 (file)
@@ -92,6 +92,17 @@ char *make_dev_hdr(char *pad, size_t len, struct d_info *dip)
        return pad;
 }
 
+char *make_dev_hdrX(char *pad, size_t len, struct d_info *dip)
+{
+       if (dip->map == NULL)
+               snprintf(pad, len, "%d,%d",
+                        MAJOR(dip->device), MINOR(dip->device));
+       else
+               snprintf(pad, len, "%s", dip->map->device);
+
+       return pad;
+}
+
 struct __oda {
        FILE *ofp;
        ai_dip_t (*func)(struct d_info *);
@@ -125,10 +136,10 @@ void __output_q2d_histo(struct d_info *dip, void *arg)
        struct __q2d *q2dp = arg;
 
        if (q2d_ok(dip->q2d_priv)) {
-               char scratch[15];
+               char dev_info[15];
                FILE *ofp = q2dp->ofp;
 
-               fprintf(q2dp->ofp, "%10s | ", make_dev_hdr(scratch, 15, dip));
+               fprintf(q2dp->ofp, "%10s | ", make_dev_hdr(dev_info, 15, dip));
                q2d_display(ofp, dip->q2d_priv);
                q2d_acc(q2dp->q2d_all, dip->q2d_priv);
                q2dp->n++;
@@ -165,7 +176,7 @@ struct {
 void __output_dip_merge_ratio(struct d_info *dip, void *arg)
 {
        double blks_avg;
-       char scratch[15];
+       char dev_info[15];
        double ratio, q2c_n, d2c_n;
 
        if (dip->n_qs == 0 || dip->n_ds == 0)
@@ -183,7 +194,7 @@ void __output_dip_merge_ratio(struct d_info *dip, void *arg)
                blks_avg = (double)dip->avgs.blks.total / d2c_n;
                fprintf((FILE *)arg,
                        "%10s | %8llu %8llu %7.1lf | %8llu %8llu %8llu %8llu\n",
-                       make_dev_hdr(scratch, 15, dip),
+                       make_dev_hdr(dev_info, 15, dip),
                        (unsigned long long)dip->n_qs,
                        (unsigned long long)dip->n_ds,
                        ratio,
@@ -192,6 +203,19 @@ void __output_dip_merge_ratio(struct d_info *dip, void *arg)
                        (unsigned long long)dip->avgs.blks.max,
                        (unsigned long long)dip->avgs.blks.total);
 
+               if (easy_parse_avgs) {
+                       fprintf(xavgs_ofp,
+                               "DMI %s %llu %llu %.9lf %llu %llu %llu %llu\n",
+                               make_dev_hdrX(dev_info, 15, dip),
+                               (unsigned long long)dip->n_qs,
+                               (unsigned long long)dip->n_ds,
+                               ratio,
+                               (unsigned long long)dip->avgs.blks.min,
+                               (unsigned long long)blks_avg,
+                               (unsigned long long)dip->avgs.blks.max,
+                               (unsigned long long)dip->avgs.blks.total);
+               }
+
                if (n_merges++ == 0) {
                        merge_data.blkmin = dip->avgs.blks.min;
                        merge_data.blkmax = dip->avgs.blks.max;
@@ -426,6 +450,18 @@ static void do_output_dip_seek_info(struct d_info *dip, FILE *ofp, int is_q2q)
                        fprintf(ofp, " %lld", m.modes[i]);
                fprintf(ofp, "\n");
 
+               if (easy_parse_avgs) {
+                       char *rec = is_q2q ? "QSK" : "DSK";
+                       fprintf(xavgs_ofp,
+                               "%s %s %lld %.9lf %lld %lld %d",
+                               rec, make_dev_hdrX(dev_info, 15, dip),
+                               nseeks, mean, median,
+                               nmodes > 0 ? m.modes[0] : 0, m.most_seeks);
+                               for (i = 1; i < nmodes; i++)
+                                       fprintf(xavgs_ofp, " %lld", m.modes[i]);
+                               fprintf(xavgs_ofp, "\n");
+               }
+
                seek_info.nseeks += nseeks;
                seek_info.mean += (nseeks * mean);
                seek_info.median += (nseeks * median);
@@ -531,6 +567,13 @@ void __dip_output_plug(struct d_info *dip, void *arg)
                        make_dev_hdr(dev_info, 15, dip),
                        dip->nplugs, dip->n_timer_unplugs, pct);
 
+               if (easy_parse_avgs) {
+                       fprintf(xavgs_ofp,
+                               "PLG %s %d %d %.9lf\n",
+                               make_dev_hdrX(dev_info, 15, dip),
+                               dip->nplugs, dip->n_timer_unplugs, pct);
+               }
+
                n_plugs++;
                plug_info.n_plugs += dip->nplugs;
                plug_info.n_timer_unplugs += dip->n_timer_unplugs;
@@ -574,6 +617,13 @@ void __dip_output_plug_nios(struct d_info *dip, void *arg)
        fprintf(ofp, "%10s | %10.1lf   %10.1lf\n",
                make_dev_hdr(dev_info, 15, dip),
                a_nios_uplug, a_nios_uplug_t);
+
+       if (easy_parse_avgs) {
+               fprintf(xavgs_ofp,
+                       "UPG %s %.9lf %.9lf\n",
+                       make_dev_hdrX(dev_info, 15, dip),
+                       a_nios_uplug, a_nios_uplug_t);
+       }
 }
 
 void __dip_output_uplug_all(FILE *ofp, struct nios_plug_info *p)
@@ -626,6 +676,12 @@ void __dip_output_actQ(struct d_info *dip, void *arg)
                fprintf((FILE *)arg, "%10s | %13.1lf\n",
                        make_dev_hdr(dev_info, 15, dip), a_actQs);
 
+               if (easy_parse_avgs) {
+                       fprintf(xavgs_ofp,
+                               "ARQ %s %.9lf\n",
+                               make_dev_hdrX(dev_info, 15, dip), a_actQs);
+               }
+
                n_actQs++;
                actQ_info.t_qs += dip->n_qs;
                actQ_info.t_act_qs += dip->t_act_q;