From 2dc9fb1a7bf013ce24dd34bc25283b60b966f015 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jan 2014 14:25:35 +0900 Subject: perf tools: Factor out sample__resolve_callchain() The report__resolve_callchain() can be shared with perf top code as it doesn't really depend on the perf report code. Factor it out as sample__resolve_callchain(). The same goes to the hist_entry__append_ callchain() too. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Andi Kleen Cc: Arun Sharma Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Rodrigo Campos Link: http://lkml.kernel.org/r/1389677157-30513-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'tools/perf/util/callchain.c') diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index e3970e3..9eb4f57 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -17,6 +17,8 @@ #include "hist.h" #include "util.h" +#include "sort.h" +#include "machine.h" #include "callchain.h" __thread struct callchain_cursor callchain_cursor; @@ -531,3 +533,24 @@ int callchain_cursor_append(struct callchain_cursor *cursor, return 0; } + +int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, + struct perf_evsel *evsel, struct addr_location *al, + int max_stack) +{ + if (sample->callchain == NULL) + return 0; + + if (symbol_conf.use_callchain || sort__has_parent) { + return machine__resolve_callchain(al->machine, evsel, al->thread, + sample, parent, al, max_stack); + } + return 0; +} + +int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) +{ + if (!symbol_conf.use_callchain) + return 0; + return callchain_append(he->callchain, &callchain_cursor, sample->period); +} -- cgit v1.1 From b965bb41061ad8d3eafda6e7feef89279fcd3916 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 14 Jan 2014 16:37:15 +0100 Subject: perf callchain: Spare double comparison of callchain first entry When a new callchain child branch matches an existing one in the rbtree, the comparison of its first entry is performed twice: 1) From append_chain_children() on branch lookup 2) If 1) reports a match, append_chain() then compares all entries of the new branch against the matching node in the rbtree, and this comparison includes the first entry of the new branch again. Lets shortcut this by performing the whole comparison only from append_chain() which then returns the result of the comparison between the first entry of the new branch and the iterating node in the rbtree. If the first entry matches, the lookup on the current level of siblings stops and propagates to the children of the matching nodes. This results in less comparisons performed by the CPU. Signed-off-by: Frederic Weisbecker Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1389713836-13375-3-git-send-email-fweisbec@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'tools/perf/util/callchain.c') diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 9eb4f57..662867d 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -15,6 +15,8 @@ #include #include +#include "asm/bug.h" + #include "hist.h" #include "util.h" #include "sort.h" @@ -358,19 +360,14 @@ append_chain_children(struct callchain_node *root, /* lookup in childrens */ while (*p) { s64 ret; - struct callchain_list *cnode; parent = *p; rnode = rb_entry(parent, struct callchain_node, rb_node_in); - cnode = list_first_entry(&rnode->val, struct callchain_list, - list); - /* just check first entry */ - ret = match_chain(node, cnode); - if (ret == 0) { - append_chain(rnode, cursor, period); + /* If at least first entry matches, rely to children */ + ret = append_chain(rnode, cursor, period); + if (ret == 0) goto inc_children_hit; - } if (ret < 0) p = &parent->rb_left; @@ -396,6 +393,7 @@ append_chain(struct callchain_node *root, u64 start = cursor->pos; bool found = false; u64 matches; + int cmp = 0; /* * Lookup in the current node @@ -410,7 +408,8 @@ append_chain(struct callchain_node *root, if (!node) break; - if (match_chain(node, cnode) != 0) + cmp = match_chain(node, cnode); + if (cmp) break; found = true; @@ -420,9 +419,10 @@ append_chain(struct callchain_node *root, /* matches not, relay no the parent */ if (!found) { + WARN_ONCE(!cmp, "Chain comparison error\n"); cursor->curr = curr_snap; cursor->pos = start; - return -1; + return cmp; } matches = cursor->pos - start; -- cgit v1.1 From 2a29190c040c0b11e39197c67abf6f87e0a61f9a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 14 Jan 2014 16:37:16 +0100 Subject: perf tools: Remove unnecessary callchain cursor state restore on unmatch If a new callchain branch doesn't match a single entry of the node that it is given against comparison in append_chain(), then the cursor is expected to be at the same position as it was before the comparison loop. As such, there is no need to restore the cursor position on exit in case of non matching branches. Signed-off-by: Frederic Weisbecker Reviewed-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1389713836-13375-4-git-send-email-fweisbec@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'tools/perf/util/callchain.c') diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 662867d..8d9db45 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -388,7 +388,6 @@ append_chain(struct callchain_node *root, struct callchain_cursor *cursor, u64 period) { - struct callchain_cursor_node *curr_snap = cursor->curr; struct callchain_list *cnode; u64 start = cursor->pos; bool found = false; @@ -420,8 +419,6 @@ append_chain(struct callchain_node *root, /* matches not, relay no the parent */ if (!found) { WARN_ONCE(!cmp, "Chain comparison error\n"); - cursor->curr = curr_snap; - cursor->pos = start; return cmp; } -- cgit v1.1