Commit 59c624e2 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf hists browser: Fix percent display in callchains

When there's only a single callchain, perf doesn't print its percentage
in front of the symbols.  This is because it assumes that the percentage
is same as parents.  But if a percent limit is applied, it's possible
that there are actually a couple of child nodes but only one of them is
shown.  In this case it should display the percent to prevent
misunderstanding of its percentage is same as the parent's.

For example, let's see the following callchain.

  $ perf report --no-children --percent-limit 0.01 --tui
  ...
  -    0.06%  sleep    [kernel.vmlinux]    [k] kmem_cache_alloc_trace
       kmem_cache_alloc_trace
     - perf_event_mmap
        - 0.04% mmap_region
             do_mmap_pgoff
           - vm_mmap_pgoff
              + 0.02% sys_mmap_pgoff
              + 0.02% vm_mmap
           + 0.02% mprotect_fixup

Current code omits the percent if 'mmap_region' becomes the only node
when percent limit is set to 0.03%, its percent is not 0.06% but users
will assume it incorrectly.

Before:

  $ perf report --no-children --percent-limit 0.03 --tui
  ...
     0.06%  sleep    [kernel.vmlinux]    [k] kmem_cache_alloc_trace
       kmem_cache_alloc_trace
     - perf_event_mmap
        - mmap_region
          do_mmap_pgoff
          vm_mmap_pgoff

After:

  $ perf report --no-children --percent-limit 0.03 --tui
  ...
     0.06%  sleep    [kernel.vmlinux]    [k] kmem_cache_alloc_trace
       kmem_cache_alloc_trace
     - perf_event_mmap
        - 0.04% mmap_region
             do_mmap_pgoff
             vm_mmap_pgoff
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1453909257-26015-10-git-send-email-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 5eca104e
...@@ -657,10 +657,24 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, ...@@ -657,10 +657,24 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
return 1; return 1;
} }
static bool check_percent_display(struct rb_node *node, u64 parent_total)
{
struct callchain_node *child;
if (node == NULL)
return false;
if (rb_next(node))
return true;
child = rb_entry(node, struct callchain_node, rb_node);
return callchain_cumul_hits(child) != parent_total;
}
static int hist_browser__show_callchain_flat(struct hist_browser *browser, static int hist_browser__show_callchain_flat(struct hist_browser *browser,
struct rb_root *root, struct rb_root *root,
unsigned short row, u64 total, unsigned short row, u64 total,
u64 parent_total __maybe_unused, u64 parent_total,
print_callchain_entry_fn print, print_callchain_entry_fn print,
struct callchain_print_arg *arg, struct callchain_print_arg *arg,
check_output_full_fn is_output_full) check_output_full_fn is_output_full)
...@@ -670,7 +684,7 @@ static int hist_browser__show_callchain_flat(struct hist_browser *browser, ...@@ -670,7 +684,7 @@ static int hist_browser__show_callchain_flat(struct hist_browser *browser,
bool need_percent; bool need_percent;
node = rb_first(root); node = rb_first(root);
need_percent = node && rb_next(node); need_percent = check_percent_display(node, parent_total);
while (node) { while (node) {
struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
...@@ -764,7 +778,7 @@ static char *hist_browser__folded_callchain_str(struct hist_browser *browser, ...@@ -764,7 +778,7 @@ static char *hist_browser__folded_callchain_str(struct hist_browser *browser,
static int hist_browser__show_callchain_folded(struct hist_browser *browser, static int hist_browser__show_callchain_folded(struct hist_browser *browser,
struct rb_root *root, struct rb_root *root,
unsigned short row, u64 total, unsigned short row, u64 total,
u64 parent_total __maybe_unused, u64 parent_total,
print_callchain_entry_fn print, print_callchain_entry_fn print,
struct callchain_print_arg *arg, struct callchain_print_arg *arg,
check_output_full_fn is_output_full) check_output_full_fn is_output_full)
...@@ -774,7 +788,7 @@ static int hist_browser__show_callchain_folded(struct hist_browser *browser, ...@@ -774,7 +788,7 @@ static int hist_browser__show_callchain_folded(struct hist_browser *browser,
bool need_percent; bool need_percent;
node = rb_first(root); node = rb_first(root);
need_percent = node && rb_next(node); need_percent = check_percent_display(node, parent_total);
while (node) { while (node) {
struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
...@@ -863,7 +877,7 @@ static int hist_browser__show_callchain_graph(struct hist_browser *browser, ...@@ -863,7 +877,7 @@ static int hist_browser__show_callchain_graph(struct hist_browser *browser,
percent_total = parent_total; percent_total = parent_total;
node = rb_first(root); node = rb_first(root);
need_percent = node && rb_next(node); need_percent = check_percent_display(node, parent_total);
while (node) { while (node) {
struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); struct callchain_node *child = rb_entry(node, struct callchain_node, 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