* [PATCH 0/7] perf report --sort
@ 2009-05-27 18:20 Peter Zijlstra
2009-05-27 18:20 ` [PATCH 1/7] perf_counter: tools: /usr/lib/debug%s.debug support Peter Zijlstra
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/7] perf_counter: tools: /usr/lib/debug%s.debug support
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 18:20 ` [PATCH 2/7] perf_counter: tools: report: add vmlinux support Peter Zijlstra
` (5 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-foo.patch --]
[-- Type: text/plain, Size: 4157 bytes --]
Some distro's seem to store debuginfo in weird places.
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 94 ++++++++++++++++++++++------
1 file changed, 76 insertions(+), 18 deletions(-)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -190,7 +190,8 @@ static inline int elf_sym__is_function(c
{
return elf_sym__type(sym) == STT_FUNC &&
sym->st_name != 0 &&
- sym->st_shndx != SHN_UNDEF;
+ sym->st_shndx != SHN_UNDEF &&
+ sym->st_size != 0;
}
static inline const char *elf_sym__name(const GElf_Sym *sym,
@@ -222,11 +223,11 @@ static Elf_Scn *elf_section_by_name(Elf
return sec;
}
-static int dso__load(struct dso *self)
+static int dso__load_sym(struct dso *self, int fd, char *name)
{
Elf_Data *symstrs;
uint32_t nr_syms;
- int fd, err = -1;
+ int err = -1;
uint32_t index;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
@@ -234,16 +235,12 @@ static int dso__load(struct dso *self)
GElf_Sym sym;
Elf_Scn *sec;
Elf *elf;
-
-
- fd = open(self->name, O_RDONLY);
- if (fd == -1)
- return -1;
+ int nr = 0;
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
fprintf(stderr, "%s: cannot read %s ELF file.\n",
- __func__, self->name);
+ __func__, name);
goto out_close;
}
@@ -292,16 +289,63 @@ static int dso__load(struct dso *self)
goto out_elf_end;
dso__insert_symbol(self, f);
+
+ nr++;
}
- err = 0;
+ err = nr;
out_elf_end:
elf_end(elf);
out_close:
- close(fd);
return err;
}
+static int dso__load(struct dso *self)
+{
+ int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
+ char *name = malloc(size);
+ int variant = 0;
+ int ret = -1;
+ int fd;
+
+ if (!name)
+ return -1;
+
+more:
+ do {
+ switch (variant) {
+ case 0: /* Fedora */
+ snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
+ break;
+ case 1: /* Ubuntu */
+ snprintf(name, size, "/usr/lib/debug%s", self->name);
+ break;
+ case 2: /* Sane people */
+ snprintf(name, size, "%s", self->name);
+ break;
+
+ default:
+ goto out;
+ }
+ variant++;
+
+ fd = open(name, O_RDONLY);
+ } while (fd < 0);
+
+ ret = dso__load_sym(self, fd, name);
+ close(fd);
+
+ /*
+ * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
+ */
+ if (!ret)
+ goto more;
+
+out:
+ free(name);
+ return ret;
+}
+
static size_t dso__fprintf(struct dso *self, FILE *fp)
{
size_t ret = fprintf(fp, "dso: %s\n", self->name);
@@ -336,11 +380,23 @@ static struct dso *dsos__find(const char
static struct dso *dsos__findnew(const char *name)
{
struct dso *dso = dsos__find(name);
+ int nr;
if (dso == NULL) {
dso = dso__new(name);
- if (dso != NULL && dso__load(dso) < 0)
+ if (!dso)
+ goto out_delete_dso;
+
+ nr = dso__load(dso);
+ if (nr < 0) {
+ fprintf(stderr, "Failed to open: %s\n", name);
goto out_delete_dso;
+ }
+ if (!nr) {
+ fprintf(stderr,
+ "Failed to find debug symbols for: %s, maybe install a debug package?\n",
+ name);
+ }
dsos__add(dso);
}
@@ -547,9 +603,9 @@ symhist__fprintf(struct symhist *self, u
size_t ret;
if (total_samples)
- ret = fprintf(fp, "%5.2f", (self->count * 100.0) / total_samples);
+ ret = fprintf(fp, "%5.2f%% ", (self->count * 100.0) / total_samples);
else
- ret = fprintf(fp, "%12d", self->count);
+ ret = fprintf(fp, "%12d ", self->count);
ret += fprintf(fp, "%14s [%c] ",
thread__name(self->thread, bf, sizeof(bf)),
@@ -922,10 +978,12 @@ more:
}
default: {
broken_event:
- fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
- (void *)(offset + head),
- (void *)(long)(event->header.size),
- event->header.type);
+ if (dump_trace)
+ fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
+ event->header.type);
+
total_unknown++;
/*
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/7] perf_counter: tools: report: add vmlinux support
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
2009-05-27 18:20 ` [PATCH 1/7] perf_counter: tools: /usr/lib/debug%s.debug support Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 19:51 ` [tip:perfcounters/core] perf_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 3/7] perf_counter: tools: report: rework histogram code Peter Zijlstra
` (4 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-sort.patch --]
[-- Type: text/plain, Size: 1786 bytes --]
Allow to use vmlinux instead of kallsyms.
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 37 +++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -19,6 +19,7 @@
#define SHOW_HV 4
static char const *input_name = "perf.data";
+static char *vmlinux = NULL;
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -532,6 +533,39 @@ out_delete_dso:
return -1;
}
+static int load_kernel(void)
+{
+ int fd, nr;
+
+ if (!vmlinux)
+ goto kallsyms;
+
+ fd = open(vmlinux, O_RDONLY);
+ if (fd < 0)
+ goto kallsyms;
+
+ kernel_dso = dso__new("[kernel]");
+ if (!kernel_dso)
+ goto fail_open;
+
+ nr = dso__load_sym(kernel_dso, fd, vmlinux);
+
+ if (nr <= 0)
+ goto fail_load;
+
+ dsos__add(kernel_dso);
+ close(fd);
+
+ return 0;
+
+fail_load:
+ dso__delete(kernel_dso);
+fail_open:
+ close(fd);
+kallsyms:
+ return load_kallsyms();
+}
+
struct map {
struct list_head node;
uint64_t start;
@@ -850,7 +884,7 @@ static int __cmd_report(void)
exit(0);
}
- if (load_kallsyms() < 0) {
+ if (load_kernel() < 0) {
perror("failed to open kallsyms");
return EXIT_FAILURE;
}
@@ -1039,6 +1073,7 @@ static const struct option options[] = {
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
+ OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
OPT_END()
};
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/7] perf_counter: tools: report: rework histogram code
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
2009-05-27 18:20 ` [PATCH 1/7] perf_counter: tools: /usr/lib/debug%s.debug support Peter Zijlstra
2009-05-27 18:20 ` [PATCH 2/7] perf_counter: tools: report: add vmlinux support Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 19:51 ` [tip:perfcounters/core] perf_counter: tools: report: Rework " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 4/7] perf_counter: tools: report: dynamic sort/print bits Peter Zijlstra
` (3 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-sort2.patch --]
[-- Type: text/plain, Size: 9952 bytes --]
In preparation for configurable sorting, rework the histgram code a bit.
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 294 +++++++++++++---------------
1 file changed, 143 insertions(+), 151 deletions(-)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -597,71 +597,9 @@ struct thread;
static const char *thread__name(struct thread *self, char *bf, size_t size);
-struct symhist {
- struct rb_node rb_node;
- struct dso *dso;
- struct symbol *sym;
- struct thread *thread;
- uint64_t ip;
- uint32_t count;
- char level;
-};
-
-static struct symhist *symhist__new(struct symbol *sym, uint64_t ip,
- struct thread *thread, struct dso *dso,
- char level)
-{
- struct symhist *self = malloc(sizeof(*self));
-
- if (self != NULL) {
- self->sym = sym;
- self->thread = thread;
- self->ip = ip;
- self->dso = dso;
- self->level = level;
- self->count = 1;
- }
-
- return self;
-}
-
-static void symhist__inc(struct symhist *self)
-{
- ++self->count;
-}
-
-static size_t
-symhist__fprintf(struct symhist *self, uint64_t total_samples, FILE *fp)
-{
- char bf[32];
- size_t ret;
-
- if (total_samples)
- ret = fprintf(fp, "%5.2f%% ", (self->count * 100.0) / total_samples);
- else
- ret = fprintf(fp, "%12d ", self->count);
-
- ret += fprintf(fp, "%14s [%c] ",
- thread__name(self->thread, bf, sizeof(bf)),
- self->level);
-
- if (verbose)
- ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
-
- if (self->level != '.')
- ret += fprintf(fp, "%s\n",
- self->sym ? self->sym->name : "<unknown>");
- else
- ret += fprintf(fp, "%s: %s\n",
- self->dso ? self->dso->name : "<unknown>",
- self->sym ? self->sym->name : "<unknown>");
- return ret;
-}
-
struct thread {
struct rb_node rb_node;
struct list_head maps;
- struct rb_root symhists;
pid_t pid;
char *comm;
};
@@ -683,67 +621,17 @@ static struct thread *thread__new(pid_t
self->pid = pid;
self->comm = NULL;
INIT_LIST_HEAD(&self->maps);
- self->symhists = RB_ROOT;
}
return self;
}
-static int thread__symbol_incnew(struct thread *self, struct symbol *sym,
- uint64_t ip, struct dso *dso, char level)
-{
- struct rb_node **p = &self->symhists.rb_node;
- struct rb_node *parent = NULL;
- struct symhist *sh;
-
- while (*p != NULL) {
- uint64_t start;
-
- parent = *p;
- sh = rb_entry(parent, struct symhist, rb_node);
-
- if (sh->sym == sym || ip == sh->ip) {
- symhist__inc(sh);
- return 0;
- }
-
- /* Handle unresolved symbols too */
- start = !sh->sym ? sh->ip : sh->sym->start;
-
- if (ip < start)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
-
- sh = symhist__new(sym, ip, self, dso, level);
- if (sh == NULL)
- return -ENOMEM;
- rb_link_node(&sh->rb_node, parent, p);
- rb_insert_color(&sh->rb_node, &self->symhists);
- return 0;
-}
-
static int thread__set_comm(struct thread *self, const char *comm)
{
self->comm = strdup(comm);
return self->comm ? 0 : -ENOMEM;
}
-static size_t thread__fprintf(struct thread *self, FILE *fp)
-{
- int ret = fprintf(fp, "thread: %d %s\n", self->pid, self->comm);
- struct rb_node *nd;
-
- for (nd = rb_first(&self->symhists); nd; nd = rb_next(nd)) {
- struct symhist *pos = rb_entry(nd, struct symhist, rb_node);
-
- ret += symhist__fprintf(pos, 0, fp);
- }
-
- return ret;
-}
-
static struct rb_root threads;
static struct thread *threads__findnew(pid_t pid)
@@ -792,70 +680,172 @@ static struct map *thread__find_map(stru
return NULL;
}
-static void threads__fprintf(FILE *fp)
+/*
+ * histogram, sorted on item, collects counts
+ */
+
+static struct rb_root hist;
+
+struct hist_entry {
+ struct rb_node rb_node;
+
+ struct thread *thread;
+ struct map *map;
+ struct dso *dso;
+ struct symbol *sym;
+ uint64_t ip;
+ char level;
+
+ uint32_t count;
+};
+
+static int64_t
+hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
{
- struct rb_node *nd;
- for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
- struct thread *pos = rb_entry(nd, struct thread, rb_node);
- thread__fprintf(pos, fp);
+ uint64_t ip_l, ip_r;
+ int cmp = right->thread->pid - left->thread->pid;
+
+ if (cmp)
+ return cmp;
+
+ if (left->sym == right->sym)
+ return 0;
+
+ ip_l = left->sym ? left->sym->start : left->ip;
+ ip_r = right->sym ? right->sym->start : right->ip;
+
+ return (int64_t)(ip_r - ip_l);
+}
+
+static int
+hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
+ struct symbol *sym, uint64_t ip, char level)
+{
+ struct rb_node **p = &hist.rb_node;
+ struct rb_node *parent = NULL;
+ struct hist_entry *he;
+ struct hist_entry entry = {
+ .thread = thread,
+ .map = map,
+ .dso = dso,
+ .sym = sym,
+ .ip = ip,
+ .level = level,
+ .count = 1,
+ };
+ int cmp;
+
+ while (*p != NULL) {
+ parent = *p;
+ he = rb_entry(parent, struct hist_entry, rb_node);
+
+ cmp = hist_entry__cmp(&entry, he);
+
+ if (!cmp) {
+ he->count++;
+ return 0;
+ }
+
+ if (cmp < 0)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
}
+
+ he = malloc(sizeof(*he));
+ if (!he)
+ return -ENOMEM;
+ *he = entry;
+ rb_link_node(&he->rb_node, parent, p);
+ rb_insert_color(&he->rb_node, &hist);
+
+ return 0;
+}
+
+static size_t
+hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
+{
+ char bf[32];
+ size_t ret;
+
+ if (total_samples) {
+ ret = fprintf(fp, "%5.2f%% ",
+ (self->count * 100.0) / total_samples);
+ } else
+ ret = fprintf(fp, "%12d ", self->count);
+
+ ret += fprintf(fp, "%14s [%c] ",
+ thread__name(self->thread, bf, sizeof(bf)),
+ self->level);
+
+ if (verbose)
+ ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
+
+ if (self->level != '.')
+ ret += fprintf(fp, "%s\n",
+ self->sym ? self->sym->name : "<unknown>");
+ else
+ ret += fprintf(fp, "%s: %s\n",
+ self->dso ? self->dso->name : "<unknown>",
+ self->sym ? self->sym->name : "<unknown>");
+ return ret;
}
-static struct rb_root global_symhists;
+/*
+ * reverse the map, sort on count.
+ */
+
+static struct rb_root output_hists;
-static void threads__insert_symhist(struct symhist *sh)
+static void output__insert_entry(struct hist_entry *he)
{
- struct rb_node **p = &global_symhists.rb_node;
+ struct rb_node **p = &output_hists.rb_node;
struct rb_node *parent = NULL;
- struct symhist *iter;
+ struct hist_entry *iter;
while (*p != NULL) {
parent = *p;
- iter = rb_entry(parent, struct symhist, rb_node);
+ iter = rb_entry(parent, struct hist_entry, rb_node);
- /* Reverse order */
- if (sh->count > iter->count)
+ if (he->count > iter->count)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
}
- rb_link_node(&sh->rb_node, parent, p);
- rb_insert_color(&sh->rb_node, &global_symhists);
+ rb_link_node(&he->rb_node, parent, p);
+ rb_insert_color(&he->rb_node, &output_hists);
}
-static void threads__sort_symhists(void)
+static void output__resort(void)
{
- struct rb_node *nd;
+ struct rb_node *next = rb_first(&hist);
+ struct hist_entry *n;
- for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
- struct thread *thread = rb_entry(nd, struct thread, rb_node);
- struct rb_node *next = rb_first(&thread->symhists);
-
- while (next) {
- struct symhist *n = rb_entry(next, struct symhist,
- rb_node);
- next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &thread->symhists);
- threads__insert_symhist(n);
- }
+ while (next) {
+ n = rb_entry(next, struct hist_entry, rb_node);
+ next = rb_next(&n->rb_node);
+ rb_erase(&n->rb_node, &hist);
+ output__insert_entry(n);
}
}
-static size_t threads__symhists_fprintf(uint64_t total_samples, FILE *fp)
+static size_t output__fprintf(FILE *fp, uint64_t total_samples)
{
+ struct hist_entry *pos;
struct rb_node *nd;
size_t ret = 0;
- for (nd = rb_first(&global_symhists); nd; nd = rb_next(nd)) {
- struct symhist *pos = rb_entry(nd, struct symhist, rb_node);
- ret += symhist__fprintf(pos, total_samples, fp);
+ 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);
}
return ret;
}
+
static int __cmd_report(void)
{
unsigned long offset = 0;
@@ -926,6 +916,7 @@ more:
struct dso *dso = NULL;
struct thread *thread = threads__findnew(event->ip.pid);
uint64_t ip = event->ip.ip;
+ struct map *map = NULL;
if (dump_trace) {
fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
@@ -945,9 +936,10 @@ more:
if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
show = SHOW_KERNEL;
level = 'k';
+
dso = kernel_dso;
+
} else if (event->header.misc & PERF_EVENT_MISC_USER) {
- struct map *map;
show = SHOW_USER;
level = '.';
@@ -957,6 +949,7 @@ more:
dso = map->dso;
ip -= map->start + map->pgoff;
}
+
} else {
show = SHOW_HV;
level = 'H';
@@ -965,8 +958,9 @@ more:
if (show & show_mask) {
struct symbol *sym = dso__find_symbol(dso, ip);
- if (thread__symbol_incnew(thread, sym, ip, dso, level)) {
- fprintf(stderr, "problem incrementing symbol count, bailing out\n");
+ if (hist_entry__add(thread, map, dso, sym, ip, level)) {
+ fprintf(stderr,
+ "problem incrementing symbol count, bailing out\n");
goto done;
}
}
@@ -1050,13 +1044,11 @@ done:
return 0;
}
- if (verbose >= 2) {
+ if (verbose >= 2)
dsos__fprintf(stdout);
- threads__fprintf(stdout);
- }
- threads__sort_symhists();
- threads__symhists_fprintf(total, stdout);
+ output__resort();
+ output__fprintf(stdout, total);
return rc;
}
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/7] perf_counter: tools: report: dynamic sort/print bits
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
` (2 preceding siblings ...)
2009-05-27 18:20 ` [PATCH 3/7] perf_counter: tools: report: rework histogram code Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 19:51 ` [tip:perfcounters/core] perf_counter: tools: report: Dynamic " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 5/7] pref_counter: tools: report: --sort option Peter Zijlstra
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-sort3.patch --]
[-- Type: text/plain, Size: 4388 bytes --]
Make the sorting and printing dynamic.
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 141 +++++++++++++++++++++-------
1 file changed, 107 insertions(+), 34 deletions(-)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -699,14 +699,41 @@ struct hist_entry {
uint32_t count;
};
+/*
+ * configurable sorting bits
+ */
+
+struct sort_entry {
+ struct list_head list;
+
+ int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
+ size_t (*print)(FILE *fp, struct hist_entry *);
+};
+
static int64_t
-hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
+sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
{
- uint64_t ip_l, ip_r;
- int cmp = right->thread->pid - left->thread->pid;
+ return right->thread->pid - left->thread->pid;
+}
+
+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)));
+}
- if (cmp)
- return cmp;
+static struct sort_entry sort_thread = {
+ .cmp = sort__thread_cmp,
+ .print = sort__thread_print,
+};
+
+static int64_t
+sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ uint64_t ip_l, ip_r;
if (left->sym == right->sym)
return 0;
@@ -717,6 +744,79 @@ hist_entry__cmp(struct hist_entry *left,
return (int64_t)(ip_r - ip_l);
}
+static size_t
+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);
+
+ 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>");
+
+ return ret;
+}
+
+static struct sort_entry sort_sym = {
+ .cmp = sort__sym_cmp,
+ .print = sort__sym_print,
+};
+
+static LIST_HEAD(hist_entry__sort_list);
+
+static void setup_sorting(void)
+{
+ list_add_tail(&sort_thread.list, &hist_entry__sort_list);
+ list_add_tail(&sort_sym.list, &hist_entry__sort_list);
+}
+
+static int64_t
+hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ struct sort_entry *se;
+ int64_t cmp = 0;
+
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ cmp = se->cmp(left, right);
+ if (cmp)
+ break;
+ }
+
+ return cmp;
+}
+
+static size_t
+hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
+{
+ struct sort_entry *se;
+ size_t ret;
+
+ if (total_samples) {
+ ret = fprintf(fp, "%5.2f%% ",
+ (self->count * 100.0) / total_samples);
+ } else
+ ret = fprintf(fp, "%12d ", self->count);
+
+ list_for_each_entry(se, &hist_entry__sort_list, list)
+ ret += se->print(fp, self);
+
+ ret += fprintf(fp, "\n");
+
+ return ret;
+}
+
+/*
+ * collect histogram counts
+ */
+
static int
hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
struct symbol *sym, uint64_t ip, char level)
@@ -762,35 +862,6 @@ hist_entry__add(struct thread *thread, s
return 0;
}
-static size_t
-hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
-{
- char bf[32];
- size_t ret;
-
- if (total_samples) {
- ret = fprintf(fp, "%5.2f%% ",
- (self->count * 100.0) / total_samples);
- } else
- ret = fprintf(fp, "%12d ", self->count);
-
- ret += fprintf(fp, "%14s [%c] ",
- thread__name(self->thread, bf, sizeof(bf)),
- self->level);
-
- if (verbose)
- ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
-
- if (self->level != '.')
- ret += fprintf(fp, "%s\n",
- self->sym ? self->sym->name : "<unknown>");
- else
- ret += fprintf(fp, "%s: %s\n",
- self->dso ? self->dso->name : "<unknown>",
- self->sym ? self->sym->name : "<unknown>");
- return ret;
-}
-
/*
* reverse the map, sort on count.
*/
@@ -1077,6 +1148,8 @@ int cmd_report(int argc, const char **ar
parse_options(argc, argv, options, report_usage, 0);
+ setup_sorting();
+
setup_pager();
return __cmd_report();
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/7] pref_counter: tools: report: --sort option
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
` (3 preceding siblings ...)
2009-05-27 18:20 ` [PATCH 4/7] perf_counter: tools: report: dynamic sort/print bits Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] pref_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 6/7] perf_counter: tools: report: add comm sorting Peter Zijlstra
2009-05-27 18:20 ` [PATCH 7/7] pref_counter: tools: report: add dso sorting Peter Zijlstra
6 siblings, 1 reply; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-sort4.patch --]
[-- Type: text/plain, Size: 2111 bytes --]
option parsing for dynamic sorting
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 43 ++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -20,6 +20,7 @@
static char const *input_name = "perf.data";
static char *vmlinux = NULL;
+static char *sort_order = "pid,symbol";
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -770,12 +771,49 @@ static struct sort_entry sort_sym = {
.print = sort__sym_print,
};
+struct sort_dimension {
+ char *name;
+ struct sort_entry *entry;
+ int taken;
+};
+
+static struct sort_dimension sort_dimensions[] = {
+ { .name = "pid", .entry = &sort_thread, },
+ { .name = "symbol", .entry = &sort_sym, },
+};
+
static LIST_HEAD(hist_entry__sort_list);
+static int sort_dimension__add(char *tok)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
+ struct sort_dimension *sd = &sort_dimensions[i];
+
+ if (sd->taken)
+ continue;
+
+ if (strcmp(tok, sd->name))
+ continue;
+
+ list_add_tail(&sd->entry->list, &hist_entry__sort_list);
+ sd->taken = 1;
+ return 0;
+ }
+
+ return -ESRCH;
+}
+
static void setup_sorting(void)
{
- list_add_tail(&sort_thread.list, &hist_entry__sort_list);
- list_add_tail(&sort_sym.list, &hist_entry__sort_list);
+ char *tmp, *tok, *str = strdup(sort_order);
+
+ for (tok = strtok_r(str, ", ", &tmp);
+ tok; tok = strtok_r(NULL, ", ", &tmp))
+ sort_dimension__add(tok);
+
+ free(str);
}
static int64_t
@@ -1137,6 +1175,7 @@ static const struct option options[] = {
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
+ OPT_STRING('s', "sort", &sort_order, "foo", "bar"),
OPT_END()
};
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 6/7] perf_counter: tools: report: add comm sorting
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
` (4 preceding siblings ...)
2009-05-27 18:20 ` [PATCH 5/7] pref_counter: tools: report: --sort option Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] perf_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 7/7] pref_counter: tools: report: add dso sorting Peter Zijlstra
6 siblings, 1 reply; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-sort5.patch --]
[-- Type: text/plain, Size: 1454 bytes --]
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 30 ++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -732,6 +732,35 @@ static struct sort_entry sort_thread = {
};
static int64_t
+sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ char *comm_l = left->thread->comm;
+ char *comm_r = right->thread->comm;
+
+ if (!comm_l || !comm_r) {
+ if (!comm_l && !comm_r)
+ return 0;
+ else if (!comm_l)
+ return -1;
+ else
+ return 1;
+ }
+
+ return strcmp(comm_l, comm_r);
+}
+
+static size_t
+sort__comm_print(FILE *fp, struct hist_entry *self)
+{
+ return fprintf(fp, "%20s ", self->thread->comm ?: "<unknown>");
+}
+
+static struct sort_entry sort_comm = {
+ .cmp = sort__comm_cmp,
+ .print = sort__comm_print,
+};
+
+static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
uint64_t ip_l, ip_r;
@@ -779,6 +808,7 @@ struct sort_dimension {
static struct sort_dimension sort_dimensions[] = {
{ .name = "pid", .entry = &sort_thread, },
+ { .name = "comm", .entry = &sort_comm, },
{ .name = "symbol", .entry = &sort_sym, },
};
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 7/7] pref_counter: tools: report: add dso sorting
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
` (5 preceding siblings ...)
2009-05-27 18:20 ` [PATCH 6/7] perf_counter: tools: report: add comm sorting Peter Zijlstra
@ 2009-05-27 18:20 ` Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] pref_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 20:46 ` [tip:perfcounters/core] pref_counter: tools: report: Add header printout & prettify tip-bot for Ingo Molnar
6 siblings, 2 replies; 15+ messages in thread
From: Peter Zijlstra @ 2009-05-27 18:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Paul Mackerras, Corey Ashford, linux-kernel, Peter Zijlstra,
Arnaldo Carvalho de Melo, John Kacur, Mike Galbraith
[-- Attachment #1: perf_counter-tools-report-sort6.patch --]
[-- Type: text/plain, Size: 1493 bytes --]
LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
Documentation/perf_counter/builtin-report.c | 30 ++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
Index: linux-2.6/Documentation/perf_counter/builtin-report.c
===================================================================
--- linux-2.6.orig/Documentation/perf_counter/builtin-report.c
+++ linux-2.6/Documentation/perf_counter/builtin-report.c
@@ -761,6 +761,35 @@ static struct sort_entry sort_comm = {
};
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 = {
+ .cmp = sort__dso_cmp,
+ .print = sort__dso_print,
+};
+
+static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
uint64_t ip_l, ip_r;
@@ -809,6 +838,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, },
};
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] perf_counter: tools: report: Add vmlinux support
2009-05-27 18:20 ` [PATCH 2/7] perf_counter: tools: report: add vmlinux support Peter Zijlstra
@ 2009-05-27 19:51 ` tip-bot for Peter Zijlstra
0 siblings, 0 replies; 15+ messages in thread
From: tip-bot for Peter Zijlstra @ 2009-05-27 19:51 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: 450aaa2b2a1b006870ba68251fbb40b2387caade
Gitweb: http://git.kernel.org/tip/450aaa2b2a1b006870ba68251fbb40b2387caade
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 27 May 2009 20:20:23 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:44:12 +0200
perf_counter: tools: report: Add vmlinux support
Allow to use vmlinux instead of kallsyms.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182100.740018486@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 37 ++++++++++++++++++++++++++-
1 files changed, 36 insertions(+), 1 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index a9ff49a..3e87cbd 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -19,6 +19,7 @@
#define SHOW_HV 4
static char const *input_name = "perf.data";
+static char *vmlinux = NULL;
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -532,6 +533,39 @@ out_delete_dso:
return -1;
}
+static int load_kernel(void)
+{
+ int fd, nr;
+
+ if (!vmlinux)
+ goto kallsyms;
+
+ fd = open(vmlinux, O_RDONLY);
+ if (fd < 0)
+ goto kallsyms;
+
+ kernel_dso = dso__new("[kernel]");
+ if (!kernel_dso)
+ goto fail_open;
+
+ nr = dso__load_sym(kernel_dso, fd, vmlinux);
+
+ if (nr <= 0)
+ goto fail_load;
+
+ dsos__add(kernel_dso);
+ close(fd);
+
+ return 0;
+
+fail_load:
+ dso__delete(kernel_dso);
+fail_open:
+ close(fd);
+kallsyms:
+ return load_kallsyms();
+}
+
struct map {
struct list_head node;
uint64_t start;
@@ -850,7 +884,7 @@ static int __cmd_report(void)
exit(0);
}
- if (load_kallsyms() < 0) {
+ if (load_kernel() < 0) {
perror("failed to open kallsyms");
return EXIT_FAILURE;
}
@@ -1039,6 +1073,7 @@ static const struct option options[] = {
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
+ OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
OPT_END()
};
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] perf_counter: tools: report: Rework histogram code
2009-05-27 18:20 ` [PATCH 3/7] perf_counter: tools: report: rework histogram code Peter Zijlstra
@ 2009-05-27 19:51 ` tip-bot for Peter Zijlstra
0 siblings, 0 replies; 15+ messages in thread
From: tip-bot for Peter Zijlstra @ 2009-05-27 19:51 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: e7fb08b1d06a6b37263c765205de5614a2273aeb
Gitweb: http://git.kernel.org/tip/e7fb08b1d06a6b37263c765205de5614a2273aeb
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 27 May 2009 20:20:24 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:44:13 +0200
perf_counter: tools: report: Rework histogram code
In preparation for configurable sorting, rework the histgram code a bit.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182100.796410098@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 294 +++++++++++++--------------
1 files changed, 143 insertions(+), 151 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 3e87cbd..2762564 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -597,71 +597,9 @@ struct thread;
static const char *thread__name(struct thread *self, char *bf, size_t size);
-struct symhist {
- struct rb_node rb_node;
- struct dso *dso;
- struct symbol *sym;
- struct thread *thread;
- uint64_t ip;
- uint32_t count;
- char level;
-};
-
-static struct symhist *symhist__new(struct symbol *sym, uint64_t ip,
- struct thread *thread, struct dso *dso,
- char level)
-{
- struct symhist *self = malloc(sizeof(*self));
-
- if (self != NULL) {
- self->sym = sym;
- self->thread = thread;
- self->ip = ip;
- self->dso = dso;
- self->level = level;
- self->count = 1;
- }
-
- return self;
-}
-
-static void symhist__inc(struct symhist *self)
-{
- ++self->count;
-}
-
-static size_t
-symhist__fprintf(struct symhist *self, uint64_t total_samples, FILE *fp)
-{
- char bf[32];
- size_t ret;
-
- if (total_samples)
- ret = fprintf(fp, "%5.2f%% ", (self->count * 100.0) / total_samples);
- else
- ret = fprintf(fp, "%12d ", self->count);
-
- ret += fprintf(fp, "%14s [%c] ",
- thread__name(self->thread, bf, sizeof(bf)),
- self->level);
-
- if (verbose)
- ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
-
- if (self->level != '.')
- ret += fprintf(fp, "%s\n",
- self->sym ? self->sym->name : "<unknown>");
- else
- ret += fprintf(fp, "%s: %s\n",
- self->dso ? self->dso->name : "<unknown>",
- self->sym ? self->sym->name : "<unknown>");
- return ret;
-}
-
struct thread {
struct rb_node rb_node;
struct list_head maps;
- struct rb_root symhists;
pid_t pid;
char *comm;
};
@@ -683,67 +621,17 @@ static struct thread *thread__new(pid_t pid)
self->pid = pid;
self->comm = NULL;
INIT_LIST_HEAD(&self->maps);
- self->symhists = RB_ROOT;
}
return self;
}
-static int thread__symbol_incnew(struct thread *self, struct symbol *sym,
- uint64_t ip, struct dso *dso, char level)
-{
- struct rb_node **p = &self->symhists.rb_node;
- struct rb_node *parent = NULL;
- struct symhist *sh;
-
- while (*p != NULL) {
- uint64_t start;
-
- parent = *p;
- sh = rb_entry(parent, struct symhist, rb_node);
-
- if (sh->sym == sym || ip == sh->ip) {
- symhist__inc(sh);
- return 0;
- }
-
- /* Handle unresolved symbols too */
- start = !sh->sym ? sh->ip : sh->sym->start;
-
- if (ip < start)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
-
- sh = symhist__new(sym, ip, self, dso, level);
- if (sh == NULL)
- return -ENOMEM;
- rb_link_node(&sh->rb_node, parent, p);
- rb_insert_color(&sh->rb_node, &self->symhists);
- return 0;
-}
-
static int thread__set_comm(struct thread *self, const char *comm)
{
self->comm = strdup(comm);
return self->comm ? 0 : -ENOMEM;
}
-static size_t thread__fprintf(struct thread *self, FILE *fp)
-{
- int ret = fprintf(fp, "thread: %d %s\n", self->pid, self->comm);
- struct rb_node *nd;
-
- for (nd = rb_first(&self->symhists); nd; nd = rb_next(nd)) {
- struct symhist *pos = rb_entry(nd, struct symhist, rb_node);
-
- ret += symhist__fprintf(pos, 0, fp);
- }
-
- return ret;
-}
-
static struct rb_root threads;
static struct thread *threads__findnew(pid_t pid)
@@ -792,70 +680,172 @@ static struct map *thread__find_map(struct thread *self, uint64_t ip)
return NULL;
}
-static void threads__fprintf(FILE *fp)
+/*
+ * histogram, sorted on item, collects counts
+ */
+
+static struct rb_root hist;
+
+struct hist_entry {
+ struct rb_node rb_node;
+
+ struct thread *thread;
+ struct map *map;
+ struct dso *dso;
+ struct symbol *sym;
+ uint64_t ip;
+ char level;
+
+ uint32_t count;
+};
+
+static int64_t
+hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ uint64_t ip_l, ip_r;
+ int cmp = right->thread->pid - left->thread->pid;
+
+ if (cmp)
+ return cmp;
+
+ if (left->sym == right->sym)
+ return 0;
+
+ ip_l = left->sym ? left->sym->start : left->ip;
+ ip_r = right->sym ? right->sym->start : right->ip;
+
+ return (int64_t)(ip_r - ip_l);
+}
+
+static int
+hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
+ struct symbol *sym, uint64_t ip, char level)
{
- struct rb_node *nd;
- for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
- struct thread *pos = rb_entry(nd, struct thread, rb_node);
- thread__fprintf(pos, fp);
+ struct rb_node **p = &hist.rb_node;
+ struct rb_node *parent = NULL;
+ struct hist_entry *he;
+ struct hist_entry entry = {
+ .thread = thread,
+ .map = map,
+ .dso = dso,
+ .sym = sym,
+ .ip = ip,
+ .level = level,
+ .count = 1,
+ };
+ int cmp;
+
+ while (*p != NULL) {
+ parent = *p;
+ he = rb_entry(parent, struct hist_entry, rb_node);
+
+ cmp = hist_entry__cmp(&entry, he);
+
+ if (!cmp) {
+ he->count++;
+ return 0;
+ }
+
+ if (cmp < 0)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
}
+
+ he = malloc(sizeof(*he));
+ if (!he)
+ return -ENOMEM;
+ *he = entry;
+ rb_link_node(&he->rb_node, parent, p);
+ rb_insert_color(&he->rb_node, &hist);
+
+ return 0;
}
-static struct rb_root global_symhists;
+static size_t
+hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
+{
+ char bf[32];
+ size_t ret;
+
+ if (total_samples) {
+ ret = fprintf(fp, "%5.2f%% ",
+ (self->count * 100.0) / total_samples);
+ } else
+ ret = fprintf(fp, "%12d ", self->count);
-static void threads__insert_symhist(struct symhist *sh)
+ ret += fprintf(fp, "%14s [%c] ",
+ thread__name(self->thread, bf, sizeof(bf)),
+ self->level);
+
+ if (verbose)
+ ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
+
+ if (self->level != '.')
+ ret += fprintf(fp, "%s\n",
+ self->sym ? self->sym->name : "<unknown>");
+ else
+ ret += fprintf(fp, "%s: %s\n",
+ self->dso ? self->dso->name : "<unknown>",
+ self->sym ? self->sym->name : "<unknown>");
+ return ret;
+}
+
+/*
+ * reverse the map, sort on count.
+ */
+
+static struct rb_root output_hists;
+
+static void output__insert_entry(struct hist_entry *he)
{
- struct rb_node **p = &global_symhists.rb_node;
+ struct rb_node **p = &output_hists.rb_node;
struct rb_node *parent = NULL;
- struct symhist *iter;
+ struct hist_entry *iter;
while (*p != NULL) {
parent = *p;
- iter = rb_entry(parent, struct symhist, rb_node);
+ iter = rb_entry(parent, struct hist_entry, rb_node);
- /* Reverse order */
- if (sh->count > iter->count)
+ if (he->count > iter->count)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
}
- rb_link_node(&sh->rb_node, parent, p);
- rb_insert_color(&sh->rb_node, &global_symhists);
+ rb_link_node(&he->rb_node, parent, p);
+ rb_insert_color(&he->rb_node, &output_hists);
}
-static void threads__sort_symhists(void)
+static void output__resort(void)
{
- struct rb_node *nd;
-
- for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
- struct thread *thread = rb_entry(nd, struct thread, rb_node);
- struct rb_node *next = rb_first(&thread->symhists);
+ struct rb_node *next = rb_first(&hist);
+ struct hist_entry *n;
- while (next) {
- struct symhist *n = rb_entry(next, struct symhist,
- rb_node);
- next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &thread->symhists);
- threads__insert_symhist(n);
- }
+ while (next) {
+ n = rb_entry(next, struct hist_entry, rb_node);
+ next = rb_next(&n->rb_node);
+ rb_erase(&n->rb_node, &hist);
+ output__insert_entry(n);
}
}
-static size_t threads__symhists_fprintf(uint64_t total_samples, FILE *fp)
+static size_t output__fprintf(FILE *fp, uint64_t total_samples)
{
+ struct hist_entry *pos;
struct rb_node *nd;
size_t ret = 0;
- for (nd = rb_first(&global_symhists); nd; nd = rb_next(nd)) {
- struct symhist *pos = rb_entry(nd, struct symhist, rb_node);
- ret += symhist__fprintf(pos, total_samples, fp);
+ 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);
}
return ret;
}
+
static int __cmd_report(void)
{
unsigned long offset = 0;
@@ -926,6 +916,7 @@ more:
struct dso *dso = NULL;
struct thread *thread = threads__findnew(event->ip.pid);
uint64_t ip = event->ip.ip;
+ struct map *map = NULL;
if (dump_trace) {
fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
@@ -945,9 +936,10 @@ more:
if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
show = SHOW_KERNEL;
level = 'k';
+
dso = kernel_dso;
+
} else if (event->header.misc & PERF_EVENT_MISC_USER) {
- struct map *map;
show = SHOW_USER;
level = '.';
@@ -957,6 +949,7 @@ more:
dso = map->dso;
ip -= map->start + map->pgoff;
}
+
} else {
show = SHOW_HV;
level = 'H';
@@ -965,8 +958,9 @@ more:
if (show & show_mask) {
struct symbol *sym = dso__find_symbol(dso, ip);
- if (thread__symbol_incnew(thread, sym, ip, dso, level)) {
- fprintf(stderr, "problem incrementing symbol count, bailing out\n");
+ if (hist_entry__add(thread, map, dso, sym, ip, level)) {
+ fprintf(stderr,
+ "problem incrementing symbol count, bailing out\n");
goto done;
}
}
@@ -1050,13 +1044,11 @@ done:
return 0;
}
- if (verbose >= 2) {
+ if (verbose >= 2)
dsos__fprintf(stdout);
- threads__fprintf(stdout);
- }
- threads__sort_symhists();
- threads__symhists_fprintf(total, stdout);
+ output__resort();
+ output__fprintf(stdout, total);
return rc;
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] perf_counter: tools: report: Dynamic sort/print bits
2009-05-27 18:20 ` [PATCH 4/7] perf_counter: tools: report: dynamic sort/print bits Peter Zijlstra
@ 2009-05-27 19:51 ` tip-bot for Peter Zijlstra
0 siblings, 0 replies; 15+ messages in thread
From: tip-bot for Peter Zijlstra @ 2009-05-27 19:51 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: 1aa167382323eeeeb38368cab85cf17979793cbe
Gitweb: http://git.kernel.org/tip/1aa167382323eeeeb38368cab85cf17979793cbe
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 27 May 2009 20:20:25 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:44:13 +0200
perf_counter: tools: report: Dynamic sort/print bits
Make the sorting and printing dynamic.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182100.921953817@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 141 ++++++++++++++++++++-------
1 files changed, 107 insertions(+), 34 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 2762564..856186f 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -699,14 +699,41 @@ struct hist_entry {
uint32_t count;
};
+/*
+ * configurable sorting bits
+ */
+
+struct sort_entry {
+ struct list_head list;
+
+ int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
+ size_t (*print)(FILE *fp, struct hist_entry *);
+};
+
static int64_t
-hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
+sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
{
- uint64_t ip_l, ip_r;
- int cmp = right->thread->pid - left->thread->pid;
+ return right->thread->pid - left->thread->pid;
+}
+
+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)));
+}
- if (cmp)
- return cmp;
+static struct sort_entry sort_thread = {
+ .cmp = sort__thread_cmp,
+ .print = sort__thread_print,
+};
+
+static int64_t
+sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ uint64_t ip_l, ip_r;
if (left->sym == right->sym)
return 0;
@@ -717,6 +744,79 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
return (int64_t)(ip_r - ip_l);
}
+static size_t
+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);
+
+ 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>");
+
+ return ret;
+}
+
+static struct sort_entry sort_sym = {
+ .cmp = sort__sym_cmp,
+ .print = sort__sym_print,
+};
+
+static LIST_HEAD(hist_entry__sort_list);
+
+static void setup_sorting(void)
+{
+ list_add_tail(&sort_thread.list, &hist_entry__sort_list);
+ list_add_tail(&sort_sym.list, &hist_entry__sort_list);
+}
+
+static int64_t
+hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ struct sort_entry *se;
+ int64_t cmp = 0;
+
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ cmp = se->cmp(left, right);
+ if (cmp)
+ break;
+ }
+
+ return cmp;
+}
+
+static size_t
+hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
+{
+ struct sort_entry *se;
+ size_t ret;
+
+ if (total_samples) {
+ ret = fprintf(fp, "%5.2f%% ",
+ (self->count * 100.0) / total_samples);
+ } else
+ ret = fprintf(fp, "%12d ", self->count);
+
+ list_for_each_entry(se, &hist_entry__sort_list, list)
+ ret += se->print(fp, self);
+
+ ret += fprintf(fp, "\n");
+
+ return ret;
+}
+
+/*
+ * collect histogram counts
+ */
+
static int
hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
struct symbol *sym, uint64_t ip, char level)
@@ -762,35 +862,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
return 0;
}
-static size_t
-hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
-{
- char bf[32];
- size_t ret;
-
- if (total_samples) {
- ret = fprintf(fp, "%5.2f%% ",
- (self->count * 100.0) / total_samples);
- } else
- ret = fprintf(fp, "%12d ", self->count);
-
- ret += fprintf(fp, "%14s [%c] ",
- thread__name(self->thread, bf, sizeof(bf)),
- self->level);
-
- if (verbose)
- ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
-
- if (self->level != '.')
- ret += fprintf(fp, "%s\n",
- self->sym ? self->sym->name : "<unknown>");
- else
- ret += fprintf(fp, "%s: %s\n",
- self->dso ? self->dso->name : "<unknown>",
- self->sym ? self->sym->name : "<unknown>");
- return ret;
-}
-
/*
* reverse the map, sort on count.
*/
@@ -1077,6 +1148,8 @@ int cmd_report(int argc, const char **argv, const char *prefix)
parse_options(argc, argv, options, report_usage, 0);
+ setup_sorting();
+
setup_pager();
return __cmd_report();
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] pref_counter: tools: report: Add --sort option
2009-05-27 18:20 ` [PATCH 5/7] pref_counter: tools: report: --sort option Peter Zijlstra
@ 2009-05-27 19:52 ` tip-bot for Peter Zijlstra
0 siblings, 0 replies; 15+ messages in thread
From: tip-bot for Peter Zijlstra @ 2009-05-27 19:52 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: 37f440cba299bb479cf45d12eef923f0979dbcaf
Gitweb: http://git.kernel.org/tip/37f440cba299bb479cf45d12eef923f0979dbcaf
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 27 May 2009 20:20:26 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:44:14 +0200
pref_counter: tools: report: Add --sort option
option parsing for dynamic sorting.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182101.041817692@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 43 +++++++++++++++++++++++++-
1 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 856186f..982abce 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -20,6 +20,7 @@
static char const *input_name = "perf.data";
static char *vmlinux = NULL;
+static char *sort_order = "pid,symbol";
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -770,12 +771,49 @@ static struct sort_entry sort_sym = {
.print = sort__sym_print,
};
+struct sort_dimension {
+ char *name;
+ struct sort_entry *entry;
+ int taken;
+};
+
+static struct sort_dimension sort_dimensions[] = {
+ { .name = "pid", .entry = &sort_thread, },
+ { .name = "symbol", .entry = &sort_sym, },
+};
+
static LIST_HEAD(hist_entry__sort_list);
+static int sort_dimension__add(char *tok)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
+ struct sort_dimension *sd = &sort_dimensions[i];
+
+ if (sd->taken)
+ continue;
+
+ if (strcmp(tok, sd->name))
+ continue;
+
+ list_add_tail(&sd->entry->list, &hist_entry__sort_list);
+ sd->taken = 1;
+ return 0;
+ }
+
+ return -ESRCH;
+}
+
static void setup_sorting(void)
{
- list_add_tail(&sort_thread.list, &hist_entry__sort_list);
- list_add_tail(&sort_sym.list, &hist_entry__sort_list);
+ char *tmp, *tok, *str = strdup(sort_order);
+
+ for (tok = strtok_r(str, ", ", &tmp);
+ tok; tok = strtok_r(NULL, ", ", &tmp))
+ sort_dimension__add(tok);
+
+ free(str);
}
static int64_t
@@ -1137,6 +1175,7 @@ static const struct option options[] = {
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
+ OPT_STRING('s', "sort", &sort_order, "foo", "bar"),
OPT_END()
};
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] perf_counter: tools: report: Add comm sorting
2009-05-27 18:20 ` [PATCH 6/7] perf_counter: tools: report: add comm sorting Peter Zijlstra
@ 2009-05-27 19:52 ` tip-bot for Peter Zijlstra
0 siblings, 0 replies; 15+ messages in thread
From: tip-bot for Peter Zijlstra @ 2009-05-27 19:52 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: 992444b173f35997f96f5cbb214f0de81d1b97ff
Gitweb: http://git.kernel.org/tip/992444b173f35997f96f5cbb214f0de81d1b97ff
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 27 May 2009 20:20:27 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:44:14 +0200
perf_counter: tools: report: Add comm sorting
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182101.129302022@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 30 +++++++++++++++++++++++++++
1 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 982abce..a634022 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -732,6 +732,35 @@ static struct sort_entry sort_thread = {
};
static int64_t
+sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ char *comm_l = left->thread->comm;
+ char *comm_r = right->thread->comm;
+
+ if (!comm_l || !comm_r) {
+ if (!comm_l && !comm_r)
+ return 0;
+ else if (!comm_l)
+ return -1;
+ else
+ return 1;
+ }
+
+ return strcmp(comm_l, comm_r);
+}
+
+static size_t
+sort__comm_print(FILE *fp, struct hist_entry *self)
+{
+ return fprintf(fp, "%20s ", self->thread->comm ?: "<unknown>");
+}
+
+static struct sort_entry sort_comm = {
+ .cmp = sort__comm_cmp,
+ .print = sort__comm_print,
+};
+
+static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
uint64_t ip_l, ip_r;
@@ -779,6 +808,7 @@ struct sort_dimension {
static struct sort_dimension sort_dimensions[] = {
{ .name = "pid", .entry = &sort_thread, },
+ { .name = "comm", .entry = &sort_comm, },
{ .name = "symbol", .entry = &sort_sym, },
};
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] pref_counter: tools: report: Add dso sorting
2009-05-27 18:20 ` [PATCH 7/7] pref_counter: tools: report: add dso sorting Peter Zijlstra
@ 2009-05-27 19:52 ` tip-bot for Peter Zijlstra
2009-05-27 20:46 ` [tip:perfcounters/core] pref_counter: tools: report: Add header printout & prettify tip-bot for Ingo Molnar
1 sibling, 0 replies; 15+ messages in thread
From: tip-bot for Peter Zijlstra @ 2009-05-27 19:52 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: 55e5ec41a9de46b6ca06031f4fbdfdfc76dc24dc
Gitweb: http://git.kernel.org/tip/55e5ec41a9de46b6ca06031f4fbdfdfc76dc24dc
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 27 May 2009 20:20:28 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:44:15 +0200
pref_counter: tools: report: Add dso sorting
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182101.229504802@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 30 +++++++++++++++++++++++++++
1 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index a634022..30e12c7 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -761,6 +761,35 @@ static struct sort_entry sort_comm = {
};
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 = {
+ .cmp = sort__dso_cmp,
+ .print = sort__dso_print,
+};
+
+static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
uint64_t ip_l, ip_r;
@@ -809,6 +838,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, },
};
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [tip:perfcounters/core] pref_counter: tools: report: Add header printout & prettify
2009-05-27 18:20 ` [PATCH 7/7] pref_counter: tools: report: add dso sorting Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] pref_counter: tools: report: Add " tip-bot for Peter Zijlstra
@ 2009-05-27 20:46 ` tip-bot for Ingo Molnar
1 sibling, 0 replies; 15+ messages in thread
From: tip-bot for Ingo Molnar @ 2009-05-27 20:46 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, acme, paulus, hpa, mingo, jkacur, a.p.zijlstra,
efault, tglx, cjashfor, mingo
Commit-ID: 2d65537ee7cd4a0818ea80a97ab7932368fff5cd
Gitweb: http://git.kernel.org/tip/2d65537ee7cd4a0818ea80a97ab7932368fff5cd
Author: Ingo Molnar <mingo@elte.hu>
AuthorDate: Wed, 27 May 2009 21:36:22 +0200
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 27 May 2009 21:40:47 +0200
pref_counter: tools: report: Add header printout & prettify
Old default output:
3.12% perf-report [.] ./perf-report: dsos__find
2.44% perf-report [k] kernel: kallsyms_expand_symbol
2.28% :4483 [.] <unknown>: <unknown>
2.05% :4174 [k] kernel: _spin_lock_irqsave
2.01% perf-report [k] kernel: vsnprintf
1.92% perf-report [k] kernel: format_decode
1.92% :4438 [k] kernel: _spin_lock
New default output:
#
# Overhead Command File: Symbol
# ........ ....... ............
#
6.54% perf [k] kernel: kallsyms_expand_symbol
6.26% perf [.] /home/mingo/tip/Documentation/perf_counter/perf: dso__insert_symbol
4.76% perf [.] /home/mingo/tip/Documentation/perf_counter/perf: hex2long
4.55% perf [k] kernel: number
4.48% perf [k] kernel: format_decode
4.09% perf [k] kernel: vsnprintf
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182101.229504802@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/perf_counter/builtin-report.c | 40 ++++++++++++++++++++-------
1 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 30e12c7..6df95c2 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -708,6 +708,7 @@ struct sort_entry {
struct list_head list;
int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
+ size_t (*print_header)(FILE *fp);
size_t (*print)(FILE *fp, struct hist_entry *);
};
@@ -722,7 +723,7 @@ sort__thread_print(FILE *fp, struct hist_entry *self)
{
char bf[32];
- return fprintf(fp, "%14s ",
+ return fprintf(fp, " %16s",
thread__name(self->thread, bf, sizeof(bf)));
}
@@ -752,7 +753,7 @@ 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 = {
@@ -781,7 +782,7 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
static size_t
sort__dso_print(FILE *fp, struct hist_entry *self)
{
- return fprintf(fp, "%64s ", self->dso ? self->dso->name : "<unknown>");
+ return fprintf(fp, " %64s", self->dso ? self->dso->name : "<unknown>");
}
static struct sort_entry sort_dso = {
@@ -803,21 +804,33 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
return (int64_t)(ip_r - ip_l);
}
+static size_t sort__sym_print_header(FILE *fp)
+{
+ size_t ret = 0;
+
+ ret += fprintf(fp, "#\n");
+ ret += fprintf(fp, "# Overhead Command File: Symbol\n");
+ ret += fprintf(fp, "# ........ ....... ............\n");
+ ret += fprintf(fp, "#\n");
+
+ return ret;
+}
+
static size_t
sort__sym_print(FILE *fp, struct hist_entry *self)
{
size_t ret = 0;
- ret += fprintf(fp, "[%c] ", self->level);
+ 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 ",
+ ret += fprintf(fp, " kernel: %s",
self->sym ? self->sym->name : "<unknown>");
else
- ret += fprintf(fp, "%s: %s ",
+ ret += fprintf(fp, " %s: %s",
self->dso ? self->dso->name : "<unknown>",
self->sym ? self->sym->name : "<unknown>");
@@ -825,8 +838,9 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
}
static struct sort_entry sort_sym = {
- .cmp = sort__sym_cmp,
- .print = sort__sym_print,
+ .cmp = sort__sym_cmp,
+ .print_header = sort__sym_print_header,
+ .print = sort__sym_print,
};
struct sort_dimension {
@@ -898,7 +912,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);
@@ -1003,9 +1017,15 @@ 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;
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ if (se->print_header)
+ ret += se->print_header(fp);
+ }
+
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);
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-05-27 20:48 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-27 18:20 [PATCH 0/7] perf report --sort Peter Zijlstra
2009-05-27 18:20 ` [PATCH 1/7] perf_counter: tools: /usr/lib/debug%s.debug support Peter Zijlstra
2009-05-27 18:20 ` [PATCH 2/7] perf_counter: tools: report: add vmlinux support Peter Zijlstra
2009-05-27 19:51 ` [tip:perfcounters/core] perf_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 3/7] perf_counter: tools: report: rework histogram code Peter Zijlstra
2009-05-27 19:51 ` [tip:perfcounters/core] perf_counter: tools: report: Rework " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 4/7] perf_counter: tools: report: dynamic sort/print bits Peter Zijlstra
2009-05-27 19:51 ` [tip:perfcounters/core] perf_counter: tools: report: Dynamic " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 5/7] pref_counter: tools: report: --sort option Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] pref_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 6/7] perf_counter: tools: report: add comm sorting Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] perf_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 18:20 ` [PATCH 7/7] pref_counter: tools: report: add dso sorting Peter Zijlstra
2009-05-27 19:52 ` [tip:perfcounters/core] pref_counter: tools: report: Add " tip-bot for Peter Zijlstra
2009-05-27 20:46 ` [tip:perfcounters/core] pref_counter: tools: report: Add header printout & prettify tip-bot for Ingo Molnar
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.