perf_counter tools: report: Implement header output for --sort variants
[deliverable/linux.git] / Documentation / perf_counter / builtin-report.c
index a634022bae079c7e6d75c01a4bfeccddaf307d9e..506cde437b785197e9c2ffe6fd091fbb69ac5e16 100644 (file)
@@ -596,8 +596,6 @@ out_delete:
 
 struct thread;
 
-static const char *thread__name(struct thread *self, char *bf, size_t size);
-
 struct thread {
        struct rb_node   rb_node;
        struct list_head maps;
@@ -605,15 +603,6 @@ struct thread {
        char             *comm;
 };
 
-static const char *thread__name(struct thread *self, char *bf, size_t size)
-{
-       if (self->comm)
-               return self->comm;
-
-       snprintf(bf, sizeof(bf), ":%u", self->pid);
-       return bf;
-}
-
 static struct thread *thread__new(pid_t pid)
 {
        struct thread *self = malloc(sizeof(*self));
@@ -707,6 +696,8 @@ struct hist_entry {
 struct sort_entry {
        struct list_head list;
 
+       char *header;
+
        int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
        size_t  (*print)(FILE *fp, struct hist_entry *);
 };
@@ -720,13 +711,11 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
 static size_t
 sort__thread_print(FILE *fp, struct hist_entry *self)
 {
-       char bf[32];
-
-       return fprintf(fp, "%14s ",
-                       thread__name(self->thread, bf, sizeof(bf)));
+       return fprintf(fp, " %16s:%5d", self->thread->comm ?: "", self->thread->pid);
 }
 
 static struct sort_entry sort_thread = {
+       .header = "         Command: Pid ",
        .cmp    = sort__thread_cmp,
        .print  = sort__thread_print,
 };
@@ -752,14 +741,45 @@ sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
 static size_t
 sort__comm_print(FILE *fp, struct hist_entry *self)
 {
-       return fprintf(fp, "%20s ", self->thread->comm ?: "<unknown>");
+       return fprintf(fp, " %16s", self->thread->comm ?: "<unknown>");
 }
 
 static struct sort_entry sort_comm = {
+       .header = "         Command",
        .cmp    = sort__comm_cmp,
        .print  = sort__comm_print,
 };
 
+static int64_t
+sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       struct dso *dso_l = left->dso;
+       struct dso *dso_r = right->dso;
+
+       if (!dso_l || !dso_r) {
+               if (!dso_l && !dso_r)
+                       return 0;
+               else if (!dso_l)
+                       return -1;
+               else
+                       return 1;
+       }
+
+       return strcmp(dso_l->name, dso_r->name);
+}
+
+static size_t
+sort__dso_print(FILE *fp, struct hist_entry *self)
+{
+       return fprintf(fp, " %64s", self->dso ? self->dso->name : "<unknown>");
+}
+
+static struct sort_entry sort_dso = {
+       .header = "                                                    Shared Object",
+       .cmp    = sort__dso_cmp,
+       .print  = sort__dso_print,
+};
+
 static int64_t
 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -779,23 +799,18 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
 {
        size_t ret = 0;
 
-       ret += fprintf(fp, "[%c] ", self->level);
-
        if (verbose)
-               ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
+               ret += fprintf(fp, " %#018llx", (unsigned long long)self->ip);
 
-       if (self->level != '.')
-               ret += fprintf(fp, "%s ",
-                              self->sym ? self->sym->name : "<unknown>");
-       else
-               ret += fprintf(fp, "%s: %s ",
-                              self->dso ? self->dso->name : "<unknown>",
-                              self->sym ? self->sym->name : "<unknown>");
+       ret += fprintf(fp, " %s: %s",
+                       self->dso ? self->dso->name : "<unknown>",
+                       self->sym ? self->sym->name : "<unknown>");
 
        return ret;
 }
 
 static struct sort_entry sort_sym = {
+       .header = "Shared Object: Symbol",
        .cmp    = sort__sym_cmp,
        .print  = sort__sym_print,
 };
@@ -809,6 +824,7 @@ struct sort_dimension {
 static struct sort_dimension sort_dimensions[] = {
        { .name = "pid",        .entry = &sort_thread,  },
        { .name = "comm",       .entry = &sort_comm,    },
+       { .name = "dso",        .entry = &sort_dso,     },
        { .name = "symbol",     .entry = &sort_sym,     },
 };
 
@@ -868,7 +884,7 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
        size_t ret;
 
        if (total_samples) {
-               ret = fprintf(fp, "%5.2f%% ",
+               ret = fprintf(fp, "    %5.2f%%",
                                (self->count * 100.0) / total_samples);
        } else
                ret = fprintf(fp, "%12d ", self->count);
@@ -973,9 +989,29 @@ static void output__resort(void)
 static size_t output__fprintf(FILE *fp, uint64_t total_samples)
 {
        struct hist_entry *pos;
+       struct sort_entry *se;
        struct rb_node *nd;
        size_t ret = 0;
 
+       fprintf(fp, "#\n");
+
+       fprintf(fp, "# Overhead");
+       list_for_each_entry(se, &hist_entry__sort_list, list)
+               fprintf(fp, " %s", se->header);
+       fprintf(fp, "\n");
+
+       fprintf(fp, "# ........");
+       list_for_each_entry(se, &hist_entry__sort_list, list) {
+               int i;
+
+               fprintf(fp, " ");
+               for (i = 0; i < strlen(se->header); i++)
+                       fprintf(fp, ".");
+       }
+       fprintf(fp, "\n");
+
+       fprintf(fp, "#\n");
+
        for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
                pos = rb_entry(nd, struct hist_entry, rb_node);
                ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1067,9 +1103,9 @@ more:
                }
 
                if (thread == NULL) {
-                       fprintf(stderr, "problem processing %d event, bailing out\n",
+                       fprintf(stderr, "problem processing %d event, skipping it.\n",
                                event->header.type);
-                       goto done;
+                       goto broken_event;
                }
 
                if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
@@ -1099,8 +1135,8 @@ more:
 
                        if (hist_entry__add(thread, map, dso, sym, ip, level)) {
                                fprintf(stderr,
-               "problem incrementing symbol count, bailing out\n");
-                               goto done;
+               "problem incrementing symbol count, skipping event\n");
+                               goto broken_event;
                        }
                }
                total++;
@@ -1119,8 +1155,8 @@ more:
                                event->mmap.filename);
                }
                if (thread == NULL || map == NULL) {
-                       fprintf(stderr, "problem processing PERF_EVENT_MMAP, bailing out\n");
-                       goto done;
+                       fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n");
+                       goto broken_event;
                }
                thread__insert_map(thread, map);
                total_mmap++;
@@ -1137,8 +1173,8 @@ more:
                }
                if (thread == NULL ||
                    thread__set_comm(thread, event->comm.comm)) {
-                       fprintf(stderr, "problem processing PERF_EVENT_COMM, bailing out\n");
-                       goto done;
+                       fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n");
+                       goto broken_event;
                }
                total_comm++;
                break;
@@ -1171,7 +1207,6 @@ broken_event:
                goto more;
 
        rc = EXIT_SUCCESS;
-done:
        close(input);
 
        if (dump_trace) {
This page took 0.03077 seconds and 5 git commands to generate.