perf report: Allow limiting the number of entries to print in callchains

Works by adding a third parameter to the '-g' argument, after the graph
type and minimum percentage, for example:

[root@doppio linux-2.6-tip]# perf report -g fractal,0.5,2

Will show only the first two symbols where at least 0.5% of the samples
took place.

All the other symbols that don't fall outside these constraints will be
put together in the last entry, prefixed with "[...]" and the total
percentage for them.
Suggested-by: default avatarArjan van de Ven <arjan@linux.intel.com>
Acked-by: default avatarArjan van de Ven <arjan@linux.intel.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 1f626bc3
...@@ -343,7 +343,7 @@ static int ...@@ -343,7 +343,7 @@ static int
parse_callchain_opt(const struct option *opt __used, const char *arg, parse_callchain_opt(const struct option *opt __used, const char *arg,
int unset) int unset)
{ {
char *tok; char *tok, *tok2;
char *endptr; char *endptr;
/* /*
...@@ -388,10 +388,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, ...@@ -388,10 +388,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
if (!tok) if (!tok)
goto setup; goto setup;
tok2 = strtok(NULL, ",");
callchain_param.min_percent = strtod(tok, &endptr); callchain_param.min_percent = strtod(tok, &endptr);
if (tok == endptr) if (tok == endptr)
return -1; return -1;
if (tok2)
callchain_param.print_limit = strtod(tok2, &endptr);
setup: setup:
if (register_callchain_param(&callchain_param) < 0) { if (register_callchain_param(&callchain_param) < 0) {
fprintf(stderr, "Can't register callchain params\n"); fprintf(stderr, "Can't register callchain params\n");
......
...@@ -34,6 +34,7 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, ...@@ -34,6 +34,7 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
struct callchain_param { struct callchain_param {
enum chain_mode mode; enum chain_mode mode;
u32 print_limit;
double min_percent; double min_percent;
sort_chain_func_t sort; sort_chain_func_t sort;
}; };
......
...@@ -333,6 +333,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -333,6 +333,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
u64 remaining; u64 remaining;
size_t ret = 0; size_t ret = 0;
int i; int i;
uint entries_printed = 0;
if (callchain_param.mode == CHAIN_GRAPH_REL) if (callchain_param.mode == CHAIN_GRAPH_REL)
new_total = self->children_hit; new_total = self->children_hit;
...@@ -379,6 +380,8 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -379,6 +380,8 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
new_depth_mask | (1 << depth), new_depth_mask | (1 << depth),
left_margin); left_margin);
node = next; node = next;
if (++entries_printed == callchain_param.print_limit)
break;
} }
if (callchain_param.mode == CHAIN_GRAPH_REL && if (callchain_param.mode == CHAIN_GRAPH_REL &&
...@@ -404,6 +407,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -404,6 +407,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
bool printed = false; bool printed = false;
int i = 0; int i = 0;
int ret = 0; int ret = 0;
u32 entries_printed = 0;
list_for_each_entry(chain, &self->val, list) { list_for_each_entry(chain, &self->val, list) {
if (!i++ && sort__first_dimension == SORT_SYM) if (!i++ && sort__first_dimension == SORT_SYM)
...@@ -424,6 +428,9 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -424,6 +428,9 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
ret += fprintf(fp, " %s\n", chain->ms.sym->name); ret += fprintf(fp, " %s\n", chain->ms.sym->name);
else else
ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
if (++entries_printed == callchain_param.print_limit)
break;
} }
ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin); ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
...@@ -462,6 +469,7 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, ...@@ -462,6 +469,7 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
struct rb_node *rb_node; struct rb_node *rb_node;
struct callchain_node *chain; struct callchain_node *chain;
size_t ret = 0; size_t ret = 0;
u32 entries_printed = 0;
rb_node = rb_first(&self->sorted_chain); rb_node = rb_first(&self->sorted_chain);
while (rb_node) { while (rb_node) {
...@@ -484,6 +492,8 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, ...@@ -484,6 +492,8 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
break; break;
} }
ret += fprintf(fp, "\n"); ret += fprintf(fp, "\n");
if (++entries_printed == callchain_param.print_limit)
break;
rb_node = rb_next(rb_node); rb_node = rb_next(rb_node);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment