Commit 25446036 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Ingo Molnar

perf tools: callchain: Fix sum of percentages to be 100% by displaying amount...

perf tools: callchain: Fix sum of percentages to be 100% by displaying amount of ignored chains in fractal mode

When we filter the callchains below a given percentage, we
ignore them and the end result only shows entries that have an
upper percentage than the filter threshold.

It seems to users then that we have an imbalance in the
percentage, as if the sum inside a profiled branch doesn't
reach 100%.

Since in the past there have been real perf report bugs that
showed the same sypmtom, it would be nice to assure the user
that the data is perfect and trustable and it all sums up to
100.00%.

So fix this by displaying the remaining hits that have been
filtered but without more detail than their amount in each
branches. Example while filtering below 50%:

7.73%  [k] delay_tsc
                |
                |--98.22%-- __const_udelay
                |          |
                |          |--86.37%-- ath5k_hw_register_timeout
                |          |          ath5k_hw_noise_floor_calibration
                |          |          ath5k_hw_reset
                |          |          ath5k_reset
                |          |          ath5k_config
                |          |          ieee80211_hw_config
                |          |          |
                |          |          |--88.53%-- ieee80211_scan_work
                |          |          |          worker_thread
                |          |          |          kthread
                |          |          |          child_rip
                |          |           --11.47%-- [...]
                |           --13.63%-- [...]
                 --1.78%-- [...]
Reported-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <1249690585-9145-4-git-send-email-fweisbec@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent b1a88349
...@@ -891,6 +891,21 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, ...@@ -891,6 +891,21 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
return ret; return ret;
} }
static struct symbol *rem_sq_bracket;
static struct callchain_list rem_hits;
static void init_rem_hits(void)
{
rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
if (!rem_sq_bracket) {
fprintf(stderr, "Not enough memory to display remaining hits\n");
return;
}
strcpy(rem_sq_bracket->name, "[...]");
rem_hits.sym = rem_sq_bracket;
}
static size_t static size_t
callchain__fprintf_graph(FILE *fp, struct callchain_node *self, callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
u64 total_samples, int depth, int depth_mask) u64 total_samples, int depth, int depth_mask)
...@@ -900,6 +915,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -900,6 +915,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
struct callchain_list *chain; struct callchain_list *chain;
int new_depth_mask = depth_mask; int new_depth_mask = depth_mask;
u64 new_total; u64 new_total;
u64 remaining;
size_t ret = 0; size_t ret = 0;
int i; int i;
...@@ -908,17 +924,25 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -908,17 +924,25 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
else else
new_total = total_samples; new_total = total_samples;
remaining = new_total;
node = rb_first(&self->rb_root); node = rb_first(&self->rb_root);
while (node) { while (node) {
u64 cumul;
child = rb_entry(node, struct callchain_node, rb_node); child = rb_entry(node, struct callchain_node, rb_node);
cumul = cumul_hits(child);
remaining -= cumul;
/* /*
* The depth mask manages the output of pipes that show * The depth mask manages the output of pipes that show
* the depth. We don't want to keep the pipes of the current * the depth. We don't want to keep the pipes of the current
* level for the last child of this depth * level for the last child of this depth.
* Except if we have remaining filtered hits. They will
* supersede the last child
*/ */
next = rb_next(node); next = rb_next(node);
if (!next) if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
new_depth_mask &= ~(1 << (depth - 1)); new_depth_mask &= ~(1 << (depth - 1));
/* /*
...@@ -933,7 +957,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -933,7 +957,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
ret += ipchain__fprintf_graph(fp, chain, depth, ret += ipchain__fprintf_graph(fp, chain, depth,
new_depth_mask, i++, new_depth_mask, i++,
new_total, new_total,
cumul_hits(child)); cumul);
} }
ret += callchain__fprintf_graph(fp, child, new_total, ret += callchain__fprintf_graph(fp, child, new_total,
depth + 1, depth + 1,
...@@ -941,6 +965,19 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ...@@ -941,6 +965,19 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
node = next; node = next;
} }
if (callchain_param.mode == CHAIN_GRAPH_REL &&
remaining && remaining != new_total) {
if (!rem_sq_bracket)
return ret;
new_depth_mask &= ~(1 << (depth - 1));
ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
new_depth_mask, 0, new_total,
remaining);
}
return ret; return ret;
} }
...@@ -1361,6 +1398,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) ...@@ -1361,6 +1398,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
unsigned int width; unsigned int width;
char *col_width = col_width_list_str; char *col_width = col_width_list_str;
init_rem_hits();
fprintf(fp, "# Samples: %Ld\n", (u64)total_samples); fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
fprintf(fp, "#\n"); fprintf(fp, "#\n");
...@@ -1432,6 +1471,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) ...@@ -1432,6 +1471,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
} }
fprintf(fp, "\n"); fprintf(fp, "\n");
free(rem_sq_bracket);
return ret; return ret;
} }
......
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