LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [GIT PULL 0/6] perf/core improments
@ 2011-02-07  0:42 Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 1/6] perf top: Remove superfluous name_len field Arnaldo Carvalho de Melo
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Arnaldo Carvalho de Melo,
	Frederic Weisbecker, Ingo Molnar, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian, Tom Zanussi,
	Arnaldo Carvalho de Melo

Hi Ingo,

        Please consider pulling from:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 perf/core

Regards,

- Arnaldo

Arnaldo Carvalho de Melo (6):
  perf top: Remove superfluous name_len field
  perf annotate: Move annotate functions to util/
  perf annotate: Support multiple histograms in annotation
  perf annotate: Config options for symbol__tty_annotate
  perf annotate: Separate objdump parsing from actual screen rendering
  perf top: Ditch private annotation code, share perf annotate's

 tools/perf/Makefile                    |    2 +
 tools/perf/builtin-annotate.c          |  276 ++--------------
 tools/perf/builtin-report.c            |   18 +-
 tools/perf/builtin-top.c               |  184 ++---------
 tools/perf/util/annotate.c             |  550 ++++++++++++++++++++++++++++++++
 tools/perf/util/annotate.h             |   94 ++++++
 tools/perf/util/hist.c                 |  219 +-------------
 tools/perf/util/hist.h                 |   43 +--
 tools/perf/util/top.c                  |    5 +-
 tools/perf/util/top.h                  |   12 +-
 tools/perf/util/ui/browsers/annotate.c |   45 ++-
 tools/perf/util/ui/browsers/hists.c    |    9 +-
 12 files changed, 769 insertions(+), 688 deletions(-)
 create mode 100644 tools/perf/util/annotate.c
 create mode 100644 tools/perf/util/annotate.h


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] perf top: Remove superfluous name_len field
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
@ 2011-02-07  0:42 ` Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 2/6] perf annotate: Move annotate functions to util/ Arnaldo Carvalho de Melo
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Ingo Molnar, Mike Galbraith, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian, Tom Zanussi

From: Arnaldo Carvalho de Melo <acme@redhat.com>

>From the sym_entry struct, struct symbol already has this field.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-top.c |    3 ---
 tools/perf/util/top.c    |    5 +++--
 tools/perf/util/top.h    |    1 -
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 104de9a..154e088 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -787,9 +787,6 @@ static int symbol_filter(struct map *map, struct symbol *sym)
 		}
 	}
 
-	if (!syme->skip)
-		syme->name_len = strlen(sym->name);
-
 	return 0;
 }
 
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 1d2e265..70a9c13 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -200,6 +200,7 @@ void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
 
 	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
 		struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
+		struct symbol *sym = sym_entry__symbol(syme);
 
 		if (++printed > top->print_entries ||
 		    (int)syme->snap_count < top->count_filter)
@@ -211,7 +212,7 @@ void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
 		if (syme->map->dso->short_name_len > *dso_short_width)
 			*dso_short_width = syme->map->dso->short_name_len;
 
-		if (syme->name_len > *sym_width)
-			*sym_width = syme->name_len;
+		if (sym->namelen > *sym_width)
+			*sym_width = sym->namelen;
 	}
 }
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 611370f..5009508 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -31,7 +31,6 @@ struct sym_entry {
 	unsigned long		snap_count;
 	double			weight;
 	int			skip;
-	u16			name_len;
 	u8			origin;
 	struct map		*map;
 	struct sym_entry_source	*src;
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/6] perf annotate: Move annotate functions to util/
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 1/6] perf top: Remove superfluous name_len field Arnaldo Carvalho de Melo
@ 2011-02-07  0:42 ` Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 3/6] perf annotate: Support multiple histograms in annotation Arnaldo Carvalho de Melo
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Ingo Molnar, Mike Galbraith, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian, Tom Zanussi

From: Arnaldo Carvalho de Melo <acme@redhat.com>

They will be used by perf top, so that we have just one set of routines
to do annotation.

Rename "struct sym_priv" to "struct annotation", etc, to clarify this
code a bit.

Rename "struct sym_ext" to "struct source_line", to give it a meaningful
name, that clarifies that it is a the result of an addr2line call, that
is sorted by percentage one particular source code line appeared in the
annotation.

And since we're moving things around also rename 'sym_hist->ip' to
'sym_hist->addr' as we want to do data structure annotation at some
point.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile                    |    2 +
 tools/perf/builtin-annotate.c          |  255 +-----------------
 tools/perf/builtin-report.c            |    3 +-
 tools/perf/util/annotate.c             |  467 ++++++++++++++++++++++++++++++++
 tools/perf/util/annotate.h             |   65 +++++
 tools/perf/util/hist.c                 |  219 +---------------
 tools/perf/util/hist.h                 |   27 --
 tools/perf/util/ui/browsers/annotate.c |   43 ++--
 8 files changed, 578 insertions(+), 503 deletions(-)
 create mode 100644 tools/perf/util/annotate.c
 create mode 100644 tools/perf/util/annotate.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 4c9499c..be3eb1d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -401,6 +401,7 @@ LIB_H += util/include/dwarf-regs.h
 LIB_H += util/include/asm/dwarf2.h
 LIB_H += util/include/asm/cpufeature.h
 LIB_H += perf.h
+LIB_H += util/annotate.h
 LIB_H += util/cache.h
 LIB_H += util/callchain.h
 LIB_H += util/build-id.h
@@ -444,6 +445,7 @@ LIB_H += $(ARCH_INCLUDE)
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
+LIB_OBJS += $(OUTPUT)util/annotate.o
 LIB_OBJS += $(OUTPUT)util/build-id.o
 LIB_OBJS += $(OUTPUT)util/config.o
 LIB_OBJS += $(OUTPUT)util/ctype.o
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index cd9dec4..9072ef4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -9,6 +9,7 @@
 
 #include "util/util.h"
 
+#include "util/util.h"
 #include "util/color.h"
 #include <linux/list.h>
 #include "util/cache.h"
@@ -18,6 +19,7 @@
 #include "perf.h"
 #include "util/debug.h"
 
+#include "util/annotate.h"
 #include "util/event.h"
 #include "util/parse-options.h"
 #include "util/parse-events.h"
@@ -79,245 +81,10 @@ static int process_sample_event(union perf_event *event,
 	return 0;
 }
 
-static int objdump_line__print(struct objdump_line *self,
-			       struct list_head *head,
-			       struct hist_entry *he, u64 len)
-{
-	struct symbol *sym = he->ms.sym;
-	static const char *prev_line;
-	static const char *prev_color;
-
-	if (self->offset != -1) {
-		const char *path = NULL;
-		unsigned int hits = 0;
-		double percent = 0.0;
-		const char *color;
-		struct sym_priv *priv = symbol__priv(sym);
-		struct sym_ext *sym_ext = priv->ext;
-		struct sym_hist *h = priv->hist;
-		s64 offset = self->offset;
-		struct objdump_line *next = objdump__get_next_ip_line(head, self);
-
-		while (offset < (s64)len &&
-		       (next == NULL || offset < next->offset)) {
-			if (sym_ext) {
-				if (path == NULL)
-					path = sym_ext[offset].path;
-				percent += sym_ext[offset].percent;
-			} else
-				hits += h->ip[offset];
-
-			++offset;
-		}
-
-		if (sym_ext == NULL && h->sum)
-			percent = 100.0 * hits / h->sum;
-
-		color = get_percent_color(percent);
-
-		/*
-		 * Also color the filename and line if needed, with
-		 * the same color than the percentage. Don't print it
-		 * twice for close colored ip with the same filename:line
-		 */
-		if (path) {
-			if (!prev_line || strcmp(prev_line, path)
-				       || color != prev_color) {
-				color_fprintf(stdout, color, " %s", path);
-				prev_line = path;
-				prev_color = color;
-			}
-		}
-
-		color_fprintf(stdout, color, " %7.2f", percent);
-		printf(" :	");
-		color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", self->line);
-	} else {
-		if (!*self->line)
-			printf("         :\n");
-		else
-			printf("         :	%s\n", self->line);
-	}
-
-	return 0;
-}
-
-static struct rb_root root_sym_ext;
-
-static void insert_source_line(struct sym_ext *sym_ext)
-{
-	struct sym_ext *iter;
-	struct rb_node **p = &root_sym_ext.rb_node;
-	struct rb_node *parent = NULL;
-
-	while (*p != NULL) {
-		parent = *p;
-		iter = rb_entry(parent, struct sym_ext, node);
-
-		if (sym_ext->percent > iter->percent)
-			p = &(*p)->rb_left;
-		else
-			p = &(*p)->rb_right;
-	}
-
-	rb_link_node(&sym_ext->node, parent, p);
-	rb_insert_color(&sym_ext->node, &root_sym_ext);
-}
-
-static void free_source_line(struct hist_entry *he, int len)
-{
-	struct sym_priv *priv = symbol__priv(he->ms.sym);
-	struct sym_ext *sym_ext = priv->ext;
-	int i;
-
-	if (!sym_ext)
-		return;
-
-	for (i = 0; i < len; i++)
-		free(sym_ext[i].path);
-	free(sym_ext);
-
-	priv->ext = NULL;
-	root_sym_ext = RB_ROOT;
-}
-
-/* Get the filename:line for the colored entries */
-static void
-get_source_line(struct hist_entry *he, int len, const char *filename)
-{
-	struct symbol *sym = he->ms.sym;
-	u64 start;
-	int i;
-	char cmd[PATH_MAX * 2];
-	struct sym_ext *sym_ext;
-	struct sym_priv *priv = symbol__priv(sym);
-	struct sym_hist *h = priv->hist;
-
-	if (!h->sum)
-		return;
-
-	sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
-	if (!priv->ext)
-		return;
-
-	start = he->ms.map->unmap_ip(he->ms.map, sym->start);
-
-	for (i = 0; i < len; i++) {
-		char *path = NULL;
-		size_t line_len;
-		u64 offset;
-		FILE *fp;
-
-		sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
-		if (sym_ext[i].percent <= 0.5)
-			continue;
-
-		offset = start + i;
-		sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
-		fp = popen(cmd, "r");
-		if (!fp)
-			continue;
-
-		if (getline(&path, &line_len, fp) < 0 || !line_len)
-			goto next;
-
-		sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
-		if (!sym_ext[i].path)
-			goto next;
-
-		strcpy(sym_ext[i].path, path);
-		insert_source_line(&sym_ext[i]);
-
-	next:
-		pclose(fp);
-	}
-}
-
-static void print_summary(const char *filename)
-{
-	struct sym_ext *sym_ext;
-	struct rb_node *node;
-
-	printf("\nSorted summary for file %s\n", filename);
-	printf("----------------------------------------------\n\n");
-
-	if (RB_EMPTY_ROOT(&root_sym_ext)) {
-		printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
-		return;
-	}
-
-	node = rb_first(&root_sym_ext);
-	while (node) {
-		double percent;
-		const char *color;
-		char *path;
-
-		sym_ext = rb_entry(node, struct sym_ext, node);
-		percent = sym_ext->percent;
-		color = get_percent_color(percent);
-		path = sym_ext->path;
-
-		color_fprintf(stdout, color, " %7.2f %s", percent, path);
-		node = rb_next(node);
-	}
-}
-
-static void hist_entry__print_hits(struct hist_entry *self)
-{
-	struct symbol *sym = self->ms.sym;
-	struct sym_priv *priv = symbol__priv(sym);
-	struct sym_hist *h = priv->hist;
-	u64 len = sym->end - sym->start, offset;
-
-	for (offset = 0; offset < len; ++offset)
-		if (h->ip[offset] != 0)
-			printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
-			       sym->start + offset, h->ip[offset]);
-	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
-}
-
 static int hist_entry__tty_annotate(struct hist_entry *he)
 {
-	struct map *map = he->ms.map;
-	struct dso *dso = map->dso;
-	struct symbol *sym = he->ms.sym;
-	const char *filename = dso->long_name, *d_filename;
-	u64 len;
-	LIST_HEAD(head);
-	struct objdump_line *pos, *n;
-
-	if (hist_entry__annotate(he, &head, 0) < 0)
-		return -1;
-
-	if (full_paths)
-		d_filename = filename;
-	else
-		d_filename = basename(filename);
-
-	len = sym->end - sym->start;
-
-	if (print_line) {
-		get_source_line(he, len, filename);
-		print_summary(filename);
-	}
-
-	printf("\n\n------------------------------------------------\n");
-	printf(" Percent |	Source code & Disassembly of %s\n", d_filename);
-	printf("------------------------------------------------\n");
-
-	if (verbose)
-		hist_entry__print_hits(he);
-
-	list_for_each_entry_safe(pos, n, &head, node) {
-		objdump_line__print(pos, &head, he, len);
-		list_del(&pos->node);
-		objdump_line__free(pos);
-	}
-
-	if (print_line)
-		free_source_line(he, len);
-
-	return 0;
+	return symbol__tty_annotate(he->ms.sym, he->ms.map,
+				    print_line, full_paths);
 }
 
 static void hists__find_annotations(struct hists *self)
@@ -327,13 +94,13 @@ static void hists__find_annotations(struct hists *self)
 
 	while (nd) {
 		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
-		struct sym_priv *priv;
+		struct annotation *notes;
 
 		if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
 			goto find_next;
 
-		priv = symbol__priv(he->ms.sym);
-		if (priv->hist == NULL) {
+		notes = symbol__annotation(he->ms.sym);
+		if (notes->histogram == NULL) {
 find_next:
 			if (key == KEY_LEFT)
 				nd = rb_prev(nd);
@@ -362,11 +129,11 @@ find_next:
 			nd = rb_next(nd);
 			/*
 			 * Since we have a hist_entry per IP for the same
-			 * symbol, free he->ms.sym->hist to signal we already
+			 * symbol, free he->ms.sym->histogram to signal we already
 			 * processed this symbol.
 			 */
-			free(priv->hist);
-			priv->hist = NULL;
+			free(notes->histogram);
+			notes->histogram = NULL;
 		}
 	}
 }
@@ -454,7 +221,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 
 	setup_browser(true);
 
-	symbol_conf.priv_size = sizeof(struct sym_priv);
+	symbol_conf.priv_size = sizeof(struct annotation);
 	symbol_conf.try_vmlinux_path = true;
 
 	if (symbol__init() < 0)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 080937c..91e4cdb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -9,6 +9,7 @@
 
 #include "util/util.h"
 
+#include "util/annotate.h"
 #include "util/color.h"
 #include <linux/list.h>
 #include "util/cache.h"
@@ -508,7 +509,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 	 * implementation.
 	 */
 	if (use_browser > 0) {
-		symbol_conf.priv_size = sizeof(struct sym_priv);
+		symbol_conf.priv_size = sizeof(struct annotation);
 		/*
  		 * For searching by name on the "Browse map details".
  		 * providing it only in verbose mode not to bloat too
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
new file mode 100644
index 0000000..9b25575
--- /dev/null
+++ b/tools/perf/util/annotate.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Parts came from builtin-annotate.c, see those files for further
+ * copyright notes.
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "util.h"
+#include "build-id.h"
+#include "color.h"
+#include "cache.h"
+#include "symbol.h"
+#include "debug.h"
+#include "annotate.h"
+
+static int symbol__alloc_hist(struct symbol *sym)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	const int size = (sizeof(*notes->histogram) +
+			  (sym->end - sym->start) * sizeof(u64));
+
+	notes->histogram = zalloc(size);
+	return notes->histogram == NULL ? -1 : 0;
+}
+
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map, u64 addr)
+{
+	unsigned int sym_size, offset;
+	struct annotation *notes;
+	struct sym_hist *h;
+
+	if (!sym || !map)
+		return 0;
+
+	notes = symbol__annotation(sym);
+	if (notes->histogram == NULL && symbol__alloc_hist(sym) < 0)
+		return -ENOMEM;
+
+	sym_size = sym->end - sym->start;
+	offset = addr - sym->start;
+
+	pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
+
+	if (offset >= sym_size)
+		return 0;
+
+	h = notes->histogram;
+	h->sum++;
+	h->addr[offset]++;
+
+	pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
+		  "] => %" PRIu64 "\n", sym->start, sym->name,
+		  addr, addr - sym->start, h->addr[offset]);
+	return 0;
+}
+
+static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
+{
+	struct objdump_line *self = malloc(sizeof(*self) + privsize);
+
+	if (self != NULL) {
+		self->offset = offset;
+		self->line = line;
+	}
+
+	return self;
+}
+
+void objdump_line__free(struct objdump_line *self)
+{
+	free(self->line);
+	free(self);
+}
+
+static void objdump__add_line(struct list_head *head, struct objdump_line *line)
+{
+	list_add_tail(&line->node, head);
+}
+
+struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
+					       struct objdump_line *pos)
+{
+	list_for_each_entry_continue(pos, head, node)
+		if (pos->offset >= 0)
+			return pos;
+
+	return NULL;
+}
+
+static void objdump_line__print(struct objdump_line *oline,
+				struct list_head *head,
+				struct symbol *sym, u64 len)
+{
+	static const char *prev_line;
+	static const char *prev_color;
+
+	if (oline->offset != -1) {
+		const char *path = NULL;
+		unsigned int hits = 0;
+		double percent = 0.0;
+		const char *color;
+		struct annotation *notes = symbol__annotation(sym);
+		struct source_line *src_line = notes->src_line;
+		struct sym_hist *h = notes->histogram;
+		s64 offset = oline->offset;
+		struct objdump_line *next = objdump__get_next_ip_line(head, oline);
+
+		while (offset < (s64)len &&
+		       (next == NULL || offset < next->offset)) {
+			if (src_line) {
+				if (path == NULL)
+					path = src_line[offset].path;
+				percent += src_line[offset].percent;
+			} else
+				hits += h->addr[offset];
+
+			++offset;
+		}
+
+		if (src_line == NULL && h->sum)
+			percent = 100.0 * hits / h->sum;
+
+		color = get_percent_color(percent);
+
+		/*
+		 * Also color the filename and line if needed, with
+		 * the same color than the percentage. Don't print it
+		 * twice for close colored addr with the same filename:line
+		 */
+		if (path) {
+			if (!prev_line || strcmp(prev_line, path)
+				       || color != prev_color) {
+				color_fprintf(stdout, color, " %s", path);
+				prev_line = path;
+				prev_color = color;
+			}
+		}
+
+		color_fprintf(stdout, color, " %7.2f", percent);
+		printf(" :	");
+		color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line);
+	} else {
+		if (!*oline->line)
+			printf("         :\n");
+		else
+			printf("         :	%s\n", oline->line);
+	}
+}
+
+static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file,
+				      struct list_head *head, size_t privsize)
+{
+	struct objdump_line *objdump_line;
+	char *line = NULL, *tmp, *tmp2, *c;
+	size_t line_len;
+	s64 line_ip, offset = -1;
+
+	if (getline(&line, &line_len, file) < 0)
+		return -1;
+
+	if (!line)
+		return -1;
+
+	while (line_len != 0 && isspace(line[line_len - 1]))
+		line[--line_len] = '\0';
+
+	c = strchr(line, '\n');
+	if (c)
+		*c = 0;
+
+	line_ip = -1;
+
+	/*
+	 * Strip leading spaces:
+	 */
+	tmp = line;
+	while (*tmp) {
+		if (*tmp != ' ')
+			break;
+		tmp++;
+	}
+
+	if (*tmp) {
+		/*
+		 * Parse hexa addresses followed by ':'
+		 */
+		line_ip = strtoull(tmp, &tmp2, 16);
+		if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
+			line_ip = -1;
+	}
+
+	if (line_ip != -1) {
+		u64 start = map__rip_2objdump(map, sym->start),
+		    end = map__rip_2objdump(map, sym->end);
+
+		offset = line_ip - start;
+		if (offset < 0 || (u64)line_ip > end)
+			offset = -1;
+	}
+
+	objdump_line = objdump_line__new(offset, line, privsize);
+	if (objdump_line == NULL) {
+		free(line);
+		return -1;
+	}
+	objdump__add_line(head, objdump_line);
+
+	return 0;
+}
+
+int symbol__annotate(struct symbol *sym, struct map *map,
+		     struct list_head *head, size_t privsize)
+{
+	struct dso *dso = map->dso;
+	char *filename = dso__build_id_filename(dso, NULL, 0);
+	bool free_filename = true;
+	char command[PATH_MAX * 2];
+	FILE *file;
+	int err = 0;
+	u64 len;
+	char symfs_filename[PATH_MAX];
+
+	if (filename) {
+		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+			 symbol_conf.symfs, filename);
+	}
+
+	if (filename == NULL) {
+		if (dso->has_build_id) {
+			pr_err("Can't annotate %s: not enough memory\n",
+			       sym->name);
+			return -ENOMEM;
+		}
+		goto fallback;
+	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
+		   strstr(command, "[kernel.kallsyms]") ||
+		   access(symfs_filename, R_OK)) {
+		free(filename);
+fallback:
+		/*
+		 * If we don't have build-ids or the build-id file isn't in the
+		 * cache, or is just a kallsyms file, well, lets hope that this
+		 * DSO is the same as when 'perf record' ran.
+		 */
+		filename = dso->long_name;
+		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+			 symbol_conf.symfs, filename);
+		free_filename = false;
+	}
+
+	if (dso->origin == DSO__ORIG_KERNEL) {
+		if (dso->annotate_warned)
+			goto out_free_filename;
+		err = -ENOENT;
+		dso->annotate_warned = 1;
+		pr_err("Can't annotate %s: No vmlinux file was found in the "
+		       "path\n", sym->name);
+		goto out_free_filename;
+	}
+
+	pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
+		 filename, sym->name, map->unmap_ip(map, sym->start),
+		 map->unmap_ip(map, sym->end));
+
+	len = sym->end - sym->start;
+
+	pr_debug("annotating [%p] %30s : [%p] %30s\n",
+		 dso, dso->long_name, sym, sym->name);
+
+	snprintf(command, sizeof(command),
+		 "objdump --start-address=0x%016" PRIx64
+		 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
+		 map__rip_2objdump(map, sym->start),
+		 map__rip_2objdump(map, sym->end),
+		 symfs_filename, filename);
+
+	pr_debug("Executing: %s\n", command);
+
+	file = popen(command, "r");
+	if (!file)
+		goto out_free_filename;
+
+	while (!feof(file))
+		if (symbol__parse_objdump_line(sym, map, file, head, privsize) < 0)
+			break;
+
+	pclose(file);
+out_free_filename:
+	if (free_filename)
+		free(filename);
+	return err;
+}
+
+static void insert_source_line(struct rb_root *root, struct source_line *src_line)
+{
+	struct source_line *iter;
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+
+	while (*p != NULL) {
+		parent = *p;
+		iter = rb_entry(parent, struct source_line, node);
+
+		if (src_line->percent > iter->percent)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+
+	rb_link_node(&src_line->node, parent, p);
+	rb_insert_color(&src_line->node, root);
+}
+
+static void symbol__free_source_line(struct symbol *sym, int len)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct source_line *src_line = notes->src_line;
+	int i;
+
+	for (i = 0; i < len; i++)
+		free(src_line[i].path);
+
+	free(src_line);
+	notes->src_line = NULL;
+}
+
+/* Get the filename:line for the colored entries */
+static int symbol__get_source_line(struct symbol *sym, struct map *map,
+				   struct rb_root *root, int len,
+				   const char *filename)
+{
+	u64 start;
+	int i;
+	char cmd[PATH_MAX * 2];
+	struct source_line *src_line;
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = notes->histogram;
+
+	if (!h->sum)
+		return 0;
+
+	src_line = notes->src_line = calloc(len, sizeof(struct source_line));
+	if (!notes->src_line)
+		return -1;
+
+	start = map->unmap_ip(map, sym->start);
+
+	for (i = 0; i < len; i++) {
+		char *path = NULL;
+		size_t line_len;
+		u64 offset;
+		FILE *fp;
+
+		src_line[i].percent = 100.0 * h->addr[i] / h->sum;
+		if (src_line[i].percent <= 0.5)
+			continue;
+
+		offset = start + i;
+		sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
+		fp = popen(cmd, "r");
+		if (!fp)
+			continue;
+
+		if (getline(&path, &line_len, fp) < 0 || !line_len)
+			goto next;
+
+		src_line[i].path = malloc(sizeof(char) * line_len + 1);
+		if (!src_line[i].path)
+			goto next;
+
+		strcpy(src_line[i].path, path);
+		insert_source_line(root, &src_line[i]);
+
+	next:
+		pclose(fp);
+	}
+
+	return 0;
+}
+
+static void print_summary(struct rb_root *root, const char *filename)
+{
+	struct source_line *src_line;
+	struct rb_node *node;
+
+	printf("\nSorted summary for file %s\n", filename);
+	printf("----------------------------------------------\n\n");
+
+	if (RB_EMPTY_ROOT(root)) {
+		printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
+		return;
+	}
+
+	node = rb_first(root);
+	while (node) {
+		double percent;
+		const char *color;
+		char *path;
+
+		src_line = rb_entry(node, struct source_line, node);
+		percent = src_line->percent;
+		color = get_percent_color(percent);
+		path = src_line->path;
+
+		color_fprintf(stdout, color, " %7.2f %s", percent, path);
+		node = rb_next(node);
+	}
+}
+
+static void symbol__annotate_hits(struct symbol *sym)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = notes->histogram;
+	u64 len = sym->end - sym->start, offset;
+
+	for (offset = 0; offset < len; ++offset)
+		if (h->addr[offset] != 0)
+			printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
+			       sym->start + offset, h->addr[offset]);
+	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
+}
+
+int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
+			 bool full_paths)
+{
+	struct dso *dso = map->dso;
+	const char *filename = dso->long_name, *d_filename;
+	struct rb_root source_line = RB_ROOT;
+	struct objdump_line *pos, *n;
+	LIST_HEAD(head);
+	u64 len;
+
+	if (symbol__annotate(sym, map, &head, 0) < 0)
+		return -1;
+
+	if (full_paths)
+		d_filename = filename;
+	else
+		d_filename = basename(filename);
+
+	len = sym->end - sym->start;
+
+	if (print_lines) {
+		symbol__get_source_line(sym, map, &source_line, len, filename);
+		print_summary(&source_line, filename);
+	}
+
+	printf("\n\n------------------------------------------------\n");
+	printf(" Percent |	Source code & Disassembly of %s\n", d_filename);
+	printf("------------------------------------------------\n");
+
+	if (verbose)
+		symbol__annotate_hits(sym);
+
+	list_for_each_entry_safe(pos, n, &head, node) {
+		objdump_line__print(pos, &head, sym, len);
+		list_del(&pos->node);
+		objdump_line__free(pos);
+	}
+
+	if (print_lines)
+		symbol__free_source_line(sym, len);
+
+	return 0;
+}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
new file mode 100644
index 0000000..6e2fbc2
--- /dev/null
+++ b/tools/perf/util/annotate.h
@@ -0,0 +1,65 @@
+#ifndef __PERF_ANNOTATE_H
+#define __PERF_ANNOTATE_H
+
+#include <stdbool.h>
+#include "types.h"
+#include "symbol.h"
+#include <linux/list.h>
+#include <linux/rbtree.h>
+
+struct objdump_line {
+	struct list_head node;
+	s64		 offset;
+	char		 *line;
+};
+
+void objdump_line__free(struct objdump_line *self);
+struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
+					       struct objdump_line *pos);
+
+struct sym_hist {
+	u64		sum;
+	u64		addr[0];
+};
+
+struct source_line {
+	struct rb_node	node;
+	double		percent;
+	char		*path;
+};
+
+struct annotation {
+	struct sym_hist	   *histogram;
+	struct source_line *src_line;
+};
+
+struct sannotation {
+	struct annotation annotation;
+	struct symbol	  symbol;
+};
+
+static inline struct annotation *symbol__annotation(struct symbol *sym)
+{
+	struct sannotation *a = container_of(sym, struct sannotation, symbol);
+	return &a->annotation;
+}
+
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map, u64 addr);
+
+int symbol__annotate(struct symbol *sym, struct map *map,
+		     struct list_head *head, size_t privsize);
+
+int symbol__tty_annotate(struct symbol *sym, struct map *map,
+			 bool print_lines, bool full_paths);
+
+#ifdef NO_NEWT_SUPPORT
+static inline int symbol__tui_annotate(symbol *sym __used,
+				       struct map *map __used)
+{
+	return 0;
+}
+#else
+int symbol__tui_annotate(struct symbol *sym, struct map *map);
+#endif
+
+#endif	/* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9588780..6d9c92c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
+#include "annotate.h"
 #include "util.h"
 #include "build-id.h"
 #include "hist.h"
@@ -949,225 +950,15 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
 	}
 }
 
-static int symbol__alloc_hist(struct symbol *self)
+int hist_entry__inc_addr_samples(struct hist_entry *he, u64 ip)
 {
-	struct sym_priv *priv = symbol__priv(self);
-	const int size = (sizeof(*priv->hist) +
-			  (self->end - self->start) * sizeof(u64));
-
-	priv->hist = zalloc(size);
-	return priv->hist == NULL ? -1 : 0;
-}
-
-int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
-{
-	unsigned int sym_size, offset;
-	struct symbol *sym = self->ms.sym;
-	struct sym_priv *priv;
-	struct sym_hist *h;
-
-	if (!sym || !self->ms.map)
-		return 0;
-
-	priv = symbol__priv(sym);
-	if (priv->hist == NULL && symbol__alloc_hist(sym) < 0)
-		return -ENOMEM;
-
-	sym_size = sym->end - sym->start;
-	offset = ip - sym->start;
-
-	pr_debug3("%s: ip=%#" PRIx64 "\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip));
-
-	if (offset >= sym_size)
-		return 0;
-
-	h = priv->hist;
-	h->sum++;
-	h->ip[offset]++;
-
-	pr_debug3("%#" PRIx64 " %s: period++ [ip: %#" PRIx64 ", %#" PRIx64
-		  "] => %" PRIu64 "\n", self->ms.sym->start, self->ms.sym->name,
-		  ip, ip - self->ms.sym->start, h->ip[offset]);
-	return 0;
-}
-
-static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
-{
-	struct objdump_line *self = malloc(sizeof(*self) + privsize);
-
-	if (self != NULL) {
-		self->offset = offset;
-		self->line = line;
-	}
-
-	return self;
-}
-
-void objdump_line__free(struct objdump_line *self)
-{
-	free(self->line);
-	free(self);
-}
-
-static void objdump__add_line(struct list_head *head, struct objdump_line *line)
-{
-	list_add_tail(&line->node, head);
-}
-
-struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
-					       struct objdump_line *pos)
-{
-	list_for_each_entry_continue(pos, head, node)
-		if (pos->offset >= 0)
-			return pos;
-
-	return NULL;
+	return symbol__inc_addr_samples(he->ms.sym, he->ms.map, ip);
 }
 
-static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
-					  struct list_head *head, size_t privsize)
-{
-	struct symbol *sym = self->ms.sym;
-	struct objdump_line *objdump_line;
-	char *line = NULL, *tmp, *tmp2, *c;
-	size_t line_len;
-	s64 line_ip, offset = -1;
-
-	if (getline(&line, &line_len, file) < 0)
-		return -1;
-
-	if (!line)
-		return -1;
-
-	while (line_len != 0 && isspace(line[line_len - 1]))
-		line[--line_len] = '\0';
-
-	c = strchr(line, '\n');
-	if (c)
-		*c = 0;
-
-	line_ip = -1;
-
-	/*
-	 * Strip leading spaces:
-	 */
-	tmp = line;
-	while (*tmp) {
-		if (*tmp != ' ')
-			break;
-		tmp++;
-	}
-
-	if (*tmp) {
-		/*
-		 * Parse hexa addresses followed by ':'
-		 */
-		line_ip = strtoull(tmp, &tmp2, 16);
-		if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
-			line_ip = -1;
-	}
-
-	if (line_ip != -1) {
-		u64 start = map__rip_2objdump(self->ms.map, sym->start),
-		    end = map__rip_2objdump(self->ms.map, sym->end);
-
-		offset = line_ip - start;
-		if (offset < 0 || (u64)line_ip > end)
-			offset = -1;
-	}
-
-	objdump_line = objdump_line__new(offset, line, privsize);
-	if (objdump_line == NULL) {
-		free(line);
-		return -1;
-	}
-	objdump__add_line(head, objdump_line);
-
-	return 0;
-}
-
-int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
+int hist_entry__annotate(struct hist_entry *he, struct list_head *head,
 			 size_t privsize)
 {
-	struct symbol *sym = self->ms.sym;
-	struct map *map = self->ms.map;
-	struct dso *dso = map->dso;
-	char *filename = dso__build_id_filename(dso, NULL, 0);
-	bool free_filename = true;
-	char command[PATH_MAX * 2];
-	FILE *file;
-	int err = 0;
-	u64 len;
-	char symfs_filename[PATH_MAX];
-
-	if (filename) {
-		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
-			 symbol_conf.symfs, filename);
-	}
-
-	if (filename == NULL) {
-		if (dso->has_build_id) {
-			pr_err("Can't annotate %s: not enough memory\n",
-			       sym->name);
-			return -ENOMEM;
-		}
-		goto fallback;
-	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
-		   strstr(command, "[kernel.kallsyms]") ||
-		   access(symfs_filename, R_OK)) {
-		free(filename);
-fallback:
-		/*
-		 * If we don't have build-ids or the build-id file isn't in the
-		 * cache, or is just a kallsyms file, well, lets hope that this
-		 * DSO is the same as when 'perf record' ran.
-		 */
-		filename = dso->long_name;
-		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
-			 symbol_conf.symfs, filename);
-		free_filename = false;
-	}
-
-	if (dso->origin == DSO__ORIG_KERNEL) {
-		if (dso->annotate_warned)
-			goto out_free_filename;
-		err = -ENOENT;
-		dso->annotate_warned = 1;
-		pr_err("Can't annotate %s: No vmlinux file was found in the "
-		       "path\n", sym->name);
-		goto out_free_filename;
-	}
-
-	pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
-		 filename, sym->name, map->unmap_ip(map, sym->start),
-		 map->unmap_ip(map, sym->end));
-
-	len = sym->end - sym->start;
-
-	pr_debug("annotating [%p] %30s : [%p] %30s\n",
-		 dso, dso->long_name, sym, sym->name);
-
-	snprintf(command, sizeof(command),
-		 "objdump --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
-		 map__rip_2objdump(map, sym->start),
-		 map__rip_2objdump(map, sym->end),
-		 symfs_filename, filename);
-
-	pr_debug("Executing: %s\n", command);
-
-	file = popen(command, "r");
-	if (!file)
-		goto out_free_filename;
-
-	while (!feof(file))
-		if (hist_entry__parse_objdump_line(self, file, head, privsize) < 0)
-			break;
-
-	pclose(file);
-out_free_filename:
-	if (free_filename)
-		free(filename);
-	return err;
+	return symbol__annotate(he->ms.sym, he->ms.map, head, privsize);
 }
 
 void hists__inc_nr_events(struct hists *self, u32 type)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 889559b..8a201f7 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -9,33 +9,6 @@ extern struct callchain_param callchain_param;
 struct hist_entry;
 struct addr_location;
 struct symbol;
-struct rb_root;
-
-struct objdump_line {
-	struct list_head node;
-	s64		 offset;
-	char		 *line;
-};
-
-void objdump_line__free(struct objdump_line *self);
-struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
-					       struct objdump_line *pos);
-
-struct sym_hist {
-	u64		sum;
-	u64		ip[0];
-};
-
-struct sym_ext {
-	struct rb_node	node;
-	double		percent;
-	char		*path;
-};
-
-struct sym_priv {
-	struct sym_hist	*hist;
-	struct sym_ext	*ext;
-};
 
 /*
  * The kernel collects the number of events it couldn't send in a stretch and
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 82b78f9..daa7138 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -1,9 +1,11 @@
 #include "../browser.h"
 #include "../helpline.h"
 #include "../libslang.h"
+#include "../../annotate.h"
 #include "../../hist.h"
 #include "../../sort.h"
 #include "../../symbol.h"
+#include "../../annotate.h"
 
 static void ui__error_window(const char *fmt, ...)
 {
@@ -66,24 +68,26 @@ static double objdump_line__calc_percent(struct objdump_line *self,
 	if (self->offset != -1) {
 		int len = sym->end - sym->start;
 		unsigned int hits = 0;
-		struct sym_priv *priv = symbol__priv(sym);
-		struct sym_ext *sym_ext = priv->ext;
-		struct sym_hist *h = priv->hist;
+		struct annotation *notes = symbol__annotation(sym);
+		struct source_line *src_line = notes->src_line;
+		struct sym_hist *h = notes->histogram;
 		s64 offset = self->offset;
 		struct objdump_line *next = objdump__get_next_ip_line(head, self);
 
-
 		while (offset < (s64)len &&
 		       (next == NULL || offset < next->offset)) {
-			if (sym_ext) {
-				percent += sym_ext[offset].percent;
+			if (src_line) {
+				percent += src_line[offset].percent;
 			} else
-				hits += h->ip[offset];
+				hits += h->addr[offset];
 
 			++offset;
 		}
-
-		if (sym_ext == NULL && h->sum)
+		/*
+ 		 * If the percentage wasn't already calculated in
+ 		 * symbol__get_source_line, do it now:
+ 		 */
+		if (src_line == NULL && h->sum)
 			percent = 100.0 * hits / h->sum;
 	}
 
@@ -136,10 +140,10 @@ static void annotate_browser__set_top(struct annotate_browser *self,
 static int annotate_browser__run(struct annotate_browser *self)
 {
 	struct rb_node *nd;
-	struct hist_entry *he = self->b.priv;
+	struct symbol *sym = self->b.priv;
 	int key;
 
-	if (ui_browser__show(&self->b, he->ms.sym->name,
+	if (ui_browser__show(&self->b, sym->name,
 			     "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
 		return -1;
 	/*
@@ -179,7 +183,12 @@ out:
 	return key;
 }
 
-int hist_entry__tui_annotate(struct hist_entry *self)
+int hist_entry__tui_annotate(struct hist_entry *he)
+{
+	return symbol__tui_annotate(he->ms.sym, he->ms.map);
+}
+
+int symbol__tui_annotate(struct symbol *sym, struct map *map)
 {
 	struct objdump_line *pos, *n;
 	struct objdump_line_rb_node *rbpos;
@@ -190,18 +199,18 @@ int hist_entry__tui_annotate(struct hist_entry *self)
 			.refresh = ui_browser__list_head_refresh,
 			.seek	 = ui_browser__list_head_seek,
 			.write	 = annotate_browser__write,
-			.priv	 = self,
+			.priv	 = sym,
 		},
 	};
 	int ret;
 
-	if (self->ms.sym == NULL)
+	if (sym == NULL)
 		return -1;
 
-	if (self->ms.map->dso->annotate_warned)
+	if (map->dso->annotate_warned)
 		return -1;
 
-	if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) {
+	if (symbol__annotate(sym, map, &head, sizeof(*rbpos)) < 0) {
 		ui__error_window(ui_helpline__last_msg);
 		return -1;
 	}
@@ -214,7 +223,7 @@ int hist_entry__tui_annotate(struct hist_entry *self)
 			browser.b.width = line_len;
 		rbpos = objdump_line__rb(pos);
 		rbpos->idx = browser.b.nr_entries++;
-		rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym);
+		rbpos->percent = objdump_line__calc_percent(pos, &head, sym);
 		if (rbpos->percent < 0.01)
 			continue;
 		objdump__insert_line(&browser.entries, rbpos);
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 3/6] perf annotate: Support multiple histograms in annotation
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 1/6] perf top: Remove superfluous name_len field Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 2/6] perf annotate: Move annotate functions to util/ Arnaldo Carvalho de Melo
@ 2011-02-07  0:42 ` Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 4/6] perf annotate: Config options for symbol__tty_annotate Arnaldo Carvalho de Melo
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Ingo Molnar, Mike Galbraith, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian, Tom Zanussi

From: Arnaldo Carvalho de Melo <acme@redhat.com>

The perf annotate tool continues aggregating everything on just one
histograms, but to support the top model add support for one histogram
perf evsel in the evlist.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c          |   29 ++++++++++++----
 tools/perf/builtin-report.c            |   15 +++++++--
 tools/perf/util/annotate.c             |   57 +++++++++++++++-----------------
 tools/perf/util/annotate.h             |   29 +++++++++++++---
 tools/perf/util/hist.c                 |    4 +-
 tools/perf/util/hist.h                 |   16 +++++----
 tools/perf/util/ui/browsers/annotate.c |   12 +++---
 tools/perf/util/ui/browsers/hists.c    |    9 +++--
 8 files changed, 106 insertions(+), 65 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 9072ef4..f3e4423 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -57,7 +57,18 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
 	if (he == NULL)
 		return -ENOMEM;
 
-	return hist_entry__inc_addr_samples(he, al->addr);
+	if (he->ms.sym != NULL) {
+		/*
+		 * All aggregated on the first sym_hist.
+		 */
+		struct annotation *notes = symbol__annotation(he->ms.sym);
+		if (notes->histograms == NULL && symbol__alloc_hist(he->ms.sym, 1) < 0)
+			return -ENOMEM;
+
+		return hist_entry__inc_addr_samples(he, 0, al->addr);
+	}
+
+	return 0;
 }
 
 static int process_sample_event(union perf_event *event,
@@ -81,9 +92,9 @@ static int process_sample_event(union perf_event *event,
 	return 0;
 }
 
-static int hist_entry__tty_annotate(struct hist_entry *he)
+static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
 {
-	return symbol__tty_annotate(he->ms.sym, he->ms.map,
+	return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
 				    print_line, full_paths);
 }
 
@@ -100,7 +111,7 @@ static void hists__find_annotations(struct hists *self)
 			goto find_next;
 
 		notes = symbol__annotation(he->ms.sym);
-		if (notes->histogram == NULL) {
+		if (notes->histograms == NULL) {
 find_next:
 			if (key == KEY_LEFT)
 				nd = rb_prev(nd);
@@ -110,7 +121,8 @@ find_next:
 		}
 
 		if (use_browser > 0) {
-			key = hist_entry__tui_annotate(he);
+			/* For now all is aggregated on the first */
+			key = hist_entry__tui_annotate(he, 0);
 			switch (key) {
 			case KEY_RIGHT:
 				next = rb_next(nd);
@@ -125,15 +137,16 @@ find_next:
 			if (next != NULL)
 				nd = next;
 		} else {
-			hist_entry__tty_annotate(he);
+			/* For now all is aggregated on the first */
+			hist_entry__tty_annotate(he, 0);
 			nd = rb_next(nd);
 			/*
 			 * Since we have a hist_entry per IP for the same
 			 * symbol, free he->ms.sym->histogram to signal we already
 			 * processed this symbol.
 			 */
-			free(notes->histogram);
-			notes->histogram = NULL;
+			free(notes->histograms);
+			notes->histograms = NULL;
 		}
 	}
 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 91e4cdb..de06bf5 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -118,8 +118,17 @@ static int perf_session__add_hist_entry(struct perf_session *session,
 	 * so we don't allocated the extra space needed because the stdio
 	 * code will not use it.
 	 */
-	if (use_browser > 0)
-		err = hist_entry__inc_addr_samples(he, al->addr);
+	if (al->sym != NULL && use_browser > 0) {
+		/*
+		 * All aggregated on the first sym_hist.
+		 */
+		struct annotation *notes = symbol__annotation(he->ms.sym);
+		if (notes->histograms == NULL &&
+		    symbol__alloc_hist(he->ms.sym, 1) < 0)
+			err = -ENOMEM;
+		else
+			err = hist_entry__inc_addr_samples(he, 0, al->addr);
+	}
 
 	return err;
 }
@@ -349,7 +358,7 @@ static int __cmd_report(void)
 	}
 
 	if (use_browser > 0)
-		hists__tui_browse_tree(&session->hists_tree, help);
+		hists__tui_browse_tree(&session->hists_tree, help, 0);
 	else
 		hists__tty_browse_tree(&session->hists_tree, help);
 
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 9b25575..7488fe9 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -15,44 +15,40 @@
 #include "debug.h"
 #include "annotate.h"
 
-static int symbol__alloc_hist(struct symbol *sym)
+int symbol__alloc_hist(struct symbol *sym, int nevents)
 {
 	struct annotation *notes = symbol__annotation(sym);
-	const int size = (sizeof(*notes->histogram) +
-			  (sym->end - sym->start) * sizeof(u64));
 
-	notes->histogram = zalloc(size);
-	return notes->histogram == NULL ? -1 : 0;
+	notes->sizeof_sym_hist = (sizeof(*notes->histograms) +
+				  (sym->end - sym->start) * sizeof(u64));
+	notes->histograms = calloc(nevents, notes->sizeof_sym_hist);
+	return notes->histograms == NULL ? -1 : 0;
 }
 
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map, u64 addr)
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+			     int evidx, u64 addr)
 {
-	unsigned int sym_size, offset;
+	unsigned offset;
 	struct annotation *notes;
 	struct sym_hist *h;
 
-	if (!sym || !map)
-		return 0;
-
 	notes = symbol__annotation(sym);
-	if (notes->histogram == NULL && symbol__alloc_hist(sym) < 0)
+	if (notes->histograms == NULL)
 		return -ENOMEM;
 
-	sym_size = sym->end - sym->start;
-	offset = addr - sym->start;
-
 	pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
 
-	if (offset >= sym_size)
+	if (addr >= sym->end)
 		return 0;
 
-	h = notes->histogram;
+	offset = addr - sym->start;
+	h = annotation__histogram(notes, evidx);
 	h->sum++;
 	h->addr[offset]++;
 
 	pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
-		  "] => %" PRIu64 "\n", sym->start, sym->name,
-		  addr, addr - sym->start, h->addr[offset]);
+		  ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
+		  addr, addr - sym->start, evidx, h->addr[offset]);
 	return 0;
 }
 
@@ -90,8 +86,8 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
 }
 
 static void objdump_line__print(struct objdump_line *oline,
-				struct list_head *head,
-				struct symbol *sym, u64 len)
+				struct list_head *head, struct symbol *sym,
+				int evidx, u64 len)
 {
 	static const char *prev_line;
 	static const char *prev_color;
@@ -103,7 +99,7 @@ static void objdump_line__print(struct objdump_line *oline,
 		const char *color;
 		struct annotation *notes = symbol__annotation(sym);
 		struct source_line *src_line = notes->src_line;
-		struct sym_hist *h = notes->histogram;
+		struct sym_hist *h = annotation__histogram(notes, evidx);
 		s64 offset = oline->offset;
 		struct objdump_line *next = objdump__get_next_ip_line(head, oline);
 
@@ -328,7 +324,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
 
 /* Get the filename:line for the colored entries */
 static int symbol__get_source_line(struct symbol *sym, struct map *map,
-				   struct rb_root *root, int len,
+				   int evidx, struct rb_root *root, int len,
 				   const char *filename)
 {
 	u64 start;
@@ -336,7 +332,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
 	char cmd[PATH_MAX * 2];
 	struct source_line *src_line;
 	struct annotation *notes = symbol__annotation(sym);
-	struct sym_hist *h = notes->histogram;
+	struct sym_hist *h = annotation__histogram(notes, evidx);
 
 	if (!h->sum)
 		return 0;
@@ -409,10 +405,10 @@ static void print_summary(struct rb_root *root, const char *filename)
 	}
 }
 
-static void symbol__annotate_hits(struct symbol *sym)
+static void symbol__annotate_hits(struct symbol *sym, int evidx)
 {
 	struct annotation *notes = symbol__annotation(sym);
-	struct sym_hist *h = notes->histogram;
+	struct sym_hist *h = annotation__histogram(notes, evidx);
 	u64 len = sym->end - sym->start, offset;
 
 	for (offset = 0; offset < len; ++offset)
@@ -422,8 +418,8 @@ static void symbol__annotate_hits(struct symbol *sym)
 	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
 }
 
-int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
-			 bool full_paths)
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
+			 bool print_lines, bool full_paths)
 {
 	struct dso *dso = map->dso;
 	const char *filename = dso->long_name, *d_filename;
@@ -443,7 +439,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
 	len = sym->end - sym->start;
 
 	if (print_lines) {
-		symbol__get_source_line(sym, map, &source_line, len, filename);
+		symbol__get_source_line(sym, map, evidx, &source_line,
+					len, filename);
 		print_summary(&source_line, filename);
 	}
 
@@ -452,10 +449,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
 	printf("------------------------------------------------\n");
 
 	if (verbose)
-		symbol__annotate_hits(sym);
+		symbol__annotate_hits(sym, evidx);
 
 	list_for_each_entry_safe(pos, n, &head, node) {
-		objdump_line__print(pos, &head, sym, len);
+		objdump_line__print(pos, &head, sym, evidx, len);
 		list_del(&pos->node);
 		objdump_line__free(pos);
 	}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 6e2fbc2..0a5069c 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -28,9 +28,21 @@ struct source_line {
 	char		*path;
 };
 
+/** struct annotation - symbols with hits have this attached as in sannotation
+ *
+ * @histogram: Array of addr hit histograms per event being monitored
+ * @src_line: If 'print_lines' is specified, per source code line percentages
+ *
+ * src_line is allocated, percentages calculated and all sorted by percentage
+ * when the annotation is about to be presented, so the percentages are for
+ * one of the entries in the histogram array, i.e. for the event/counter being
+ * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
+ * returns.
+ */
 struct annotation {
-	struct sym_hist	   *histogram;
 	struct source_line *src_line;
+	struct sym_hist	   *histograms;
+	int    		   sizeof_sym_hist;
 };
 
 struct sannotation {
@@ -38,28 +50,35 @@ struct sannotation {
 	struct symbol	  symbol;
 };
 
+static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
+{
+	return ((void *)notes->histograms) + (notes->sizeof_sym_hist * idx);
+}
+
 static inline struct annotation *symbol__annotation(struct symbol *sym)
 {
 	struct sannotation *a = container_of(sym, struct sannotation, symbol);
 	return &a->annotation;
 }
 
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map, u64 addr);
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+			     int evidx, u64 addr);
+int symbol__alloc_hist(struct symbol *sym, int nevents);
 
 int symbol__annotate(struct symbol *sym, struct map *map,
 		     struct list_head *head, size_t privsize);
 
-int symbol__tty_annotate(struct symbol *sym, struct map *map,
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
 			 bool print_lines, bool full_paths);
 
 #ifdef NO_NEWT_SUPPORT
 static inline int symbol__tui_annotate(symbol *sym __used,
-				       struct map *map __used)
+				       struct map *map __used, int evidx __used)
 {
 	return 0;
 }
 #else
-int symbol__tui_annotate(struct symbol *sym, struct map *map);
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx);
 #endif
 
 #endif	/* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6d9c92c..bac5ab6 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -950,9 +950,9 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
 	}
 }
 
-int hist_entry__inc_addr_samples(struct hist_entry *he, u64 ip)
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
 {
-	return symbol__inc_addr_samples(he->ms.sym, he->ms.map, ip);
+	return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
 }
 
 int hist_entry__annotate(struct hist_entry *he, struct list_head *head,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8a201f7..2c6cdae 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -77,7 +77,7 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
 size_t hists__fprintf(struct hists *self, struct hists *pair,
 		      bool show_displacement, FILE *fp);
 
-int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip);
+int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
 int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
 			 size_t privsize);
 
@@ -91,18 +91,20 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
 #ifdef NO_NEWT_SUPPORT
 static inline int hists__browse(struct hists *self __used,
 				const char *helpline __used,
-				const char *ev_name __used)
+				const char *ev_name __used, int evidx __used)
 {
 	return 0;
 }
 
 static inline int hists__tui_browse_tree(struct rb_root *self __used,
-					 const char *help __used)
+					 const char *help __used,
+					 int evidx __used)
 {
 	return 0;
 }
 
-static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
+static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
+					   int evidx __used)
 {
 	return 0;
 }
@@ -111,13 +113,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
 #else
 #include <newt.h>
 int hists__browse(struct hists *self, const char *helpline,
-		  const char *ev_name);
-int hist_entry__tui_annotate(struct hist_entry *self);
+		  const char *ev_name, int evidx);
+int hist_entry__tui_annotate(struct hist_entry *self, int evidx);
 
 #define KEY_LEFT NEWT_KEY_LEFT
 #define KEY_RIGHT NEWT_KEY_RIGHT
 
-int hists__tui_browse_tree(struct rb_root *self, const char *help);
+int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx);
 #endif
 
 unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index daa7138..8d8a168 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -61,7 +61,7 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
 
 static double objdump_line__calc_percent(struct objdump_line *self,
 					 struct list_head *head,
-					 struct symbol *sym)
+					 struct symbol *sym, int evidx)
 {
 	double percent = 0.0;
 
@@ -70,7 +70,7 @@ static double objdump_line__calc_percent(struct objdump_line *self,
 		unsigned int hits = 0;
 		struct annotation *notes = symbol__annotation(sym);
 		struct source_line *src_line = notes->src_line;
-		struct sym_hist *h = notes->histogram;
+		struct sym_hist *h = annotation__histogram(notes, evidx);
 		s64 offset = self->offset;
 		struct objdump_line *next = objdump__get_next_ip_line(head, self);
 
@@ -183,12 +183,12 @@ out:
 	return key;
 }
 
-int hist_entry__tui_annotate(struct hist_entry *he)
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx)
 {
-	return symbol__tui_annotate(he->ms.sym, he->ms.map);
+	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx);
 }
 
-int symbol__tui_annotate(struct symbol *sym, struct map *map)
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
 {
 	struct objdump_line *pos, *n;
 	struct objdump_line_rb_node *rbpos;
@@ -223,7 +223,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map)
 			browser.b.width = line_len;
 		rbpos = objdump_line__rb(pos);
 		rbpos->idx = browser.b.nr_entries++;
-		rbpos->percent = objdump_line__calc_percent(pos, &head, sym);
+		rbpos->percent = objdump_line__calc_percent(pos, &head, sym, evidx);
 		if (rbpos->percent < 0.01)
 			continue;
 		objdump__insert_line(&browser.entries, rbpos);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 8642823..294b495 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -797,7 +797,8 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
 	return printed;
 }
 
-int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
+int hists__browse(struct hists *self, const char *helpline,
+		  const char *ev_name, int evidx)
 {
 	struct hist_browser *browser = hist_browser__new(self);
 	struct pstack *fstack;
@@ -935,7 +936,7 @@ do_annotate:
 			if (he == NULL)
 				continue;
 
-			hist_entry__tui_annotate(he);
+			hist_entry__tui_annotate(he, evidx);
 		} else if (choice == browse_map)
 			map__browse(browser->selection->map);
 		else if (choice == zoom_dso) {
@@ -984,7 +985,7 @@ out:
 	return key;
 }
 
-int hists__tui_browse_tree(struct rb_root *self, const char *help)
+int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx)
 {
 	struct rb_node *first = rb_first(self), *nd = first, *next;
 	int key = 0;
@@ -993,7 +994,7 @@ int hists__tui_browse_tree(struct rb_root *self, const char *help)
 		struct hists *hists = rb_entry(nd, struct hists, rb_node);
 		const char *ev_name = __event_name(hists->type, hists->config);
 
-		key = hists__browse(hists, help, ev_name);
+		key = hists__browse(hists, help, ev_name, evidx);
 		switch (key) {
 		case NEWT_KEY_TAB:
 			next = rb_next(nd);
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/6] perf annotate: Config options for symbol__tty_annotate
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
                   ` (2 preceding siblings ...)
  2011-02-07  0:42 ` [PATCH 3/6] perf annotate: Support multiple histograms in annotation Arnaldo Carvalho de Melo
@ 2011-02-07  0:42 ` Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 5/6] perf annotate: Separate objdump parsing from actual screen rendering Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Ingo Molnar, Mike Galbraith, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian, Tom Zanussi

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Max line# that should be printed, minimum percentage filter, just like
'perf top', alas, due to it :-)

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c |    2 +-
 tools/perf/util/annotate.c    |   14 ++++++++++----
 tools/perf/util/annotate.h    |    3 ++-
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f3e4423..ea6a116 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -95,7 +95,7 @@ static int process_sample_event(union perf_event *event,
 static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
 {
 	return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
-				    print_line, full_paths);
+				    print_line, full_paths, 0, 0);
 }
 
 static void hists__find_annotations(struct hists *self)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7488fe9..072bc8d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -87,7 +87,7 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
 
 static void objdump_line__print(struct objdump_line *oline,
 				struct list_head *head, struct symbol *sym,
-				int evidx, u64 len)
+				int evidx, u64 len, int min_pcnt)
 {
 	static const char *prev_line;
 	static const char *prev_color;
@@ -118,6 +118,9 @@ static void objdump_line__print(struct objdump_line *oline,
 		if (src_line == NULL && h->sum)
 			percent = 100.0 * hits / h->sum;
 
+		if (percent < min_pcnt)
+			return;
+
 		color = get_percent_color(percent);
 
 		/*
@@ -419,13 +422,15 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
 }
 
 int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
-			 bool print_lines, bool full_paths)
+			 bool print_lines, bool full_paths, int min_pcnt,
+			 int max_lines)
 {
 	struct dso *dso = map->dso;
 	const char *filename = dso->long_name, *d_filename;
 	struct rb_root source_line = RB_ROOT;
 	struct objdump_line *pos, *n;
 	LIST_HEAD(head);
+	int printed = 2;
 	u64 len;
 
 	if (symbol__annotate(sym, map, &head, 0) < 0)
@@ -444,7 +449,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
 		print_summary(&source_line, filename);
 	}
 
-	printf("\n\n------------------------------------------------\n");
 	printf(" Percent |	Source code & Disassembly of %s\n", d_filename);
 	printf("------------------------------------------------\n");
 
@@ -452,9 +456,11 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
 		symbol__annotate_hits(sym, evidx);
 
 	list_for_each_entry_safe(pos, n, &head, node) {
-		objdump_line__print(pos, &head, sym, evidx, len);
+		objdump_line__print(pos, &head, sym, evidx, len, min_pcnt);
 		list_del(&pos->node);
 		objdump_line__free(pos);
+		if (max_lines && ++printed >= max_lines)
+			break;
 	}
 
 	if (print_lines)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 0a5069c..6b70732 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -69,7 +69,8 @@ int symbol__annotate(struct symbol *sym, struct map *map,
 		     struct list_head *head, size_t privsize);
 
 int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
-			 bool print_lines, bool full_paths);
+			 bool print_lines, bool full_paths, int min_pcnt,
+			 int max_lines);
 
 #ifdef NO_NEWT_SUPPORT
 static inline int symbol__tui_annotate(symbol *sym __used,
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 5/6] perf annotate: Separate objdump parsing from actual screen rendering
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
                   ` (3 preceding siblings ...)
  2011-02-07  0:42 ` [PATCH 4/6] perf annotate: Config options for symbol__tty_annotate Arnaldo Carvalho de Melo
@ 2011-02-07  0:42 ` Arnaldo Carvalho de Melo
  2011-02-07  0:42 ` [PATCH 6/6] perf top: Ditch private annotation code, share perf annotate's Arnaldo Carvalho de Melo
  2011-02-07  7:58 ` [GIT PULL 0/6] perf/core improments Ingo Molnar
  6 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Ingo Molnar, Mike Galbraith, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian, Tom Zanussi

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Because in 'perf top' we'll need to parse just once and then, as samples
come, render multiple times with evolving counter values.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/annotate.c |   62 ++++++++++++++++++++++++++++++-------------
 tools/perf/util/annotate.h |    4 +++
 2 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 072bc8d..10cdbad 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -421,21 +421,16 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
 	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
 }
 
-int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
-			 bool print_lines, bool full_paths, int min_pcnt,
-			 int max_lines)
+void symbol__annotate_printf(struct symbol *sym, struct map *map,
+			     struct list_head *head, int evidx, bool full_paths,
+			     int min_pcnt, int max_lines)
 {
 	struct dso *dso = map->dso;
 	const char *filename = dso->long_name, *d_filename;
-	struct rb_root source_line = RB_ROOT;
-	struct objdump_line *pos, *n;
-	LIST_HEAD(head);
+	struct objdump_line *pos;
 	int printed = 2;
 	u64 len;
 
-	if (symbol__annotate(sym, map, &head, 0) < 0)
-		return -1;
-
 	if (full_paths)
 		d_filename = filename;
 	else
@@ -443,28 +438,57 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
 
 	len = sym->end - sym->start;
 
-	if (print_lines) {
-		symbol__get_source_line(sym, map, evidx, &source_line,
-					len, filename);
-		print_summary(&source_line, filename);
-	}
-
 	printf(" Percent |	Source code & Disassembly of %s\n", d_filename);
 	printf("------------------------------------------------\n");
 
 	if (verbose)
 		symbol__annotate_hits(sym, evidx);
 
-	list_for_each_entry_safe(pos, n, &head, node) {
-		objdump_line__print(pos, &head, sym, evidx, len, min_pcnt);
-		list_del(&pos->node);
-		objdump_line__free(pos);
+	list_for_each_entry(pos, head, node) {
+		objdump_line__print(pos, head, sym, evidx, len, min_pcnt);
 		if (max_lines && ++printed >= max_lines)
 			break;
+
+	}
+}
+
+void objdump_line_list__purge(struct list_head *head)
+{
+	struct objdump_line *pos, *n;
+
+	list_for_each_entry_safe(pos, n, head, node) {
+		list_del(&pos->node);
+		objdump_line__free(pos);
+	}
+}
+
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
+			 bool print_lines, bool full_paths, int min_pcnt,
+			 int max_lines)
+{
+	struct dso *dso = map->dso;
+	const char *filename = dso->long_name;
+	struct rb_root source_line = RB_ROOT;
+	LIST_HEAD(head);
+	u64 len;
+
+	if (symbol__annotate(sym, map, &head, 0) < 0)
+		return -1;
+
+	len = sym->end - sym->start;
+
+	if (print_lines) {
+		symbol__get_source_line(sym, map, evidx, &source_line,
+					len, filename);
+		print_summary(&source_line, filename);
 	}
 
+	symbol__annotate_printf(sym, map, &head, evidx, full_paths,
+				min_pcnt, max_lines);
 	if (print_lines)
 		symbol__free_source_line(sym, len);
 
+	objdump_line_list__purge(&head);
+
 	return 0;
 }
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 6b70732..53dd92d 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -67,6 +67,10 @@ int symbol__alloc_hist(struct symbol *sym, int nevents);
 
 int symbol__annotate(struct symbol *sym, struct map *map,
 		     struct list_head *head, size_t privsize);
+void symbol__annotate_printf(struct symbol *sym, struct map *map,
+			     struct list_head *head, int evidx, bool full_paths,
+			     int min_pcnt, int max_lines);
+void objdump_line_list__purge(struct list_head *head);
 
 int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
 			 bool print_lines, bool full_paths, int min_pcnt,
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 6/6] perf top: Ditch private annotation code, share perf annotate's
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
                   ` (4 preceding siblings ...)
  2011-02-07  0:42 ` [PATCH 5/6] perf annotate: Separate objdump parsing from actual screen rendering Arnaldo Carvalho de Melo
@ 2011-02-07  0:42 ` Arnaldo Carvalho de Melo
  2011-02-07  7:58 ` [GIT PULL 0/6] perf/core improments Ingo Molnar
  6 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-02-07  0:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Ingo Molnar, Mike Galbraith, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian, Tom Zanussi

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Next step: Live TUI annotation in perf top, just press enter on a symbol
line.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-top.c   |  181 ++++++++------------------------------------
 tools/perf/util/annotate.c |   76 ++++++++++++++++---
 tools/perf/util/annotate.h |   11 ++-
 tools/perf/util/top.h      |   11 +---
 4 files changed, 106 insertions(+), 173 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 154e088..716118a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -20,6 +20,7 @@
 
 #include "perf.h"
 
+#include "util/annotate.h"
 #include "util/cache.h"
 #include "util/color.h"
 #include "util/evlist.h"
@@ -140,10 +141,7 @@ static int parse_source(struct sym_entry *syme)
 	struct symbol *sym;
 	struct sym_entry_source *source;
 	struct map *map;
-	FILE *file;
-	char command[PATH_MAX*2];
-	const char *path;
-	u64 len;
+	int err = -1;
 
 	if (!syme)
 		return -1;
@@ -162,197 +160,80 @@ static int parse_source(struct sym_entry *syme)
 		if (syme->src == NULL)
 			return -1;
 		pthread_mutex_init(&syme->src->lock, NULL);
+		INIT_LIST_HEAD(&syme->src->head);
 	}
 
 	source = syme->src;
 
-	if (source->lines) {
+	if (symbol__annotation(sym)->histograms != NULL) {
 		pthread_mutex_lock(&source->lock);
 		goto out_assign;
 	}
-	path = map->dso->long_name;
-
-	len = sym->end - sym->start;
-
-	sprintf(command,
-		"objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s",
-		BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
-		BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
-
-	file = popen(command, "r");
-	if (!file)
-		return -1;
 
 	pthread_mutex_lock(&source->lock);
-	source->lines_tail = &source->lines;
-	while (!feof(file)) {
-		struct source_line *src;
-		size_t dummy = 0;
-		char *c, *sep;
-
-		src = malloc(sizeof(struct source_line));
-		assert(src != NULL);
-		memset(src, 0, sizeof(struct source_line));
-
-		if (getline(&src->line, &dummy, file) < 0)
-			break;
-		if (!src->line)
-			break;
-
-		c = strchr(src->line, '\n');
-		if (c)
-			*c = 0;
 
-		src->next = NULL;
-		*source->lines_tail = src;
-		source->lines_tail = &src->next;
-
-		src->eip = strtoull(src->line, &sep, 16);
-		if (*sep == ':')
-			src->eip = map__objdump_2ip(map, src->eip);
-		else /* this line has no ip info (e.g. source line) */
-			src->eip = 0;
+	if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
+		pr_err("Not enough memory for annotating '%s' symbol!\n",
+		       sym->name);
+		goto out_unlock;
 	}
-	pclose(file);
+
+	err = symbol__annotate(sym, syme->map, &source->head, 0);
+	if (err == 0) {
 out_assign:
 	sym_filter_entry = syme;
+	}
+out_unlock:
 	pthread_mutex_unlock(&source->lock);
-	return 0;
+	return err;
 }
 
 static void __zero_source_counters(struct sym_entry *syme)
 {
-	int i;
-	struct source_line *line;
-
-	line = syme->src->lines;
-	while (line) {
-		for (i = 0; i < top.evlist->nr_entries; i++)
-			line->count[i] = 0;
-		line = line->next;
-	}
+	struct symbol *sym = sym_entry__symbol(syme);
+	symbol__annotate_zero_histograms(sym);
 }
 
 static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
 {
-	struct source_line *line;
-
 	if (syme != sym_filter_entry)
 		return;
 
 	if (pthread_mutex_trylock(&syme->src->lock))
 		return;
 
-	if (syme->src == NULL || syme->src->source == NULL)
-		goto out_unlock;
-
-	for (line = syme->src->lines; line; line = line->next) {
-		/* skip lines without IP info */
-		if (line->eip == 0)
-			continue;
-		if (line->eip == ip) {
-			line->count[counter]++;
-			break;
-		}
-		if (line->eip > ip)
-			break;
-	}
-out_unlock:
-	pthread_mutex_unlock(&syme->src->lock);
-}
-
-#define PATTERN_LEN		(BITS_PER_LONG / 4 + 2)
+	ip = syme->map->map_ip(syme->map, ip);
+	symbol__inc_addr_samples(sym_entry__symbol(syme), syme->map, counter, ip);
 
-static void lookup_sym_source(struct sym_entry *syme)
-{
-	struct symbol *symbol = sym_entry__symbol(syme);
-	struct source_line *line;
-	char pattern[PATTERN_LEN + 1];
-
-	sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4,
-		map__rip_2objdump(syme->map, symbol->start));
-
-	pthread_mutex_lock(&syme->src->lock);
-	for (line = syme->src->lines; line; line = line->next) {
-		if (memcmp(line->line, pattern, PATTERN_LEN) == 0) {
-			syme->src->source = line;
-			break;
-		}
-	}
 	pthread_mutex_unlock(&syme->src->lock);
 }
 
-static void show_lines(struct source_line *queue, int count, int total)
-{
-	int i;
-	struct source_line *line;
-
-	line = queue;
-	for (i = 0; i < count; i++) {
-		float pcnt = 100.0*(float)line->count[top.sym_counter]/(float)total;
-
-		printf("%8li %4.1f%%\t%s\n", line->count[top.sym_counter], pcnt, line->line);
-		line = line->next;
-	}
-}
-
-#define TRACE_COUNT     3
-
 static void show_details(struct sym_entry *syme)
 {
 	struct symbol *symbol;
-	struct source_line *line;
-	struct source_line *line_queue = NULL;
-	int displayed = 0;
-	int line_queue_count = 0, total = 0, more = 0;
+	int more;
 
 	if (!syme)
 		return;
 
-	if (!syme->src->source)
-		lookup_sym_source(syme);
-
-	if (!syme->src->source)
+	symbol = sym_entry__symbol(syme);
+	if (!syme->src || symbol__annotation(symbol)->histograms == NULL)
 		return;
 
-	symbol = sym_entry__symbol(syme);
 	printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
 	printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
 
 	pthread_mutex_lock(&syme->src->lock);
-	line = syme->src->source;
-	while (line) {
-		total += line->count[top.sym_counter];
-		line = line->next;
-	}
-
-	line = syme->src->source;
-	while (line) {
-		float pcnt = 0.0;
-
-		if (!line_queue_count)
-			line_queue = line;
-		line_queue_count++;
-
-		if (line->count[top.sym_counter])
-			pcnt = 100.0 * line->count[top.sym_counter] / (float)total;
-		if (pcnt >= (float)sym_pcnt_filter) {
-			if (displayed <= top.print_entries)
-				show_lines(line_queue, line_queue_count, total);
-			else more++;
-			displayed += line_queue_count;
-			line_queue_count = 0;
-			line_queue = NULL;
-		} else if (line_queue_count > TRACE_COUNT) {
-			line_queue = line_queue->next;
-			line_queue_count--;
-		}
-
-		line->count[top.sym_counter] = top.zero ? 0 : line->count[top.sym_counter] * 7 / 8;
-		line = line->next;
-	}
+	more = symbol__annotate_printf(symbol, syme->map, &syme->src->head,
+				       top.sym_evsel->idx, 0, sym_pcnt_filter,
+				       top.print_entries);
+	if (top.zero)
+		symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
+	else
+		symbol__annotate_decay_histogram(symbol, &syme->src->head,
+						 top.sym_evsel->idx);
 	pthread_mutex_unlock(&syme->src->lock);
-	if (more)
+	if (more != 0)
 		printf("%d lines not displayed, maybe increase display entries [e]\n", more);
 }
 
@@ -1172,7 +1053,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 
 	top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
 
-	symbol_conf.priv_size = (sizeof(struct sym_entry) +
+	symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) +
 				 (top.evlist->nr_entries + 1) * sizeof(unsigned long));
 
 	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 10cdbad..2973376 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -22,9 +22,19 @@ int symbol__alloc_hist(struct symbol *sym, int nevents)
 	notes->sizeof_sym_hist = (sizeof(*notes->histograms) +
 				  (sym->end - sym->start) * sizeof(u64));
 	notes->histograms = calloc(nevents, notes->sizeof_sym_hist);
+	notes->nr_histograms = nevents;
 	return notes->histograms == NULL ? -1 : 0;
 }
 
+void symbol__annotate_zero_histograms(struct symbol *sym)
+{
+	struct annotation *notes = symbol__annotation(sym);
+
+	if (notes->histograms != NULL)
+		memset(notes->histograms, 0,
+		       notes->nr_histograms * notes->sizeof_sym_hist);
+}
+
 int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 			     int evidx, u64 addr)
 {
@@ -85,9 +95,10 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
 	return NULL;
 }
 
-static void objdump_line__print(struct objdump_line *oline,
-				struct list_head *head, struct symbol *sym,
-				int evidx, u64 len, int min_pcnt)
+static int objdump_line__print(struct objdump_line *oline,
+			       struct list_head *head, struct symbol *sym,
+			       int evidx, u64 len, int min_pcnt,
+			       int printed, int max_lines)
 {
 	static const char *prev_line;
 	static const char *prev_color;
@@ -119,7 +130,10 @@ static void objdump_line__print(struct objdump_line *oline,
 			percent = 100.0 * hits / h->sum;
 
 		if (percent < min_pcnt)
-			return;
+			return -1;
+
+		if (printed >= max_lines)
+			return 1;
 
 		color = get_percent_color(percent);
 
@@ -140,12 +154,16 @@ static void objdump_line__print(struct objdump_line *oline,
 		color_fprintf(stdout, color, " %7.2f", percent);
 		printf(" :	");
 		color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line);
-	} else {
+	} else if (printed >= max_lines)
+		return 1;
+	else {
 		if (!*oline->line)
 			printf("         :\n");
 		else
 			printf("         :	%s\n", oline->line);
 	}
+
+	return 0;
 }
 
 static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file,
@@ -421,14 +439,15 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
 	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
 }
 
-void symbol__annotate_printf(struct symbol *sym, struct map *map,
-			     struct list_head *head, int evidx, bool full_paths,
-			     int min_pcnt, int max_lines)
+int symbol__annotate_printf(struct symbol *sym, struct map *map,
+			    struct list_head *head, int evidx, bool full_paths,
+			    int min_pcnt, int max_lines)
 {
 	struct dso *dso = map->dso;
 	const char *filename = dso->long_name, *d_filename;
 	struct objdump_line *pos;
 	int printed = 2;
+	int more = 0;
 	u64 len;
 
 	if (full_paths)
@@ -445,10 +464,47 @@ void symbol__annotate_printf(struct symbol *sym, struct map *map,
 		symbol__annotate_hits(sym, evidx);
 
 	list_for_each_entry(pos, head, node) {
-		objdump_line__print(pos, head, sym, evidx, len, min_pcnt);
-		if (max_lines && ++printed >= max_lines)
+		switch (objdump_line__print(pos, head, sym, evidx, len, min_pcnt,
+					    printed, max_lines)) {
+		case 0:
+			++printed;
+			break;
+		case 1:
+			/* filtered by max_lines */
+			++more;
 			break;
+		case -1:
+		default:
+			/* filtered by min_pcnt */
+			break;
+		}
+	}
+
+	return more;
+}
 
+void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = annotation__histogram(notes, evidx);
+
+	memset(h, 0, notes->sizeof_sym_hist);
+}
+
+void symbol__annotate_decay_histogram(struct symbol *sym,
+				      struct list_head *head, int evidx)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = annotation__histogram(notes, evidx);
+	struct objdump_line *pos;
+
+	h->sum = 0;
+
+	list_for_each_entry(pos, head, node) {
+		if (pos->offset != -1) {
+			h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
+			h->sum += h->addr[pos->offset];
+		}
 	}
 }
 
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 53dd92d..b1253aa 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -42,6 +42,7 @@ struct source_line {
 struct annotation {
 	struct source_line *src_line;
 	struct sym_hist	   *histograms;
+	int    		   nr_histograms;
 	int    		   sizeof_sym_hist;
 };
 
@@ -64,12 +65,16 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
 int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 			     int evidx, u64 addr);
 int symbol__alloc_hist(struct symbol *sym, int nevents);
+void symbol__annotate_zero_histograms(struct symbol *sym);
 
 int symbol__annotate(struct symbol *sym, struct map *map,
 		     struct list_head *head, size_t privsize);
-void symbol__annotate_printf(struct symbol *sym, struct map *map,
-			     struct list_head *head, int evidx, bool full_paths,
-			     int min_pcnt, int max_lines);
+int symbol__annotate_printf(struct symbol *sym, struct map *map,
+			    struct list_head *head, int evidx, bool full_paths,
+			    int min_pcnt, int max_lines);
+void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
+void symbol__annotate_decay_histogram(struct symbol *sym,
+				      struct list_head *head, int evidx);
 void objdump_line_list__purge(struct list_head *head);
 
 int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 5009508..fe44afb 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -11,17 +11,8 @@
 struct perf_evlist;
 struct perf_evsel;
 
-struct source_line {
-	u64			eip;
-	unsigned long		count[MAX_COUNTERS]; /* FIXME */
-	char			*line;
-	struct source_line	*next;
-};
-
 struct sym_entry_source {
-	struct source_line	*source;
-	struct source_line	*lines;
-	struct source_line	**lines_tail;
+	struct list_head	head;
 	pthread_mutex_t		lock;
 };
 
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [GIT PULL 0/6] perf/core improments
  2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
                   ` (5 preceding siblings ...)
  2011-02-07  0:42 ` [PATCH 6/6] perf top: Ditch private annotation code, share perf annotate's Arnaldo Carvalho de Melo
@ 2011-02-07  7:58 ` Ingo Molnar
  6 siblings, 0 replies; 8+ messages in thread
From: Ingo Molnar @ 2011-02-07  7:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Mike Galbraith, Paul Mackerras, Peter Zijlstra, Stephane Eranian,
	Tom Zanussi, Arnaldo Carvalho de Melo


* Arnaldo Carvalho de Melo <acme@infradead.org> wrote:

> Hi Ingo,
> 
>         Please consider pulling from:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 perf/core
> 
> Regards,
> 
> - Arnaldo
> 
> Arnaldo Carvalho de Melo (6):
>   perf top: Remove superfluous name_len field
>   perf annotate: Move annotate functions to util/
>   perf annotate: Support multiple histograms in annotation
>   perf annotate: Config options for symbol__tty_annotate
>   perf annotate: Separate objdump parsing from actual screen rendering
>   perf top: Ditch private annotation code, share perf annotate's
> 
>  tools/perf/Makefile                    |    2 +
>  tools/perf/builtin-annotate.c          |  276 ++--------------
>  tools/perf/builtin-report.c            |   18 +-
>  tools/perf/builtin-top.c               |  184 ++---------
>  tools/perf/util/annotate.c             |  550 ++++++++++++++++++++++++++++++++
>  tools/perf/util/annotate.h             |   94 ++++++
>  tools/perf/util/hist.c                 |  219 +-------------
>  tools/perf/util/hist.h                 |   43 +--
>  tools/perf/util/top.c                  |    5 +-
>  tools/perf/util/top.h                  |   12 +-
>  tools/perf/util/ui/browsers/annotate.c |   45 ++-
>  tools/perf/util/ui/browsers/hists.c    |    9 +-
>  12 files changed, 769 insertions(+), 688 deletions(-)
>  create mode 100644 tools/perf/util/annotate.c
>  create mode 100644 tools/perf/util/annotate.h

Pulled, thanks a lot Arnaldo!

	Ingo

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-02-07  7:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-07  0:42 [GIT PULL 0/6] perf/core improments Arnaldo Carvalho de Melo
2011-02-07  0:42 ` [PATCH 1/6] perf top: Remove superfluous name_len field Arnaldo Carvalho de Melo
2011-02-07  0:42 ` [PATCH 2/6] perf annotate: Move annotate functions to util/ Arnaldo Carvalho de Melo
2011-02-07  0:42 ` [PATCH 3/6] perf annotate: Support multiple histograms in annotation Arnaldo Carvalho de Melo
2011-02-07  0:42 ` [PATCH 4/6] perf annotate: Config options for symbol__tty_annotate Arnaldo Carvalho de Melo
2011-02-07  0:42 ` [PATCH 5/6] perf annotate: Separate objdump parsing from actual screen rendering Arnaldo Carvalho de Melo
2011-02-07  0:42 ` [PATCH 6/6] perf top: Ditch private annotation code, share perf annotate's Arnaldo Carvalho de Melo
2011-02-07  7:58 ` [GIT PULL 0/6] perf/core improments Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).