perf report: Implement --sort cpu
authorArun Sharma <aruns@google.com>
Fri, 4 Jun 2010 14:27:10 +0000 (11:27 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 5 Jun 2010 12:35:53 +0000 (09:35 -0300)
In a shared multi-core environment, users want to analyze why their
program was slow. In particular, if the code ran slower only on certain
CPUs due to interference from other programs or kernel threads, the user
should be able to notice that.

Sample usage:

perf record -f -a -- sleep 3
perf report --sort cpu,comm

Workload:

program is running on 16 CPUs
Experiencing interference from an antagonist only on 4 CPUs.

  Samples: 106218177676 cycles

  Overhead  CPU          Command
  ........  ...  ...............

     6.25%  2            program
     6.24%  6            program
     6.24%  11           program
     6.24%  5            program
     6.24%  9            program
     6.24%  10           program
     6.23%  15           program
     6.23%  7            program
     6.23%  3            program
     6.23%  14           program
     6.22%  1            program
     6.20%  13           program
     3.17%  12           program
     3.15%  8            program
     3.14%  0            program
     3.13%  4            program
     3.11%  4         antagonist
     3.11%  0         antagonist
     3.10%  8         antagonist
     3.07%  12        antagonist

Cc: David S. Miller <davem@davemloft.net>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <20100505181612.GA5091@sharma-home.net>
Signed-off-by: Arun Sharma <aruns@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-record.c
tools/perf/util/event.c
tools/perf/util/hist.c
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/symbol.h

index f28c4bbd801fd3567df703f6283696d01164dfc0..5e5c6403a3158b01854649a924d23841466e71c9 100644 (file)
@@ -274,6 +274,9 @@ static void create_counter(int counter, int cpu)
        if (call_graph)
                attr->sample_type       |= PERF_SAMPLE_CALLCHAIN;
 
+       if (system_wide)
+               attr->sample_type       |= PERF_SAMPLE_CPU;
+
        if (raw_samples) {
                attr->sample_type       |= PERF_SAMPLE_TIME;
                attr->sample_type       |= PERF_SAMPLE_RAW;
index ed3e14ff6df06f4ce0c27bacf0ee064b7d7d3f75..a7460868124bd0d1e643d43866c7a04863f0999e 100644 (file)
@@ -710,6 +710,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
                    al->map ? al->map->dso->long_name :
                        al->level == 'H' ? "[hypervisor]" : "<not found>");
        al->sym = NULL;
+       al->cpu = data->cpu;
 
        if (al->map) {
                if (symbol_conf.dso_list &&
index 9e6baad92c4a1c5ecac7720b4d10f1d30c17e555..68d288c975de308b5161e2326fa0747a68726fc8 100644 (file)
@@ -70,6 +70,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
                        .map    = al->map,
                        .sym    = al->sym,
                },
+               .cpu    = al->cpu,
                .ip     = al->addr,
                .level  = al->level,
                .period = period,
index 2316cb5a41164d4d99fbb289118def977b74cf5e..c27b4b03fbc17a424b3cba97ad8c7566121e57d7 100644 (file)
@@ -13,6 +13,7 @@ enum sort_type        sort__first_dimension;
 unsigned int dsos__col_width;
 unsigned int comms__col_width;
 unsigned int threads__col_width;
+unsigned int cpus__col_width;
 static unsigned int parent_symbol__col_width;
 char * field_sep;
 
@@ -28,6 +29,8 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
                                    size_t size, unsigned int width);
 static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
                                       size_t size, unsigned int width);
+static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
+                                   size_t size, unsigned int width);
 
 struct sort_entry sort_thread = {
        .se_header      = "Command:  Pid",
@@ -63,6 +66,13 @@ struct sort_entry sort_parent = {
        .se_snprintf    = hist_entry__parent_snprintf,
        .se_width       = &parent_symbol__col_width,
 };
+struct sort_entry sort_cpu = {
+       .se_header      = "CPU",
+       .se_cmp         = sort__cpu_cmp,
+       .se_snprintf    = hist_entry__cpu_snprintf,
+       .se_width       = &cpus__col_width,
+};
 
 struct sort_dimension {
        const char              *name;
@@ -76,6 +86,7 @@ static struct sort_dimension sort_dimensions[] = {
        { .name = "dso",        .entry = &sort_dso,     },
        { .name = "symbol",     .entry = &sort_sym,     },
        { .name = "parent",     .entry = &sort_parent,  },
+       { .name = "cpu",        .entry = &sort_cpu,     },
 };
 
 int64_t cmp_null(void *l, void *r)
@@ -242,6 +253,20 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
                              self->parent ? self->parent->name : "[other]");
 }
 
+/* --sort cpu */
+
+int64_t
+sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       return right->cpu - left->cpu;
+}
+
+static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
+                                      size_t size, unsigned int width)
+{
+       return repsep_snprintf(bf, size, "%-*d", width, self->cpu);
+}
+
 int sort_dimension__add(const char *tok)
 {
        unsigned int i;
@@ -281,6 +306,8 @@ int sort_dimension__add(const char *tok)
                                sort__first_dimension = SORT_SYM;
                        else if (!strcmp(sd->name, "parent"))
                                sort__first_dimension = SORT_PARENT;
+                       else if (!strcmp(sd->name, "cpu"))
+                               sort__first_dimension = SORT_CPU;
                }
 
                list_add_tail(&sd->entry->list, &hist_entry__sort_list);
index 0d61c4082f43849ddfe4ac1f6cb1cf9841009dd8..560c855417e4ac2989dfe82ec8dffe30dc8933ed 100644 (file)
@@ -39,6 +39,7 @@ extern struct sort_entry sort_parent;
 extern unsigned int dsos__col_width;
 extern unsigned int comms__col_width;
 extern unsigned int threads__col_width;
+extern unsigned int cpus__col_width;
 extern enum sort_type sort__first_dimension;
 
 struct hist_entry {
@@ -51,6 +52,7 @@ struct hist_entry {
        struct map_symbol       ms;
        struct thread           *thread;
        u64                     ip;
+       s32                     cpu;
        u32                     nr_events;
        char                    level;
        u8                      filtered;
@@ -68,7 +70,8 @@ enum sort_type {
        SORT_COMM,
        SORT_DSO,
        SORT_SYM,
-       SORT_PARENT
+       SORT_PARENT,
+       SORT_CPU,
 };
 
 /*
@@ -104,6 +107,7 @@ extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *);
 extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *);
 extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *);
 extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
+int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right);
 extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
 extern int sort_dimension__add(const char *);
 void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
index 34760a2fc606d39d58ba5d15855e8eed4d630216..10b7ff859ce03b4d60b49f19c174584101cf92e9 100644 (file)
@@ -110,7 +110,8 @@ struct addr_location {
        u64           addr;
        char          level;
        bool          filtered;
-       unsigned int  cpumode;
+       u8            cpumode;
+       s32           cpu;
 };
 
 enum dso_kernel_type {