]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - tools/perf/builtin-stat.c
perf stat: Align scaled output of cpu-clock
[mirror_ubuntu-zesty-kernel.git] / tools / perf / builtin-stat.c
index 7ce65f52415e0799f060d35d67290fac196dfb12..d14b37ad7638b189532e746e2f27fbc4a46de792 100644 (file)
@@ -278,9 +278,14 @@ struct stats                       runtime_itlb_cache_stats[MAX_NR_CPUS];
 struct stats                   runtime_dtlb_cache_stats[MAX_NR_CPUS];
 struct stats                   walltime_nsecs_stats;
 
-static int create_perf_stat_counter(struct perf_evsel *evsel)
+static int create_perf_stat_counter(struct perf_evsel *evsel,
+                                   struct perf_evsel *first)
 {
        struct perf_event_attr *attr = &evsel->attr;
+       struct xyarray *group_fd = NULL;
+
+       if (group && evsel != first)
+               group_fd = first->fd;
 
        if (scale)
                attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -289,14 +294,15 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
        attr->inherit = !no_inherit;
 
        if (system_wide)
-               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, group);
-
+               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
+                                               group, group_fd);
        if (target_pid == -1 && target_tid == -1) {
                attr->disabled = 1;
                attr->enable_on_exec = 1;
        }
 
-       return perf_evsel__open_per_thread(evsel, evsel_list->threads, group);
+       return perf_evsel__open_per_thread(evsel, evsel_list->threads,
+                                          group, group_fd);
 }
 
 /*
@@ -396,7 +402,7 @@ static int read_counter(struct perf_evsel *counter)
 static int run_perf_stat(int argc __used, const char **argv)
 {
        unsigned long long t0, t1;
-       struct perf_evsel *counter;
+       struct perf_evsel *counter, *first;
        int status = 0;
        int child_ready_pipe[2], go_pipe[2];
        const bool forks = (argc > 0);
@@ -453,9 +459,12 @@ static int run_perf_stat(int argc __used, const char **argv)
                close(child_ready_pipe[0]);
        }
 
+       first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
+
        list_for_each_entry(counter, &evsel_list->entries, node) {
-               if (create_perf_stat_counter(counter) < 0) {
-                       if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) {
+               if (create_perf_stat_counter(counter, first) < 0) {
+                       if (errno == EINVAL || errno == ENOSYS ||
+                           errno == ENOENT || errno == EOPNOTSUPP) {
                                if (verbose)
                                        ui__warning("%s event is not supported by the kernel.\n",
                                                    event_name(counter));
@@ -567,6 +576,35 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
        if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
                fprintf(output, " # %8.3f CPUs utilized          ",
                        avg / avg_stats(&walltime_nsecs_stats));
+       else
+               fprintf(output, "                                   ");
+}
+
+/* used for get_ratio_color() */
+enum grc_type {
+       GRC_STALLED_CYCLES_FE,
+       GRC_STALLED_CYCLES_BE,
+       GRC_CACHE_MISSES,
+       GRC_MAX_NR
+};
+
+static const char *get_ratio_color(enum grc_type type, double ratio)
+{
+       static const double grc_table[GRC_MAX_NR][3] = {
+               [GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 },
+               [GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 },
+               [GRC_CACHE_MISSES]      = { 20.0, 10.0, 5.0 },
+       };
+       const char *color = PERF_COLOR_NORMAL;
+
+       if (ratio > grc_table[type][0])
+               color = PERF_COLOR_RED;
+       else if (ratio > grc_table[type][1])
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > grc_table[type][2])
+               color = PERF_COLOR_YELLOW;
+
+       return color;
 }
 
 static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -579,13 +617,7 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 50.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 30.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -602,13 +634,7 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 75.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 50.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 20.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -625,13 +651,7 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 20.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -648,13 +668,7 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 20.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -671,13 +685,7 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 20.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -694,13 +702,7 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 20.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -717,13 +719,7 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 20.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -740,13 +736,7 @@ static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, doub
        if (total)
                ratio = avg / total * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 20.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 10.0)
-               color = PERF_COLOR_MAGENTA;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
+       color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
        fprintf(output, " #  ");
        color_fprintf(output, color, "%6.2f%%", ratio);
@@ -856,12 +846,18 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
 
                fprintf(output, " # %8.3f GHz                    ", ratio);
        } else if (runtime_nsecs_stats[cpu].n != 0) {
+               char unit = 'M';
+
                total = avg_stats(&runtime_nsecs_stats[cpu]);
 
                if (total)
                        ratio = 1000.0 * avg / total;
+               if (ratio < 0.001) {
+                       ratio *= 1000;
+                       unit = 'K';
+               }
 
-               fprintf(output, " # %8.3f M/sec                  ", ratio);
+               fprintf(output, " # %8.3f %c/sec                  ", ratio, unit);
        } else {
                fprintf(output, "                                   ");
        }
@@ -1099,22 +1095,13 @@ static const struct option options[] = {
  */
 static int add_default_attributes(void)
 {
-       struct perf_evsel *pos;
-       size_t attr_nr = 0;
-       size_t c;
-
        /* Set attrs if no event is selected and !null_run: */
        if (null_run)
                return 0;
 
        if (!evsel_list->nr_entries) {
-               for (c = 0; c < ARRAY_SIZE(default_attrs); c++) {
-                       pos = perf_evsel__new(default_attrs + c, c + attr_nr);
-                       if (pos == NULL)
-                               return -1;
-                       perf_evlist__add(evsel_list, pos);
-               }
-               attr_nr += c;
+               if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0)
+                       return -1;
        }
 
        /* Detailed events get appended to the event list: */
@@ -1123,38 +1110,21 @@ static int add_default_attributes(void)
                return 0;
 
        /* Append detailed run extra attributes: */
-       for (c = 0; c < ARRAY_SIZE(detailed_attrs); c++) {
-               pos = perf_evsel__new(detailed_attrs + c, c + attr_nr);
-               if (pos == NULL)
-                       return -1;
-               perf_evlist__add(evsel_list, pos);
-       }
-       attr_nr += c;
+       if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0)
+               return -1;
 
        if (detailed_run < 2)
                return 0;
 
        /* Append very detailed run extra attributes: */
-       for (c = 0; c < ARRAY_SIZE(very_detailed_attrs); c++) {
-               pos = perf_evsel__new(very_detailed_attrs + c, c + attr_nr);
-               if (pos == NULL)
-                       return -1;
-               perf_evlist__add(evsel_list, pos);
-       }
+       if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0)
+               return -1;
 
        if (detailed_run < 3)
                return 0;
 
        /* Append very, very detailed run extra attributes: */
-       for (c = 0; c < ARRAY_SIZE(very_very_detailed_attrs); c++) {
-               pos = perf_evsel__new(very_very_detailed_attrs + c, c + attr_nr);
-               if (pos == NULL)
-                       return -1;
-               perf_evlist__add(evsel_list, pos);
-       }
-
-
-       return 0;
+       return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs);
 }
 
 int cmd_stat(int argc, const char **argv, const char *prefix __used)
@@ -1239,7 +1209,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
        if (target_pid != -1)
                target_tid = target_pid;
 
-       evsel_list->threads = thread_map__new(target_pid, target_tid);
+       evsel_list->threads = thread_map__new(target_pid, target_tid, UINT_MAX);
        if (evsel_list->threads == NULL) {
                pr_err("Problems finding threads of monitor\n");
                usage_with_options(stat_usage, options);
@@ -1258,8 +1228,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
 
        list_for_each_entry(pos, &evsel_list->entries, node) {
                if (perf_evsel__alloc_stat_priv(pos) < 0 ||
-                   perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
-                   perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
+                   perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0)
                        goto out_free_fd;
        }