public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/7] perf report/gtk: Add support for hierarchy view
@ 2013-05-21  6:14 Namhyung Kim
  2013-05-21  6:14 ` [PATCH 1/7] perf hists: Basic support of hierarchical view Namhyung Kim
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

Hi guys,

This patchset implements a new feature that collects hist entries in a
hierachical manner.  That means lower-level entries are belonged to an
upper-level entry.  The entry hierachy is built on the sort keys
given, so users can set it whatever they want.  It only shows
top-level entries first, and user can expand/collapse it dynamically.

This is only implemented in --gtk currently, since it's well-matched
to the GTK tree view widget and I didn't want to be bothered with the
TUI browser code at this stage. :)

I don't attach a screenshot now, but this is an hypothetical example
on stdio.  An usual output of perf report look like:

  Overhead  Command      Shared Object                                    Symbol
  ........  .......  .................  ........................................
    22.70%  swapper  [kernel.kallsyms]  [k] intel_idle
     8.36%  swapper  [kernel.kallsyms]  [k] irqtime_acouunt_process_tick.isra.74
     1.33%  swapper  [kernel.kallsyms]  [k] __schedule


If --hierarchy (-H) option is given, it'll look like (after expanding
all children):

  Overhead  Command / Shared Object / Symbol
  ........  ..............................................
    32.39%  - swapper
    32.39%    - [kernel.kallsyms]
    22.70%        [k] intel_idle
     8.36%        [k] irqtime_acouunt_process_tick.isra.74
     1.33%        [k] __schedule

(The overhead of an upper-level entry is the sum of lower-level
entries' overhead).

You can get it from 'perf/hierarchy-v1' branch on my tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/namhyung-perf.git


Any comments are welcome, thanks!
Namhyung


Namhyung Kim (7):
  perf hists: Basic support of hierarchical view
  perf gtk/hists: Use GtkTreeStore instead of GtkListStore
  perf gtk/hists: Factor out perf_gtk__add_entries()
  perf gtk/hists: Add support for hierachical output
  perf report: Add -H (--hierarchy) option
  perf gtk/hists: Add a double-click handler for hierarchy mode
  perf gtk/hists: Set rules hint for the hist browser

 tools/perf/Documentation/perf-report.txt |   5 +
 tools/perf/builtin-report.c              |   6 +
 tools/perf/ui/gtk/hists.c                | 192 ++++++++++++++----
 tools/perf/util/hist.c                   | 325 +++++++++++++++++++++++++++----
 tools/perf/util/sort.h                   |   3 +
 tools/perf/util/symbol.h                 |   3 +-
 6 files changed, 460 insertions(+), 74 deletions(-)

-- 
1.7.11.7


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

* [PATCH 1/7] perf hists: Basic support of hierarchical view
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  6:14 ` [PATCH 2/7] perf gtk/hists: Use GtkTreeStore instead of GtkListStore Namhyung Kim
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

In a hierarchical view, the events sorted and grouped on first key,
and then second key, and so on.  Now each hist entry has 3 of hroots
to save it's children entries.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/hist.c   | 325 +++++++++++++++++++++++++++++++++++++++++------
 tools/perf/util/sort.h   |   3 +
 tools/perf/util/symbol.h |   3 +-
 3 files changed, 291 insertions(+), 40 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 72b4eec820c3..80b981d52582 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -348,7 +348,7 @@ static u8 symbol__parent_filter(const struct symbol *parent)
 	return 0;
 }
 
-static struct hist_entry *add_hist_entry(struct hists *hists,
+static struct hist_entry *__add_hist_entry(struct hists *hists,
 				      struct hist_entry *entry,
 				      struct addr_location *al,
 				      u64 period,
@@ -417,6 +417,96 @@ out_unlock:
 	return he;
 }
 
+static struct hist_entry *__add_hist_entry_hierarchy(struct hists *hists,
+						     struct hist_entry *entry,
+						     struct addr_location *al,
+						     u64 period, u64 weight)
+{
+	struct rb_root *root;
+	struct rb_node **p;
+	struct rb_node *parent = NULL;
+	struct hist_entry *he = NULL;
+	struct sort_entry *se;
+	int cmp;
+
+	pthread_mutex_lock(&hists->lock);
+
+	root = hists->entries_in;
+	p = &root->rb_node;
+
+	list_for_each_entry(se, &hist_entry__sort_list, list) {
+		while (*p != NULL) {
+			parent = *p;
+			he = rb_entry(parent, struct hist_entry, rb_node_in);
+
+			/*
+			 * Make sure that it receives arguments in a same order as
+			 * hist_entry__collapse() so that we can use an appropriate
+			 * function when searching an entry regardless which sort
+			 * keys were used.
+			 */
+			cmp = se->se_cmp(he, entry);
+
+			if (!cmp) {
+				he_stat__add_period(&he->stat, period, weight);
+
+				/*
+				 * This mem info was allocated from machine__resolve_mem
+				 * and will not be used anymore.
+				 */
+				free(entry->mem_info);
+
+				/* If the map of an existing hist_entry has
+				 * become out-of-date due to an exec() or
+				 * similar, update it.  Otherwise we will
+				 * mis-adjust symbol addresses when computing
+				 * the history counter to increment.
+				 */
+				if (he->ms.map != entry->ms.map) {
+					he->ms.map = entry->ms.map;
+					if (he->ms.map)
+						he->ms.map->referenced = true;
+				}
+				goto next;
+			}
+
+			if (cmp < 0)
+				p = &(*p)->rb_left;
+			else
+				p = &(*p)->rb_right;
+		}
+
+		he = hist_entry__new(entry);
+		if (!he)
+			goto out_unlock;
+
+		rb_link_node(&he->rb_node_in, parent, p);
+		rb_insert_color(&he->rb_node_in, root);
+next:
+		hist_entry__add_cpumode_period(he, al->cpumode, period);
+
+		root = &he->rb_hroot_in;
+		p = &root->rb_node;
+		parent = NULL;
+	}
+
+out_unlock:
+	pthread_mutex_unlock(&hists->lock);
+	return he;
+}
+
+static struct hist_entry *add_hist_entry(struct hists *hists,
+				      struct hist_entry *entry,
+				      struct addr_location *al,
+				      u64 period,
+				      u64 weight)
+{
+	if (!symbol_conf.hierarchy)
+		return __add_hist_entry(hists, entry, al, period, weight);
+
+	return __add_hist_entry_hierarchy(hists, entry, al, period, weight);
+}
+
 struct hist_entry *__hists__add_mem_entry(struct hists *self,
 					  struct addr_location *al,
 					  struct symbol *sym_parent,
@@ -548,6 +638,8 @@ void hist_entry__free(struct hist_entry *he)
 	free(he);
 }
 
+static void hists__apply_filters(struct hists *hists, struct hist_entry *he);
+
 /*
  * collapse the histogram
  */
@@ -591,56 +683,148 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
 	return true;
 }
 
-static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
+static void hists__collapse_resort_entries(struct hists *hists,
+					   struct rb_root *root_in,
+					   struct rb_root *root)
 {
-	struct rb_root *root;
-
-	pthread_mutex_lock(&hists->lock);
+	struct rb_node *next;
+	struct hist_entry *he;
 
-	root = hists->entries_in;
-	if (++hists->entries_in > &hists->entries_in_array[1])
-		hists->entries_in = &hists->entries_in_array[0];
+	next = rb_first(root_in);
 
-	pthread_mutex_unlock(&hists->lock);
+	while (next) {
+		he = rb_entry(next, struct hist_entry, rb_node_in);
+		next = rb_next(&he->rb_node_in);
 
-	return root;
+		rb_erase(&he->rb_node_in, root_in);
+		if (hists__collapse_insert_entry(hists, root, he)) {
+			/*
+			 * If it wasn't combined with one of the entries already
+			 * collapsed, we need to apply the filters that may have
+			 * been set by, say, the hist_browser.
+			 */
+			hists__apply_filters(hists, he);
+		}
+	}
 }
 
-static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
+static struct hist_entry *
+__collapse_insert_entry_hierarchy(struct rb_root *root, struct hist_entry *he,
+				  struct sort_entry *se)
 {
-	hists__filter_entry_by_dso(hists, he);
-	hists__filter_entry_by_thread(hists, he);
-	hists__filter_entry_by_symbol(hists, he);
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct hist_entry *iter;
+	int64_t cmp;
+
+	while (*p != NULL) {
+		int64_t (*f)(struct hist_entry *, struct hist_entry *);
+		f = se->se_collapse ?: se->se_cmp;
+
+		parent = *p;
+		iter = rb_entry(parent, struct hist_entry, rb_node_in);
+
+		cmp = f(iter, he);
+
+		if (!cmp) {
+			he_stat__add_stat(&iter->stat, &he->stat);
+
+			if (symbol_conf.use_callchain) {
+				callchain_cursor_reset(&callchain_cursor);
+				callchain_merge(&callchain_cursor,
+						iter->callchain,
+						he->callchain);
+			}
+			return iter;
+		}
+
+		if (cmp < 0)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+
+	rb_link_node(&he->rb_node_in, parent, p);
+	rb_insert_color(&he->rb_node_in, root);
+	return he;
 }
 
-static void __hists__collapse_resort(struct hists *hists, bool threaded)
+static void
+hists__collapse_resort_entries_hierarchy(struct hists *hists,
+					 struct rb_root *root_in,
+					 struct rb_root *root,
+					 struct sort_entry *se)
 {
-	struct rb_root *root;
 	struct rb_node *next;
-	struct hist_entry *n;
+	struct hist_entry *he;
+	struct sort_entry *se_next;
 
-	if (!sort__need_collapse && !threaded)
+	next = rb_first(root_in);
+	if (next == NULL)
 		return;
 
-	root = hists__get_rotate_entries_in(hists);
-	next = rb_first(root);
+	BUG_ON(&se->list == &hist_entry__sort_list);
+	se_next = list_entry(se->list.next, struct sort_entry, list);
 
 	while (next) {
-		n = rb_entry(next, struct hist_entry, rb_node_in);
-		next = rb_next(&n->rb_node_in);
+		struct hist_entry *he_new;
+
+		he = rb_entry(next, struct hist_entry, rb_node_in);
+		next = rb_next(&he->rb_node_in);
 
-		rb_erase(&n->rb_node_in, root);
-		if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
+		rb_erase(&he->rb_node_in, root_in);
+		he_new = __collapse_insert_entry_hierarchy(root, he, se);
+		if (he == he_new) {
 			/*
 			 * If it wasn't combined with one of the entries already
 			 * collapsed, we need to apply the filters that may have
 			 * been set by, say, the hist_browser.
 			 */
-			hists__apply_filters(hists, n);
+			hists__apply_filters(hists, he);
 		}
+
+		hists__collapse_resort_entries_hierarchy(hists, &he->rb_hroot_in,
+					&he_new->rb_hroot_collapsed, se_next);
+
+		if (he != he_new)
+			hist_entry__free(he);
 	}
 }
 
+static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
+{
+	struct rb_root *root;
+
+	pthread_mutex_lock(&hists->lock);
+
+	root = hists->entries_in;
+	if (++hists->entries_in > &hists->entries_in_array[1])
+		hists->entries_in = &hists->entries_in_array[0];
+
+	pthread_mutex_unlock(&hists->lock);
+
+	return root;
+}
+
+static void __hists__collapse_resort(struct hists *hists, bool threaded)
+{
+	struct rb_root *root_in;
+	struct rb_root *root;
+	struct sort_entry *se;
+
+	if (!sort__need_collapse && !threaded)
+		return;
+
+	root_in = hists__get_rotate_entries_in(hists);
+	root = &hists->entries_collapsed;
+
+	if (!symbol_conf.hierarchy)
+		return hists__collapse_resort_entries(hists, root_in, root);
+
+	se = list_first_entry(&hist_entry__sort_list, struct sort_entry, list);
+	hists__collapse_resort_entries_hierarchy(hists, root_in, root, se);
+}
+
 void hists__collapse_resort(struct hists *hists)
 {
 	return __hists__collapse_resort(hists, false);
@@ -711,11 +895,11 @@ out:
 	return ret;
 }
 
-static void __hists__insert_output_entry(struct rb_root *entries,
+static void __hists__insert_output_entry(struct rb_root *root,
 					 struct hist_entry *he,
 					 u64 min_callchain_hits)
 {
-	struct rb_node **p = &entries->rb_node;
+	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
 	struct hist_entry *iter;
 
@@ -734,37 +918,92 @@ static void __hists__insert_output_entry(struct rb_root *entries,
 	}
 
 	rb_link_node(&he->rb_node, parent, p);
-	rb_insert_color(&he->rb_node, entries);
+	rb_insert_color(&he->rb_node, root);
+}
+
+static void hists__output_resort_entries(struct hists *hists,
+					 struct rb_root *root_in,
+					 struct rb_root *root,
+					 u64 min_callchain_hits)
+{
+	struct rb_node *next;
+	struct hist_entry *he;
+
+	next = rb_first(root_in);
+
+	while (next) {
+		he = rb_entry(next, struct hist_entry, rb_node_in);
+		next = rb_next(&he->rb_node_in);
+
+		__hists__insert_output_entry(root, he, min_callchain_hits);
+		hists__inc_nr_entries(hists, he);
+	}
+}
+
+static void hists__output_resort_entries_hierarchy(struct hists *hists,
+						   struct rb_root *root_in,
+						   struct rb_root *root,
+						   u64 min_callchain_hits,
+						   bool threaded)
+{
+	struct rb_node *next;
+	struct hist_entry *he;
+	struct rb_root *hroot_in;
+
+	next = rb_first(root_in);
+
+	if (next == NULL) {
+		he = list_entry(root, struct hist_entry, rb_hroot);
+		/* only count leaf nodes */
+		hists__inc_nr_entries(hists, he);
+		return;
+	}
+
+	while (next) {
+		he = rb_entry(next, struct hist_entry, rb_node_in);
+		next = rb_next(&he->rb_node_in);
+
+		__hists__insert_output_entry(root, he, min_callchain_hits);
+
+		if (sort__need_collapse || threaded)
+			hroot_in = &he->rb_hroot_collapsed;
+		else
+			hroot_in = &he->rb_hroot_in;
+
+		hists__output_resort_entries_hierarchy(hists, hroot_in,
+						       &he->rb_hroot,
+						       min_callchain_hits,
+						       threaded);
+	}
 }
 
 static void __hists__output_resort(struct hists *hists, bool threaded)
 {
+	struct rb_root *root_in;
 	struct rb_root *root;
-	struct rb_node *next;
-	struct hist_entry *n;
 	u64 min_callchain_hits;
 
 	min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
 
 	if (sort__need_collapse || threaded)
-		root = &hists->entries_collapsed;
+		root_in = &hists->entries_collapsed;
 	else
-		root = hists->entries_in;
+		root_in = hists->entries_in;
 
-	next = rb_first(root);
 	hists->entries = RB_ROOT;
+	root = &hists->entries;
 
 	hists->nr_entries = 0;
 	hists->stats.total_period = 0;
 	hists__reset_col_len(hists);
 
-	while (next) {
-		n = rb_entry(next, struct hist_entry, rb_node_in);
-		next = rb_next(&n->rb_node_in);
-
-		__hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
-		hists__inc_nr_entries(hists, n);
+	if (!symbol_conf.hierarchy) {
+		return hists__output_resort_entries(hists, root_in, root,
+						    min_callchain_hits);
 	}
+
+	hists__output_resort_entries_hierarchy(hists, root_in, root,
+					       min_callchain_hits, threaded);
 }
 
 void hists__output_resort(struct hists *hists)
@@ -889,6 +1128,14 @@ void hists__filter_by_symbol(struct hists *hists)
 	}
 }
 
+static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
+{
+	hists__filter_entry_by_dso(hists, he);
+	hists__filter_entry_by_thread(hists, he);
+	hists__filter_entry_by_symbol(hists, he);
+}
+
+
 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, evidx, ip);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 51f1b5a854e7..6c2ba362ca05 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -75,6 +75,9 @@ struct hist_entry_diff {
 struct hist_entry {
 	struct rb_node		rb_node_in;
 	struct rb_node		rb_node;
+	struct rb_root		rb_hroot_in;
+	struct rb_root		rb_hroot_collapsed;
+	struct rb_root		rb_hroot;
 	union {
 		struct list_head node;
 		struct list_head head;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5f720dc076da..ee0cfd8b785e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -98,7 +98,8 @@ struct symbol_conf {
 			annotate_asm_raw,
 			annotate_src,
 			event_group,
-			demangle;
+			demangle,
+			hierarchy;
 	const char	*vmlinux_name,
 			*kallsyms_name,
 			*source_prefix,
-- 
1.7.11.7


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

* [PATCH 2/7] perf gtk/hists: Use GtkTreeStore instead of GtkListStore
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
  2013-05-21  6:14 ` [PATCH 1/7] perf hists: Basic support of hierarchical view Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  6:14 ` [PATCH 3/7] perf gtk/hists: Factor out perf_gtk__add_entries() Namhyung Kim
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

The GtkTreeStore can save items in a tree-like way.  This is a
preparation for supporting hierachical output in the hist browser.

Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/gtk/hists.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 6f259b3d14e2..ba59d5d63d74 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -130,7 +130,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 	GType col_types[MAX_COLUMNS];
 	GtkCellRenderer *renderer;
 	struct sort_entry *se;
-	GtkListStore *store;
+	GtkTreeStore *store;
 	struct rb_node *nd;
 	GtkWidget *view;
 	int col_idx;
@@ -155,7 +155,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 		col_types[nr_cols++] = G_TYPE_STRING;
 	}
 
-	store = gtk_list_store_newv(nr_cols, col_types);
+	store = gtk_tree_store_newv(nr_cols, col_types);
 
 	view = gtk_tree_view_new();
 
@@ -193,7 +193,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 		if (h->filtered)
 			continue;
 
-		gtk_list_store_append(store, &iter);
+		gtk_tree_store_append(store, &iter, NULL);
 
 		col_idx = 0;
 
@@ -203,7 +203,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 			else
 				fmt->entry(&hpp, h);
 
-			gtk_list_store_set(store, &iter, col_idx++, s, -1);
+			gtk_tree_store_set(store, &iter, col_idx++, s, -1);
 		}
 
 		list_for_each_entry(se, &hist_entry__sort_list, list) {
@@ -213,7 +213,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 			se->se_snprintf(h, s, ARRAY_SIZE(s),
 					hists__col_len(hists, se->se_width_idx));
 
-			gtk_list_store_set(store, &iter, col_idx++, s, -1);
+			gtk_tree_store_set(store, &iter, col_idx++, s, -1);
 		}
 	}
 
-- 
1.7.11.7


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

* [PATCH 3/7] perf gtk/hists: Factor out perf_gtk__add_entries()
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
  2013-05-21  6:14 ` [PATCH 1/7] perf hists: Basic support of hierarchical view Namhyung Kim
  2013-05-21  6:14 ` [PATCH 2/7] perf gtk/hists: Use GtkTreeStore instead of GtkListStore Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  6:14 ` [PATCH 4/7] perf gtk/hists: Add support for hierachical output Namhyung Kim
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

This is a preparation for supporting hierarchical output in the hist
browser.

Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/gtk/hists.c | 72 +++++++++++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index ba59d5d63d74..e1b8f702daf2 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -124,6 +124,46 @@ void perf_gtk__init_hpp(void)
 				perf_gtk__hpp_color_overhead_guest_us;
 }
 
+static void perf_gtk__add_entries(struct hists *hists, struct perf_hpp *hpp,
+				  GtkTreeStore *store)
+{
+	int col_idx;
+	struct rb_node *nd;
+	struct perf_hpp_fmt *fmt;
+	struct sort_entry *se;
+
+	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
+		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+		GtkTreeIter iter;
+
+		if (h->filtered)
+			continue;
+
+		gtk_tree_store_append(store, &iter, NULL);
+
+		col_idx = 0;
+
+		perf_hpp__for_each_format(fmt) {
+			if (fmt->color)
+				fmt->color(hpp, h);
+			else
+				fmt->entry(hpp, h);
+
+			gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
+		}
+
+		list_for_each_entry(se, &hist_entry__sort_list, list) {
+			if (se->elide)
+				continue;
+
+			se->se_snprintf(h, hpp->buf, hpp->size,
+					hists__col_len(hists, se->se_width_idx));
+
+			gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
+		}
+	}
+}
+
 static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 {
 	struct perf_hpp_fmt *fmt;
@@ -131,7 +171,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 	GtkCellRenderer *renderer;
 	struct sort_entry *se;
 	GtkTreeStore *store;
-	struct rb_node *nd;
 	GtkWidget *view;
 	int col_idx;
 	int nr_cols;
@@ -186,36 +225,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 
 	g_object_unref(GTK_TREE_MODEL(store));
 
-	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
-		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-		GtkTreeIter iter;
-
-		if (h->filtered)
-			continue;
-
-		gtk_tree_store_append(store, &iter, NULL);
-
-		col_idx = 0;
-
-		perf_hpp__for_each_format(fmt) {
-			if (fmt->color)
-				fmt->color(&hpp, h);
-			else
-				fmt->entry(&hpp, h);
-
-			gtk_tree_store_set(store, &iter, col_idx++, s, -1);
-		}
-
-		list_for_each_entry(se, &hist_entry__sort_list, list) {
-			if (se->elide)
-				continue;
-
-			se->se_snprintf(h, s, ARRAY_SIZE(s),
-					hists__col_len(hists, se->se_width_idx));
-
-			gtk_tree_store_set(store, &iter, col_idx++, s, -1);
-		}
-	}
+	perf_gtk__add_entries(hists, &hpp, store);
 
 	gtk_container_add(GTK_CONTAINER(window), view);
 }
-- 
1.7.11.7


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

* [PATCH 4/7] perf gtk/hists: Add support for hierachical output
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
                   ` (2 preceding siblings ...)
  2013-05-21  6:14 ` [PATCH 3/7] perf gtk/hists: Factor out perf_gtk__add_entries() Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  6:14 ` [PATCH 5/7] perf report: Add -H (--hierarchy) option Namhyung Kim
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

When the symbol_conf.hierarchy is set, perf will collapse entries by a
first sort key, and then second key, and so on in a hierarchical
manner.  It'll be looked like a tree view so set the expander column
to a column that displays sort entries.

Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/gtk/hists.c | 109 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 103 insertions(+), 6 deletions(-)

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index e1b8f702daf2..fb4b5ff00319 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -164,6 +164,62 @@ static void perf_gtk__add_entries(struct hists *hists, struct perf_hpp *hpp,
 	}
 }
 
+static void __perf_gtk__add_entries_hierarchy(struct hists *hists,
+					      struct rb_root *root,
+					      GtkTreeStore *store,
+					      GtkTreeIter *parent,
+					      struct perf_hpp *hpp,
+					      struct sort_entry *se)
+{
+	int col_idx;
+	struct rb_node *nd;
+	struct perf_hpp_fmt *fmt;
+
+	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
+		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+		GtkTreeIter iter;
+		struct sort_entry *next_se;
+
+		if (h->filtered)
+			continue;
+
+		gtk_tree_store_append(store, &iter, parent);
+
+		col_idx = 0;
+
+		perf_hpp__for_each_format(fmt) {
+			if (fmt->color)
+				fmt->color(hpp, h);
+			else
+				fmt->entry(hpp, h);
+
+			gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
+		}
+
+		se->se_snprintf(h, hpp->buf, hpp->size,
+				hists__col_len(hists, se->se_width_idx));
+
+		gtk_tree_store_set(store, &iter, col_idx++, ltrim(hpp->buf), -1);
+
+		next_se = list_entry(se->list.next, struct sort_entry, list);
+		__perf_gtk__add_entries_hierarchy(hists, &h->rb_hroot, store,
+						  &iter, hpp, next_se);
+	}
+}
+
+static void perf_gtk__add_entries_hierarchy(struct hists *hists,
+					    struct perf_hpp *hpp,
+					    GtkTreeStore *store)
+{
+	struct rb_root *root;
+	struct sort_entry *se;
+
+	root = &hists->entries;
+	se = list_first_entry(&hist_entry__sort_list, struct sort_entry, list);
+
+	__perf_gtk__add_entries_hierarchy(hists, root, store, NULL, hpp, se);
+}
+
 static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 {
 	struct perf_hpp_fmt *fmt;
@@ -173,6 +229,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 	GtkTreeStore *store;
 	GtkWidget *view;
 	int col_idx;
+	int sort_col = 0;
 	int nr_cols;
 	char s[512];
 
@@ -187,11 +244,19 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 	perf_hpp__for_each_format(fmt)
 		col_types[nr_cols++] = G_TYPE_STRING;
 
-	list_for_each_entry(se, &hist_entry__sort_list, list) {
-		if (se->elide)
-			continue;
-
-		col_types[nr_cols++] = G_TYPE_STRING;
+	if (symbol_conf.hierarchy) {
+		/*
+		 * In --hierarchy mode, all sort entries are displayed in a
+		 * single column.
+		 */
+		col_types[nr_cols] = G_TYPE_STRING;
+		sort_col = nr_cols++;
+	} else {
+		list_for_each_entry(se, &hist_entry__sort_list, list) {
+			if (se->elide)
+				continue;
+			col_types[nr_cols++] = G_TYPE_STRING;
+		}
 	}
 
 	store = gtk_tree_store_newv(nr_cols, col_types);
@@ -211,6 +276,26 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 							    col_idx++, NULL);
 	}
 
+	if (symbol_conf.hierarchy) {
+		bool first = true;
+
+		s[0] = '\0';
+		list_for_each_entry(se, &hist_entry__sort_list, list) {
+			if (!first)
+				strcat(s, " / ");
+
+			strcat(s, se->se_header);
+
+			first = false;
+		}
+
+		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+							    -1, s,
+							    renderer, "text",
+							    col_idx++, NULL);
+		goto add;
+	}
+
 	list_for_each_entry(se, &hist_entry__sort_list, list) {
 		if (se->elide)
 			continue;
@@ -221,11 +306,23 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 							    col_idx++, NULL);
 	}
 
+add:
 	gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
 
 	g_object_unref(GTK_TREE_MODEL(store));
 
-	perf_gtk__add_entries(hists, &hpp, store);
+	if (!symbol_conf.hierarchy)
+		perf_gtk__add_entries(hists, &hpp, store);
+	else {
+		GtkTreeViewColumn *expander_col;
+
+		expander_col = gtk_tree_view_get_column(GTK_TREE_VIEW(view),
+							sort_col);
+		gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view),
+						  expander_col);
+
+		perf_gtk__add_entries_hierarchy(hists, &hpp, store);
+	}
 
 	gtk_container_add(GTK_CONTAINER(window), view);
 }
-- 
1.7.11.7


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

* [PATCH 5/7] perf report: Add -H (--hierarchy) option
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
                   ` (3 preceding siblings ...)
  2013-05-21  6:14 ` [PATCH 4/7] perf gtk/hists: Add support for hierachical output Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  6:14 ` [PATCH 6/7] perf gtk/hists: Add a double-click handler for hierarchy mode Namhyung Kim
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

It's for enabling the hierarchical view.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Documentation/perf-report.txt | 5 +++++
 tools/perf/builtin-report.c              | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 7d5f4f38aa52..3c86b9f83c54 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -210,6 +210,11 @@ OPTIONS
 	Demangle symbol names to human readable form. It's enabled by default,
 	disable with --no-demangle.
 
+-H::
+--hierarchy::
+	Show events in hierarchical view.  Each events are grouped under prior
+	sort keys.  Currently --gtk output is supported only.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-annotate[1]
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d45bf9b0361d..9b9a35b296d8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -809,6 +809,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
 		    "Disable symbol demangling"),
 	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
+	OPT_BOOLEAN('H', "hierarchy", &symbol_conf.hierarchy, "Hierarchical view"),
 	OPT_END()
 	};
 
@@ -833,6 +834,11 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 			input_name = "perf.data";
 	}
 
+	if (symbol_conf.hierarchy && use_browser != 2) {
+		pr_err("--hierarchy option is only used for --gtk output\n");
+		return -EINVAL;
+	}
+
 	if (strcmp(input_name, "-") != 0)
 		setup_browser(true);
 	else {
-- 
1.7.11.7


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

* [PATCH 6/7] perf gtk/hists: Add a double-click handler for hierarchy mode
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
                   ` (4 preceding siblings ...)
  2013-05-21  6:14 ` [PATCH 5/7] perf report: Add -H (--hierarchy) option Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  6:14 ` [PATCH 7/7] perf gtk/hists: Set rules hint for the hist browser Namhyung Kim
  2013-05-21  7:04 ` [RFC 0/7] perf report/gtk: Add support for hierarchy view Pekka Enberg
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

If hierarchy mode is enabled, add "row-activated" signal handler for
handling double-click or pressing ENTER key action.

Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/gtk/hists.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index fb4b5ff00319..e161317236fe 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -220,6 +220,18 @@ static void perf_gtk__add_entries_hierarchy(struct hists *hists,
 	__perf_gtk__add_entries_hierarchy(hists, root, store, NULL, hpp, se);
 }
 
+static void on_row_activated(GtkTreeView *view, GtkTreePath *path,
+			     GtkTreeViewColumn *col __maybe_unused,
+			     gpointer user_data __maybe_unused)
+{
+	bool expanded = gtk_tree_view_row_expanded(view, path);
+
+	if (expanded)
+		gtk_tree_view_collapse_row(view, path);
+	else
+		gtk_tree_view_expand_row(view, path, FALSE);
+}
+
 static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 {
 	struct perf_hpp_fmt *fmt;
@@ -322,6 +334,9 @@ add:
 						  expander_col);
 
 		perf_gtk__add_entries_hierarchy(hists, &hpp, store);
+
+		g_signal_connect(view, "row-activated",
+				 G_CALLBACK(on_row_activated), NULL);
 	}
 
 	gtk_container_add(GTK_CONTAINER(window), view);
-- 
1.7.11.7


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

* [PATCH 7/7] perf gtk/hists: Set rules hint for the hist browser
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
                   ` (5 preceding siblings ...)
  2013-05-21  6:14 ` [PATCH 6/7] perf gtk/hists: Add a double-click handler for hierarchy mode Namhyung Kim
@ 2013-05-21  6:14 ` Namhyung Kim
  2013-05-21  7:04 ` [RFC 0/7] perf report/gtk: Add support for hierarchy view Pekka Enberg
  7 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  6:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian, Pekka Enberg

From: Namhyung Kim <namhyung.kim@lge.com>

The 'rules' means that every second line of the tree view has a shaded
background, which makes it easier to see which cell belongs to which
row in the tree view.  It can be useful for a tree view that has a lot
of rows.

Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/gtk/hists.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index e161317236fe..b108d2fb1130 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -339,6 +339,8 @@ add:
 				 G_CALLBACK(on_row_activated), NULL);
 	}
 
+	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
+
 	gtk_container_add(GTK_CONTAINER(window), view);
 }
 
-- 
1.7.11.7


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

* Re: [RFC 0/7] perf report/gtk: Add support for hierarchy view
  2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
                   ` (6 preceding siblings ...)
  2013-05-21  6:14 ` [PATCH 7/7] perf gtk/hists: Set rules hint for the hist browser Namhyung Kim
@ 2013-05-21  7:04 ` Pekka Enberg
  2013-05-21  7:26   ` Namhyung Kim
  7 siblings, 1 reply; 11+ messages in thread
From: Pekka Enberg @ 2013-05-21  7:04 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Namhyung Kim, LKML, Jiri Olsa, David Ahern,
	Stephane Eranian

Hello,

On Tue, May 21, 2013 at 9:14 AM, Namhyung Kim <namhyung@kernel.org> wrote:
> This patchset implements a new feature that collects hist entries in a
> hierachical manner.  That means lower-level entries are belonged to an
> upper-level entry.  The entry hierachy is built on the sort keys
> given, so users can set it whatever they want.  It only shows
> top-level entries first, and user can expand/collapse it dynamically.
>
> This is only implemented in --gtk currently, since it's well-matched
> to the GTK tree view widget and I didn't want to be bothered with the
> TUI browser code at this stage. :)

Can use this infrastructure to support call-graphs in the GTK UI?

                        Pekka

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

* Re: [RFC 0/7] perf report/gtk: Add support for hierarchy view
  2013-05-21  7:04 ` [RFC 0/7] perf report/gtk: Add support for hierarchy view Pekka Enberg
@ 2013-05-21  7:26   ` Namhyung Kim
  2013-05-22  8:45     ` Pekka Enberg
  0 siblings, 1 reply; 11+ messages in thread
From: Namhyung Kim @ 2013-05-21  7:26 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Namhyung Kim, LKML, Jiri Olsa, David Ahern,
	Stephane Eranian

Hi Pekka,

On Tue, 21 May 2013 10:04:05 +0300, Pekka Enberg wrote:
> Hello,
>
> On Tue, May 21, 2013 at 9:14 AM, Namhyung Kim <namhyung@kernel.org> wrote:
>> This patchset implements a new feature that collects hist entries in a
>> hierachical manner.  That means lower-level entries are belonged to an
>> upper-level entry.  The entry hierachy is built on the sort keys
>> given, so users can set it whatever they want.  It only shows
>> top-level entries first, and user can expand/collapse it dynamically.
>>
>> This is only implemented in --gtk currently, since it's well-matched
>> to the GTK tree view widget and I didn't want to be bothered with the
>> TUI browser code at this stage. :)
>
> Can use this infrastructure to support call-graphs in the GTK UI?

Yes, I think it's doable.  I don't have an idea how to use both of the
features at the same time though.  Anyway, I'll try to add support for
callchains later.

Thanks,
Namhyung

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

* Re: [RFC 0/7] perf report/gtk: Add support for hierarchy view
  2013-05-21  7:26   ` Namhyung Kim
@ 2013-05-22  8:45     ` Pekka Enberg
  0 siblings, 0 replies; 11+ messages in thread
From: Pekka Enberg @ 2013-05-22  8:45 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Namhyung Kim, LKML, Jiri Olsa, David Ahern,
	Stephane Eranian

On 05/21/2013 10:26 AM, Namhyung Kim wrote:
> On Tue, 21 May 2013 10:04:05 +0300, Pekka Enberg wrote:
>> Hello,
>>
>> On Tue, May 21, 2013 at 9:14 AM, Namhyung Kim <namhyung@kernel.org> wrote:
>>> This patchset implements a new feature that collects hist entries in a
>>> hierachical manner.  That means lower-level entries are belonged to an
>>> upper-level entry.  The entry hierachy is built on the sort keys
>>> given, so users can set it whatever they want.  It only shows
>>> top-level entries first, and user can expand/collapse it dynamically.
>>>
>>> This is only implemented in --gtk currently, since it's well-matched
>>> to the GTK tree view widget and I didn't want to be bothered with the
>>> TUI browser code at this stage. :)
>>
>> Can use this infrastructure to support call-graphs in the GTK UI?
>
> Yes, I think it's doable.  I don't have an idea how to use both of the
> features at the same time though.  Anyway, I'll try to add support for
> callchains later.

So I think hierarchy view makes tons of sense but it needs to be 
orthogonal with call-graphs. Preferably in such a way that if you have 
both hierarchy view and call-graphs enabled, you can seamlessly drill 
down from process level all the way to call-graph leaf nodes.

			Pekka

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

end of thread, other threads:[~2013-05-22  8:45 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-21  6:14 [RFC 0/7] perf report/gtk: Add support for hierarchy view Namhyung Kim
2013-05-21  6:14 ` [PATCH 1/7] perf hists: Basic support of hierarchical view Namhyung Kim
2013-05-21  6:14 ` [PATCH 2/7] perf gtk/hists: Use GtkTreeStore instead of GtkListStore Namhyung Kim
2013-05-21  6:14 ` [PATCH 3/7] perf gtk/hists: Factor out perf_gtk__add_entries() Namhyung Kim
2013-05-21  6:14 ` [PATCH 4/7] perf gtk/hists: Add support for hierachical output Namhyung Kim
2013-05-21  6:14 ` [PATCH 5/7] perf report: Add -H (--hierarchy) option Namhyung Kim
2013-05-21  6:14 ` [PATCH 6/7] perf gtk/hists: Add a double-click handler for hierarchy mode Namhyung Kim
2013-05-21  6:14 ` [PATCH 7/7] perf gtk/hists: Set rules hint for the hist browser Namhyung Kim
2013-05-21  7:04 ` [RFC 0/7] perf report/gtk: Add support for hierarchy view Pekka Enberg
2013-05-21  7:26   ` Namhyung Kim
2013-05-22  8:45     ` Pekka Enberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox