perf stat: New metricgroup output for the default mode
[linux-2.6-microblaze.git] / tools / perf / util / stat-display.c
index a2bbdc2..7329b33 100644 (file)
@@ -25,6 +25,7 @@
 #define CNTR_NOT_SUPPORTED     "<not supported>"
 #define CNTR_NOT_COUNTED       "<not counted>"
 
+#define MGROUP_LEN   50
 #define METRIC_LEN   38
 #define EVNAME_LEN   32
 #define COUNTS_LEN   18
@@ -364,16 +365,27 @@ static void new_line_std(struct perf_stat_config *config __maybe_unused,
        os->newline = true;
 }
 
-static void do_new_line_std(struct perf_stat_config *config,
-                           struct outstate *os)
+static inline void __new_line_std_csv(struct perf_stat_config *config,
+                                     struct outstate *os)
 {
        fputc('\n', os->fh);
        if (os->prefix)
                fputs(os->prefix, os->fh);
        aggr_printout(config, os->evsel, os->id, os->aggr_nr);
+}
+
+static inline void __new_line_std(struct outstate *os)
+{
+       fprintf(os->fh, "                                                 ");
+}
+
+static void do_new_line_std(struct perf_stat_config *config,
+                           struct outstate *os)
+{
+       __new_line_std_csv(config, os);
        if (config->aggr_mode == AGGR_NONE)
                fprintf(os->fh, "        ");
-       fprintf(os->fh, "                                                 ");
+       __new_line_std(os);
 }
 
 static void print_metric_std(struct perf_stat_config *config,
@@ -408,10 +420,7 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx)
        struct outstate *os = ctx;
        int i;
 
-       fputc('\n', os->fh);
-       if (os->prefix)
-               fprintf(os->fh, "%s", os->prefix);
-       aggr_printout(config, os->evsel, os->id, os->aggr_nr);
+       __new_line_std_csv(config, os);
        for (i = 0; i < os->nfields; i++)
                fputs(config->csv_sep, os->fh);
 }
@@ -462,6 +471,54 @@ static void new_line_json(struct perf_stat_config *config, void *ctx)
        aggr_printout(config, os->evsel, os->id, os->aggr_nr);
 }
 
+static void print_metricgroup_header_json(struct perf_stat_config *config,
+                                         void *ctx,
+                                         const char *metricgroup_name)
+{
+       if (!metricgroup_name)
+               return;
+
+       fprintf(config->output, "\"metricgroup\" : \"%s\"}", metricgroup_name);
+       new_line_json(config, ctx);
+}
+
+static void print_metricgroup_header_csv(struct perf_stat_config *config,
+                                        void *ctx,
+                                        const char *metricgroup_name)
+{
+       struct outstate *os = ctx;
+       int i;
+
+       if (!metricgroup_name) {
+               /* Leave space for running and enabling */
+               for (i = 0; i < os->nfields - 2; i++)
+                       fputs(config->csv_sep, os->fh);
+               return;
+       }
+
+       for (i = 0; i < os->nfields; i++)
+               fputs(config->csv_sep, os->fh);
+       fprintf(config->output, "%s", metricgroup_name);
+       new_line_csv(config, ctx);
+}
+
+static void print_metricgroup_header_std(struct perf_stat_config *config,
+                                        void *ctx,
+                                        const char *metricgroup_name)
+{
+       struct outstate *os = ctx;
+       int n;
+
+       if (!metricgroup_name) {
+               __new_line_std(os);
+               return;
+       }
+
+       n = fprintf(config->output, " %*s", EVNAME_LEN, metricgroup_name);
+
+       fprintf(config->output, "%*s", MGROUP_LEN - n - 1, "");
+}
+
 /* Filter out some columns that don't work well in metrics only mode */
 
 static bool valid_only_metric(const char *unit)
@@ -713,19 +770,23 @@ static void printout(struct perf_stat_config *config, struct outstate *os,
        struct perf_stat_output_ctx out;
        print_metric_t pm;
        new_line_t nl;
+       print_metricgroup_header_t pmh;
        bool ok = true;
        struct evsel *counter = os->evsel;
 
        if (config->csv_output) {
                pm = config->metric_only ? print_metric_only_csv : print_metric_csv;
                nl = config->metric_only ? new_line_metric : new_line_csv;
+               pmh = print_metricgroup_header_csv;
                os->nfields = 4 + (counter->cgrp ? 1 : 0);
        } else if (config->json_output) {
                pm = config->metric_only ? print_metric_only_json : print_metric_json;
                nl = config->metric_only ? new_line_metric : new_line_json;
+               pmh = print_metricgroup_header_json;
        } else {
                pm = config->metric_only ? print_metric_only : print_metric_std;
                nl = config->metric_only ? new_line_metric : new_line_std;
+               pmh = print_metricgroup_header_std;
        }
 
        if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
@@ -747,10 +808,11 @@ static void printout(struct perf_stat_config *config, struct outstate *os,
 
        out.print_metric = pm;
        out.new_line = nl;
+       out.print_metricgroup_header = pmh;
        out.ctx = os;
        out.force_header = false;
 
-       if (!config->metric_only) {
+       if (!config->metric_only && !counter->default_metricgroup) {
                abs_printout(config, os->id, os->aggr_nr, counter, uval, ok);
 
                print_noise(config, counter, noise, /*before_metric=*/true);
@@ -758,8 +820,31 @@ static void printout(struct perf_stat_config *config, struct outstate *os,
        }
 
        if (ok) {
-               perf_stat__print_shadow_stats(config, counter, uval, aggr_idx,
-                                             &out, &config->metric_events);
+               if (!config->metric_only && counter->default_metricgroup) {
+                       void *from = NULL;
+
+                       aggr_printout(config, os->evsel, os->id, os->aggr_nr);
+                       /* Print out all the metricgroup with the same metric event. */
+                       do {
+                               int num = 0;
+
+                               /* Print out the new line for the next new metricgroup. */
+                               if (from) {
+                                       if (config->json_output)
+                                               new_line_json(config, (void *)os);
+                                       else
+                                               __new_line_std_csv(config, os);
+                               }
+
+                               print_noise(config, counter, noise, /*before_metric=*/true);
+                               print_running(config, run, ena, /*before_metric=*/true);
+                               from = perf_stat__print_shadow_stats_metricgroup(config, counter, aggr_idx,
+                                                                                &num, from, &out,
+                                                                                &config->metric_events);
+                       } while (from != NULL);
+               } else
+                       perf_stat__print_shadow_stats(config, counter, uval, aggr_idx,
+                                                     &out, &config->metric_events);
        } else {
                pm(config, os, /*color=*/NULL, /*format=*/NULL, /*unit=*/"", /*val=*/0);
        }
@@ -889,6 +974,9 @@ static void print_counter_aggrdata(struct perf_stat_config *config,
        ena = aggr->counts.ena;
        run = aggr->counts.run;
 
+       if (perf_stat__skip_metric_event(counter, &config->metric_events, ena, run))
+               return;
+
        if (val == 0 && should_skip_zero_counter(config, counter, &id))
                return;