From: Andi Kleen <andi@firstfloor.org>
To: acme@infradead.org
Cc: jolsa@redhat.com, namhyung@kernel.org, mingo@kernel.org,
dsahern@gmail.com, fweisbec@gmail.com, adrian.hunter@intel.com,
linux-kernel@vger.kernel.org, Andi Kleen <ak@linux.intel.com>
Subject: [PATCH 4/9] perf, tools: Filter out small loops from LBR-as-call-stack
Date: Sat, 11 Jan 2014 11:42:54 -0800 [thread overview]
Message-ID: <1389469379-13340-5-git-send-email-andi@firstfloor.org> (raw)
In-Reply-To: <1389469379-13340-1-git-send-email-andi@firstfloor.org>
From: Andi Kleen <ak@linux.intel.com>
Small loops can cause unnecessary duplication in the LBR-as-callstack,
because the loop body appears multiple times. Filter out duplications
from the LBR before unifying it into the histories. This way the
same loop body only appears once.
This uses a simple hash based cycle detector. It takes some short
cuts (not handling hash collisions) so in rare cases duplicates may
be missed.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/util/machine.c | 73 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 62 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index f2eaf85..2f440f2 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -11,6 +11,7 @@
#include <stdbool.h>
#include <symbol/kallsyms.h>
#include "unwind.h"
+#include "linux/hash.h"
int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
{
@@ -1296,6 +1297,46 @@ static int add_callchain_ip(struct machine *machine,
return callchain_cursor_append(&callchain_cursor, ip, al.map, al.sym);
}
+#define CHASHSZ 127
+#define CHASHBITS 7
+#define NO_ENTRY 0xff
+
+#define PERF_MAX_BRANCH_DEPTH 127
+
+/* Remove loops. */
+static int remove_loops(struct branch_entry *l, int nr)
+{
+ int i, j, off;
+ unsigned char chash[CHASHSZ];
+ memset(chash, -1, sizeof(chash));
+
+ BUG_ON(nr >= 256);
+ for (i = 0; i < nr; i++) {
+ int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;
+
+ /* no collision handling for now */
+ if (chash[h] == NO_ENTRY) {
+ chash[h] = i;
+ } else if (l[chash[h]].from == l[i].from) {
+ bool is_loop = true;
+ /* check if it is a real loop */
+ off = 0;
+ for (j = chash[h]; j < i && i + off < nr; j++, off++)
+ if (l[j].from != l[i + off].from) {
+ is_loop = false;
+ break;
+ }
+ if (is_loop) {
+ memmove(l + i, l + i + off,
+ (nr - (i + off))
+ * sizeof(struct branch_entry));
+ nr -= off;
+ }
+ }
+ }
+ return nr;
+}
+
static int machine__resolve_callchain_sample(struct machine *machine,
struct thread *thread,
struct ip_callchain *chain,
@@ -1322,29 +1363,39 @@ static int machine__resolve_callchain_sample(struct machine *machine,
* - No extra filters
* - No annotations (should annotate somehow)
* - When the sample is near the beginning of the function
- * we may overlap with the real callstack. Could handle this
- * case later, by checking against the last ip.
+ * we may overlap with the real callstack.
*/
+ if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
+ pr_warning("corrupted branch chain. skipping...\n");
+ return 0;
+ }
+
if (callchain_param.branch_callstack) {
- for (i = 0; i < branch->nr; i++) {
- struct branch_entry *b;
+ int nr = branch->nr;
+ struct branch_entry be[nr];
+ for (i = 0; i < nr; i++) {
if (callchain_param.order == ORDER_CALLEE)
- b = &branch->entries[i];
+ be[i] = branch->entries[i];
else
- b = &branch->entries[branch->nr - i - 1];
+ be[i] = branch->entries[branch->nr - i - 1];
+ }
- err = add_callchain_ip(machine, thread, parent, root_al,
- -1, b->to);
+ nr = remove_loops(be, nr);
+
+ for (i = 0; i < nr; i++) {
+ err = add_callchain_ip(machine, thread, parent,
+ root_al,
+ -1, be[i].to);
if (!err)
- err = add_callchain_ip(machine, thread, parent, root_al,
- -1, b->from);
+ err = add_callchain_ip(machine, thread,
+ parent, root_al,
+ -1, be[i].from);
if (err == -EINVAL)
break;
if (err)
return err;
-
}
}
--
1.8.3.1
next prev parent reply other threads:[~2014-01-11 19:43 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-11 19:42 perf: Implement lbr-as-callgraph v2 Andi Kleen
2014-01-11 19:42 ` [PATCH 1/9] perf, tools: fix BFD detection on opensuse Andi Kleen
2014-01-12 15:16 ` Jiri Olsa
2014-01-13 9:03 ` Namhyung Kim
2014-01-12 15:40 ` David Ahern
2014-03-02 8:57 ` [tip:perf/urgent] perf " tip-bot for Andi Kleen
2014-01-11 19:42 ` [PATCH 2/9] perf, tools: Support handling complete branch stacks as histograms Andi Kleen
2014-01-11 19:42 ` [PATCH 3/9] perf, tools: Add --branch-history option to report v2 Andi Kleen
2014-01-11 19:42 ` Andi Kleen [this message]
2014-01-11 19:42 ` [PATCH 5/9] perf, tools: Enable printing the srcline in the history Andi Kleen
2014-01-11 19:42 ` [PATCH 6/9] perf, tools: Fix max stack handling with lbr-as-callgraph Andi Kleen
2014-01-11 19:42 ` [PATCH 7/9] perf, tools: Add overlap detection for report branch-call-stack mode Andi Kleen
2014-01-11 19:42 ` [PATCH 8/9] perf, tools: Only print base source file for srcline Andi Kleen
2014-01-11 19:42 ` [PATCH 9/9] perf, tools: Support source line numbers in annotate Andi Kleen
2014-01-12 15:16 ` perf: Implement lbr-as-callgraph v2 Jiri Olsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1389469379-13340-5-git-send-email-andi@firstfloor.org \
--to=andi@firstfloor.org \
--cc=acme@infradead.org \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=dsahern@gmail.com \
--cc=fweisbec@gmail.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=namhyung@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®