linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET 00/13] perf report: Add support for event group view (v8)
@ 2013-01-15  7:31 Namhyung Kim
  2013-01-15  7:31 ` [PATCH 01/13] perf tools: Keep group information Namhyung Kim
                   ` (13 more replies)
  0 siblings, 14 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Hi,

This is my 8th attempt to enable the event group view for perf report.
For basic idea and usage example, please see my initial post [1].

This version is rebased on the current acme/perf/core and it's mainly
changed due to a refactoring of gtk browser.

You can get this via 'perf/group-v8' branch on my tree:

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

Any comments are welcome, thanks,
Namhyung


v7 -> v8:
 * rebase onto acme/perf/core
 * patch 3 in the previous version is merged
 * add Jiri's Acked-by's

v6 -> v7:
 * hists__{match,link} changes are merged separately
 * factor out inc_group_count() from parsing group_def (Jiri)
 * add checking for group fields in evlist/evsel (Jiri)
 * check return value of during header processing (Arnaldo)
 * get rid of a temporal array in hpp functions (Arnaldo)
 * convert hpp macros to static inline functions (Jiri)

v5 -> v6:
 * set ->leader alse for leader evsel (Arnaldo)
 * use hists__{match,link} (Arnaldo)

v4 -> v5:
 * rebase onto acme/perf/core

v3 -> v4:
 * patch 1-9 in previous post are merged.
 * add Jiri's Acked-by
 * add report.group config option

v2 -> v3:
 * drop patch 1 since it's merged into acme/perf/core
 * cherry-pick Jiri's hpp changes
 * add missing bswap_32 on reading nr_groups (Jiri)
 * remove perf_evlist__recalc_nr_groups() in favor of list_is_last (Jiri)

v1 -> v2:
 * save group relation to header (Jiri)

[1] https://lkml.org/lkml/2012/7/24/81


Namhyung Kim (13):
  perf tools: Keep group information
  perf tests: Add group test conditions
  perf header: Add HEADER_GROUP_DESC feature
  perf report: Make another loop for linking group hists
  perf hists: Resort hist entries using group members for output
  perf ui/hist: Add support for event group view
  perf hist browser: Add support for event group view
  perf gtk/browser: Add support for event group view
  perf gtk/browser: Trim column header string when event group enabled
  perf report: Bypass non-leader events when event group is enabled
  perf report: Show group description when event group is enabled
  perf report: Add --group option
  perf report: Add report.group config option

 tools/perf/Documentation/perf-report.txt |   3 +
 tools/perf/builtin-record.c              |   3 +
 tools/perf/builtin-report.c              |  47 ++++-
 tools/perf/builtin-script.c              |  12 --
 tools/perf/tests/parse-events.c          |  28 +++
 tools/perf/ui/browsers/hists.c           | 219 +++++++++++++++++----
 tools/perf/ui/gtk/hists.c                | 128 ++++++++++---
 tools/perf/ui/hist.c                     | 316 ++++++++++++++++---------------
 tools/perf/ui/stdio/hist.c               |   2 +
 tools/perf/util/evlist.c                 |   7 +-
 tools/perf/util/evlist.h                 |   1 +
 tools/perf/util/evsel.c                  |  25 +++
 tools/perf/util/evsel.h                  |  16 ++
 tools/perf/util/header.c                 | 164 ++++++++++++++++
 tools/perf/util/header.h                 |   2 +
 tools/perf/util/hist.c                   |  59 +++++-
 tools/perf/util/parse-events.c           |   1 +
 tools/perf/util/parse-events.h           |   1 +
 tools/perf/util/parse-events.y           |  10 +
 tools/perf/util/string.c                 |  18 ++
 tools/perf/util/symbol.h                 |   3 +-
 tools/perf/util/util.h                   |   1 +
 22 files changed, 840 insertions(+), 226 deletions(-)

-- 
1.7.11.7


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

* [PATCH 01/13] perf tools: Keep group information
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 02/13] perf tests: Add group test conditions Namhyung Kim
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Arnaldo Carvalho de Melo

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

Add a few of group-related field in struct perf_{evlist,evsel} so that
the group information in a evlist can be known easily.  It only counts
groups which have more than 1 members since leader-only groups are
treated as non-group events.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1355726345-29553-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c       |  7 ++++++-
 tools/perf/util/evlist.h       |  1 +
 tools/perf/util/evsel.h        |  6 ++++++
 tools/perf/util/parse-events.c |  1 +
 tools/perf/util/parse-events.h |  1 +
 tools/perf/util/parse-events.y | 10 ++++++++++
 6 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index dc8aee97a488..eddd5ebcd690 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -117,6 +117,9 @@ void __perf_evlist__set_leader(struct list_head *list)
 	struct perf_evsel *evsel, *leader;
 
 	leader = list_entry(list->next, struct perf_evsel, node);
+	evsel = list_entry(list->prev, struct perf_evsel, node);
+
+	leader->nr_members = evsel->idx - leader->idx + 1;
 
 	list_for_each_entry(evsel, list, node) {
 		if (evsel != leader)
@@ -126,8 +129,10 @@ void __perf_evlist__set_leader(struct list_head *list)
 
 void perf_evlist__set_leader(struct perf_evlist *evlist)
 {
-	if (evlist->nr_entries)
+	if (evlist->nr_entries) {
+		evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0;
 		__perf_evlist__set_leader(&evlist->entries);
+	}
 }
 
 int perf_evlist__add_default(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 457e2350d21d..73579a25a93e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -21,6 +21,7 @@ struct perf_evlist {
 	struct list_head entries;
 	struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
 	int		 nr_entries;
+	int		 nr_groups;
 	int		 nr_fds;
 	int		 nr_mmaps;
 	int		 mmap_len;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index c68d1b82e843..f5d22f12ccd8 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -73,6 +73,7 @@ struct perf_evsel {
 	bool 			needs_swap;
 	/* parse modifier helper */
 	int			exclude_GH;
+	int			nr_members;
 	struct perf_evsel	*leader;
 	char			*group_name;
 };
@@ -257,4 +258,9 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
 int perf_evsel__open_strerror(struct perf_evsel *evsel,
 			      struct perf_target *target,
 			      int err, char *msg, size_t size);
+
+static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
+{
+	return evsel->idx - evsel->leader->idx;
+}
 #endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 626c120f00da..64d663192495 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -885,6 +885,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
 	if (!ret) {
 		int entries = data.idx - evlist->nr_entries;
 		perf_evlist__splice_list_tail(evlist, &data.list, entries);
+		evlist->nr_groups += data.nr_groups;
 		return 0;
 	}
 
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index b7af80b8bdda..330b8896876b 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -65,6 +65,7 @@ struct parse_events__term {
 struct parse_events_data__events {
 	struct list_head list;
 	int idx;
+	int nr_groups;
 };
 
 struct parse_events_data__terms {
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 0f9914ae6bac..7f2d63afcf38 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -23,6 +23,14 @@ do { \
 		YYABORT; \
 } while (0)
 
+static inc_group_count(struct list_head *list,
+		       struct parse_events_data__events *data)
+{
+	/* Count groups only have more than 1 members */
+	if (!list_is_last(list->next, list))
+		data->nr_groups++;
+}
+
 %}
 
 %token PE_START_EVENTS PE_START_TERMS
@@ -123,6 +131,7 @@ PE_NAME '{' events '}'
 {
 	struct list_head *list = $3;
 
+	inc_group_count(list, _data);
 	parse_events__set_leader($1, list);
 	$$ = list;
 }
@@ -131,6 +140,7 @@ PE_NAME '{' events '}'
 {
 	struct list_head *list = $2;
 
+	inc_group_count(list, _data);
 	parse_events__set_leader(NULL, list);
 	$$ = list;
 }
-- 
1.7.11.7


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

* [PATCH 02/13] perf tests: Add group test conditions
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
  2013-01-15  7:31 ` [PATCH 01/13] perf tools: Keep group information Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 03/13] perf header: Add HEADER_GROUP_DESC feature Namhyung Kim
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Arnaldo Carvalho de Melo

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

As some new fields for handling groups added, check them to be sure to
have valid values in test__group* cases.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1355726345-29553-3-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/parse-events.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index e7eb708da32c..257d60f5cfc7 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -23,6 +23,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist)
 	struct perf_evsel *evsel = perf_evlist__first(evlist);
 
 	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
 	TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
 	TEST_ASSERT_VAL("wrong sample_type",
 		PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
@@ -35,6 +36,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
 	struct perf_evsel *evsel;
 
 	TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+	TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
 
 	list_for_each_entry(evsel, &evlist->entries, node) {
 		TEST_ASSERT_VAL("wrong type",
@@ -510,6 +512,7 @@ static int test__group1(struct perf_evlist *evlist)
 	struct perf_evsel *evsel, *leader;
 
 	TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
 
 	/* instructions:k */
 	evsel = leader = perf_evlist__first(evlist);
@@ -523,6 +526,8 @@ static int test__group1(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* cycles:upp */
 	evsel = perf_evsel__next(evsel);
@@ -537,6 +542,7 @@ static int test__group1(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	return 0;
 }
@@ -546,6 +552,7 @@ static int test__group2(struct perf_evlist *evlist)
 	struct perf_evsel *evsel, *leader;
 
 	TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
 
 	/* faults + :ku modifier */
 	evsel = leader = perf_evlist__first(evlist);
@@ -559,6 +566,8 @@ static int test__group2(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* cache-references + :u modifier */
 	evsel = perf_evsel__next(evsel);
@@ -572,6 +581,7 @@ static int test__group2(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	/* cycles:k */
 	evsel = perf_evsel__next(evsel);
@@ -594,6 +604,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
 	struct perf_evsel *evsel, *leader;
 
 	TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
 
 	/* group1 syscalls:sys_enter_open:H */
 	evsel = leader = perf_evlist__first(evlist);
@@ -610,6 +621,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
 	TEST_ASSERT_VAL("wrong group name",
 		!strcmp(leader->group_name, "group1"));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* group1 cycles:kppp */
 	evsel = perf_evsel__next(evsel);
@@ -625,6 +638,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
 	TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	/* group2 cycles + G modifier */
 	evsel = leader = perf_evsel__next(evsel);
@@ -640,6 +654,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
 	TEST_ASSERT_VAL("wrong group name",
 		!strcmp(leader->group_name, "group2"));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* group2 1:3 + G modifier */
 	evsel = perf_evsel__next(evsel);
@@ -652,6 +668,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	/* instructions:u */
 	evsel = perf_evsel__next(evsel);
@@ -674,6 +691,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
 	struct perf_evsel *evsel, *leader;
 
 	TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
 
 	/* cycles:u + p */
 	evsel = leader = perf_evlist__first(evlist);
@@ -689,6 +707,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
 	TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* instructions:kp + p */
 	evsel = perf_evsel__next(evsel);
@@ -703,6 +723,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	return 0;
 }
@@ -712,6 +733,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
 	struct perf_evsel *evsel, *leader;
 
 	TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
 
 	/* cycles + G */
 	evsel = leader = perf_evlist__first(evlist);
@@ -726,6 +748,8 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* instructions + G */
 	evsel = perf_evsel__next(evsel);
@@ -739,6 +763,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	/* cycles:G */
 	evsel = leader = perf_evsel__next(evsel);
@@ -753,6 +778,8 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
 	TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+	TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
 	/* instructions:G */
 	evsel = perf_evsel__next(evsel);
@@ -766,6 +793,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
 	TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+	TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
 	/* cycles */
 	evsel = perf_evsel__next(evsel);
-- 
1.7.11.7


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

* [PATCH 03/13] perf header: Add HEADER_GROUP_DESC feature
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
  2013-01-15  7:31 ` [PATCH 01/13] perf tools: Keep group information Namhyung Kim
  2013-01-15  7:31 ` [PATCH 02/13] perf tests: Add group test conditions Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 04/13] perf report: Make another loop for linking group hists Namhyung Kim
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Arnaldo Carvalho de Melo

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

Save group relationship information so that it can be restored when perf
report is running.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1355726345-29553-5-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |   3 +
 tools/perf/util/header.c    | 164 ++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h    |   2 +
 3 files changed, 169 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2ac690cad411..774c90713a53 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -486,6 +486,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		goto out_delete_session;
 	}
 
+	if (!evsel_list->nr_groups)
+		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
+
 	/*
 	 * perf_session__delete(session) will be called at perf_record__exit()
 	 */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index fccd69dbbbb9..b614c9638fd5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1082,6 +1082,52 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
 }
 
 /*
+ * File format:
+ *
+ * struct group_descs {
+ *	u32	nr_groups;
+ *	struct group_desc {
+ *		char	name[];
+ *		u32	leader_idx;
+ *		u32	nr_members;
+ *	}[nr_groups];
+ * };
+ */
+static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
+			    struct perf_evlist *evlist)
+{
+	u32 nr_groups = evlist->nr_groups;
+	struct perf_evsel *evsel;
+	int ret;
+
+	ret = do_write(fd, &nr_groups, sizeof(nr_groups));
+	if (ret < 0)
+		return ret;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		if (perf_evsel__is_group_leader(evsel) &&
+		    evsel->nr_members > 1) {
+			const char *name = evsel->group_name ?: "{anon_group}";
+			u32 leader_idx = evsel->idx;
+			u32 nr_members = evsel->nr_members;
+
+			ret = do_write_string(fd, name);
+			if (ret < 0)
+				return ret;
+
+			ret = do_write(fd, &leader_idx, sizeof(leader_idx));
+			if (ret < 0)
+				return ret;
+
+			ret = do_write(fd, &nr_members, sizeof(nr_members));
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+/*
  * default get_cpuid(): nothing gets recorded
  * actual implementation must be in arch/$(ARCH)/util/header.c
  */
@@ -1444,6 +1490,31 @@ error:
 	fprintf(fp, "# pmu mappings: unable to read\n");
 }
 
+static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
+			     FILE *fp)
+{
+	struct perf_session *session;
+	struct perf_evsel *evsel;
+	u32 nr = 0;
+
+	session = container_of(ph, struct perf_session, header);
+
+	list_for_each_entry(evsel, &session->evlist->entries, node) {
+		if (perf_evsel__is_group_leader(evsel) &&
+		    evsel->nr_members > 1) {
+			fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
+				perf_evsel__name(evsel));
+
+			nr = evsel->nr_members - 1;
+		} else if (nr) {
+			fprintf(fp, ",%s", perf_evsel__name(evsel));
+
+			if (--nr == 0)
+				fprintf(fp, "}\n");
+		}
+	}
+}
+
 static int __event_process_build_id(struct build_id_event *bev,
 				    char *filename,
 				    struct perf_session *session)
@@ -1958,6 +2029,98 @@ error:
 	return -1;
 }
 
+static int process_group_desc(struct perf_file_section *section __maybe_unused,
+			      struct perf_header *ph, int fd,
+			      void *data __maybe_unused)
+{
+	size_t ret = -1;
+	u32 i, nr, nr_groups;
+	struct perf_session *session;
+	struct perf_evsel *evsel, *leader = NULL;
+	struct group_desc {
+		char *name;
+		u32 leader_idx;
+		u32 nr_members;
+	} *desc;
+
+	if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups))
+		return -1;
+
+	if (ph->needs_swap)
+		nr_groups = bswap_32(nr_groups);
+
+	ph->env.nr_groups = nr_groups;
+	if (!nr_groups) {
+		pr_debug("group desc not available\n");
+		return 0;
+	}
+
+	desc = calloc(nr_groups, sizeof(*desc));
+	if (!desc)
+		return -1;
+
+	for (i = 0; i < nr_groups; i++) {
+		desc[i].name = do_read_string(fd, ph);
+		if (!desc[i].name)
+			goto out_free;
+
+		if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32))
+			goto out_free;
+
+		if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32))
+			goto out_free;
+
+		if (ph->needs_swap) {
+			desc[i].leader_idx = bswap_32(desc[i].leader_idx);
+			desc[i].nr_members = bswap_32(desc[i].nr_members);
+		}
+	}
+
+	/*
+	 * Rebuild group relationship based on the group_desc
+	 */
+	session = container_of(ph, struct perf_session, header);
+	session->evlist->nr_groups = nr_groups;
+
+	i = nr = 0;
+	list_for_each_entry(evsel, &session->evlist->entries, node) {
+		if (evsel->idx == (int) desc[i].leader_idx) {
+			evsel->leader = evsel;
+			/* {anon_group} is a dummy name */
+			if (strcmp(desc[i].name, "{anon_group}"))
+				evsel->group_name = desc[i].name;
+			evsel->nr_members = desc[i].nr_members;
+
+			if (i >= nr_groups || nr > 0) {
+				pr_debug("invalid group desc\n");
+				goto out_free;
+			}
+
+			leader = evsel;
+			nr = evsel->nr_members - 1;
+			i++;
+		} else if (nr) {
+			/* This is a group member */
+			evsel->leader = leader;
+
+			nr--;
+		}
+	}
+
+	if (i != nr_groups || nr != 0) {
+		pr_debug("invalid group desc\n");
+		goto out_free;
+	}
+
+	ret = 0;
+out_free:
+	while ((int) --i >= 0)
+		free(desc[i].name);
+	free(desc);
+
+	return ret;
+}
+
 struct feature_ops {
 	int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
 	void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1997,6 +2160,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),
 	FEAT_OPA(HEADER_BRANCH_STACK,	branch_stack),
 	FEAT_OPP(HEADER_PMU_MAPPINGS,	pmu_mappings),
+	FEAT_OPP(HEADER_GROUP_DESC,	group_desc),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 20f0344accb1..c9fc55cada6d 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -29,6 +29,7 @@ enum {
 	HEADER_NUMA_TOPOLOGY,
 	HEADER_BRANCH_STACK,
 	HEADER_PMU_MAPPINGS,
+	HEADER_GROUP_DESC,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
@@ -79,6 +80,7 @@ struct perf_session_env {
 	char			*numa_nodes;
 	int			nr_pmu_mappings;
 	char			*pmu_mappings;
+	int			nr_groups;
 };
 
 struct perf_header {
-- 
1.7.11.7


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

* [PATCH 04/13] perf report: Make another loop for linking group hists
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (2 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 03/13] perf header: Add HEADER_GROUP_DESC feature Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 05/13] perf hists: Resort hist entries using group members for output Namhyung Kim
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Arnaldo Carvalho de Melo

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

Now the event grouping viewing requires linking all member hists in a
group to the leader's.  Thus hists__output_resort should be called after
linking all events in evlist.

Introduce symbol_conf.event_group flag to determine whether the feature
is enabled or not.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1355726345-29553-6-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-report.c | 13 ++++++++++++-
 tools/perf/util/symbol.h    |  3 ++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 47a864478543..fd2503a5f876 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -416,8 +416,16 @@ static int __cmd_report(struct perf_report *rep)
 			hists->symbol_filter_str = rep->symbol_filter_str;
 
 		hists__collapse_resort(hists);
-		hists__output_resort(hists);
 		nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
+
+		/* Non-group events are considered as leader */
+		if (symbol_conf.event_group &&
+		    !perf_evsel__is_group_leader(pos)) {
+			struct hists *leader_hists = &pos->leader->hists;
+
+			hists__match(leader_hists, hists);
+			hists__link(leader_hists, hists);
+		}
 	}
 
 	if (nr_samples == 0) {
@@ -425,6 +433,9 @@ static int __cmd_report(struct perf_report *rep)
 		goto out_delete;
 	}
 
+	list_for_each_entry(pos, &session->evlist->entries, node)
+		hists__output_resort(&pos->hists);
+
 	if (use_browser > 0) {
 		if (use_browser == 1) {
 			perf_evlist__tui_browse_hists(session->evlist, help,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d97377ac2f16..b62ca37c4b77 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -96,7 +96,8 @@ struct symbol_conf {
 			initialized,
 			kptr_restrict,
 			annotate_asm_raw,
-			annotate_src;
+			annotate_src,
+			event_group;
 	const char	*vmlinux_name,
 			*kallsyms_name,
 			*source_prefix,
-- 
1.7.11.7


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

* [PATCH 05/13] perf hists: Resort hist entries using group members for output
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (3 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 04/13] perf report: Make another loop for linking group hists Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15 18:29   ` Arnaldo Carvalho de Melo
  2013-01-15  7:31 ` [PATCH 06/13] perf ui/hist: Add support for event group view Namhyung Kim
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Arnaldo Carvalho de Melo

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

When event group is enabled, sorting hist entries on periods for output
should consider groups members' period also.  To do that, build period
table using link/pair information and compare the table.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1355726345-29553-7-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel.h |  2 ++
 tools/perf/util/hist.c  | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index f5d22f12ccd8..24225d728ba4 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -78,6 +78,8 @@ struct perf_evsel {
 	char			*group_name;
 };
 
+#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
+
 struct cpu_map;
 struct thread_map;
 struct perf_evlist;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 8170a3d11ffa..f855941bebea 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -4,6 +4,7 @@
 #include "hist.h"
 #include "session.h"
 #include "sort.h"
+#include "evsel.h"
 #include <math.h>
 
 static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -540,6 +541,62 @@ void hists__collapse_resort_threaded(struct hists *hists)
  * reverse the map, sort on period.
  */
 
+static int period_cmp(u64 period_a, u64 period_b)
+{
+	if (period_a > period_b)
+		return 1;
+	if (period_a < period_b)
+		return -1;
+	return 0;
+}
+
+static int hist_entry__sort_on_period(struct hist_entry *a,
+				      struct hist_entry *b)
+{
+	int ret;
+	int i, nr_members;
+	struct perf_evsel *evsel;
+	struct hist_entry *pair;
+	u64 *periods_a, *periods_b;
+
+	ret = period_cmp(a->stat.period, b->stat.period);
+	if (ret || !symbol_conf.event_group)
+		return ret;
+
+	evsel = hists_to_evsel(a->hists);
+	nr_members = evsel->nr_members;
+	if (nr_members <= 1)
+		return ret;
+
+	periods_a = zalloc(sizeof(periods_a) * nr_members);
+	periods_b = zalloc(sizeof(periods_b) * nr_members);
+
+	if (!periods_a || !periods_b)
+		goto out;
+
+	list_for_each_entry(pair, &a->pairs.head, pairs.node) {
+		evsel = hists_to_evsel(pair->hists);
+		periods_a[perf_evsel__group_idx(evsel)] = pair->stat.period;
+	}
+
+	list_for_each_entry(pair, &b->pairs.head, pairs.node) {
+		evsel = hists_to_evsel(pair->hists);
+		periods_b[perf_evsel__group_idx(evsel)] = pair->stat.period;
+	}
+
+	for (i = 1; i < nr_members; i++) {
+		ret = period_cmp(periods_a[i], periods_b[i]);
+		if (ret)
+			break;
+	}
+
+out:
+	free(periods_a);
+	free(periods_b);
+
+	return ret;
+}
+
 static void __hists__insert_output_entry(struct rb_root *entries,
 					 struct hist_entry *he,
 					 u64 min_callchain_hits)
@@ -556,7 +613,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
 		parent = *p;
 		iter = rb_entry(parent, struct hist_entry, rb_node);
 
-		if (he->stat.period > iter->stat.period)
+		if (hist_entry__sort_on_period(he, iter) > 0)
 			p = &(*p)->rb_left;
 		else
 			p = &(*p)->rb_right;
-- 
1.7.11.7


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

* [PATCH 06/13] perf ui/hist: Add support for event group view
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (4 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 05/13] perf hists: Resort hist entries using group members for output Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15 18:31   ` Arnaldo Carvalho de Melo
  2013-01-15  7:31 ` [PATCH 07/13] perf hist browser: " Namhyung Kim
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

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

Show group members' overhead also when showing the leader's if event
group is enabled.  Use macro for defining hpp functions which looks
almost identical.

Thanks to Arnaldo for suggesting a better way to print group members
without allocating temporary array.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/hist.c       | 311 +++++++++++++++++++++++----------------------
 tools/perf/ui/stdio/hist.c |   2 +
 2 files changed, 164 insertions(+), 149 deletions(-)

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 1889c12ca81f..ec14335a9713 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -3,151 +3,190 @@
 #include "../util/hist.h"
 #include "../util/util.h"
 #include "../util/sort.h"
-
+#include "../util/evsel.h"
 
 /* hist period print (hpp) functions */
-static int hpp__header_overhead(struct perf_hpp *hpp)
-{
-	return scnprintf(hpp->buf, hpp->size, "Overhead");
-}
 
-static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
-{
-	return 8;
-}
+typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...);
 
-static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
+static int __hpp__percent_fmt(struct perf_hpp *hpp, struct hist_entry *he,
+			      u64 (*get_field)(struct hist_entry *),
+			      const char *fmt, hpp_snprint_fn print_fn)
 {
+	int ret;
+	double percent = 0.0;
 	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period / hists->stats.total_period;
 
-	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
-}
+	if (hists->stats.total_period)
+		percent = 100.0 * get_field(he) / hists->stats.total_period;
 
-static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period / hists->stats.total_period;
-	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
+	ret = print_fn(hpp->buf, hpp->size, fmt, percent);
 
-	return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
+	if (symbol_conf.event_group) {
+		int prev_idx, idx_delta, i;
+		struct perf_evsel *evsel = hists_to_evsel(hists);
+		struct hist_entry *pair;
+		int nr_members = evsel->nr_members;
 
-static int hpp__header_overhead_sys(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
+		if (nr_members <= 1)
+			return ret;
 
-	return scnprintf(hpp->buf, hpp->size, fmt, "sys");
-}
+		prev_idx = perf_evsel__group_idx(evsel);
 
-static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
-{
-	return 7;
-}
+		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+			u64 period = get_field(pair);
+			u64 total = pair->hists->stats.total_period;
 
-static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
+			if (!total)
+				continue;
 
-	return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
-}
+			evsel = hists_to_evsel(pair->hists);
+			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
 
-static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
-	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
+			for (i = 0; i < idx_delta; i++) {
+				ret += print_fn(hpp->buf + ret, hpp->size - ret,
+						fmt, 0.0);
+			}
 
-	return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
+			ret += print_fn(hpp->buf + ret, hpp->size - ret,
+					fmt, 100.0 * period / total);
 
-static int hpp__header_overhead_us(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
+			prev_idx += 1 + idx_delta;
+		}
 
-	return scnprintf(hpp->buf, hpp->size, fmt, "user");
-}
+		idx_delta = nr_members - prev_idx - 1;
 
-static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
-{
-	return 7;
+		for (i = 0; i < idx_delta; i++) {
+			ret += print_fn(hpp->buf + ret, hpp->size - ret,
+					fmt, 0.0);
+		}
+	}
+	return ret;
 }
 
-static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
+static int __hpp__raw_fmt(struct perf_hpp *hpp, struct hist_entry *he,
+			  u64 (*get_field)(struct hist_entry *),
+			  const char *fmt, hpp_snprint_fn print_fn)
 {
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
-
-	return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
-}
+	int ret;
+	ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he));
 
-static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
-	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
+	if (symbol_conf.event_group) {
+		int prev_idx, idx_delta, i;
+		struct perf_evsel *evsel = hists_to_evsel(he->hists);
+		struct hist_entry *pair;
+		int nr_members = evsel->nr_members;
 
-	return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
+		if (nr_members <= 1)
+			return ret;
 
-static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
-{
-	return scnprintf(hpp->buf, hpp->size, "guest sys");
-}
+		prev_idx = perf_evsel__group_idx(evsel);
 
-static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
-{
-	return 9;
-}
+		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+			evsel = hists_to_evsel(pair->hists);
+			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
 
-static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
-					 struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
+			for (i = 0; i < idx_delta; i++) {
+				ret += print_fn(hpp->buf + ret, hpp->size - ret,
+						fmt, 0.0);
+			}
 
-	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
-}
+			ret += print_fn(hpp->buf + ret, hpp->size - ret,
+					fmt, get_field(pair));
 
-static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
-					 struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
-	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
+			prev_idx += 1 + idx_delta;
+		}
 
-static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
-{
-	return scnprintf(hpp->buf, hpp->size, "guest usr");
-}
+		idx_delta = nr_members - prev_idx - 1;
 
-static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
-{
-	return 9;
+		for (i = 0; i < idx_delta; i++) {
+			ret += print_fn(hpp->buf + ret, hpp->size - ret,
+					fmt, 0.0);
+		}
+	}
+	return ret;
 }
 
-static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
-					struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
-
-	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
-}
 
-static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
-					struct hist_entry *he)
-{
-	struct hists *hists = he->hists;
-	double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
-	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
+#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) 		\
+static int hpp__header_##_type(struct perf_hpp *hpp)			\
+{									\
+	int len = _min_width;						\
+									\
+	if (symbol_conf.event_group) {					\
+		struct perf_evsel *evsel = hpp->ptr;			\
+									\
+		len = max(len, evsel->nr_members * _unit_width);	\
+	}								\
+	return scnprintf(hpp->buf, hpp->size, "%*s", len, _str);	\
+}
+
+#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) 			\
+static int hpp__width_##_type(struct perf_hpp *hpp)			\
+{									\
+	int len = _min_width;						\
+									\
+	if (symbol_conf.event_group) {					\
+		struct perf_evsel *evsel = hpp->ptr;			\
+									\
+		len = max(len, evsel->nr_members * _unit_width);	\
+	}								\
+	return len;							\
+}
+
+#define __HPP_COLOR_PERCENT_FN(_type, _field)					\
+static u64 he_get_##_field(struct hist_entry *he)				\
+{										\
+	return he->stat._field;							\
+}										\
+										\
+static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
+{										\
+	return __hpp__percent_fmt(hpp, he, he_get_##_field, " %6.2f%%",		\
+				  (hpp_snprint_fn)percent_color_snprintf); 	\
+}
+
+#define __HPP_ENTRY_PERCENT_FN(_type, _field)					\
+static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
+{										\
+	const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%";		\
+	return __hpp__percent_fmt(hpp, he, he_get_##_field, fmt,		\
+				  scnprintf);					\
+}
+
+#define __HPP_ENTRY_RAW_FN(_type, _field)					\
+static u64 he_get_raw_##_field(struct hist_entry *he)				\
+{										\
+	return he->stat._field;							\
+}										\
+										\
+static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
+{										\
+	const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64;	\
+	return __hpp__raw_fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf);	\
+}
+
+#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width)	\
+__HPP_HEADER_FN(_type, _str, _min_width, _unit_width)			\
+__HPP_WIDTH_FN(_type, _min_width, _unit_width)				\
+__HPP_COLOR_PERCENT_FN(_type, _field)					\
+__HPP_ENTRY_PERCENT_FN(_type, _field)
+
+#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width)	\
+__HPP_HEADER_FN(_type, _str, _min_width, _unit_width)			\
+__HPP_WIDTH_FN(_type, _min_width, _unit_width)				\
+__HPP_ENTRY_RAW_FN(_type, _field)
+
+
+HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8)
+HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8)
+HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8)
+HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8)
+HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
+
+HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12)
+HPP_RAW_FNS(period, "Period", period, 12, 12)
 
-	return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
 
 static int hpp__header_baseline(struct perf_hpp *hpp)
 {
@@ -179,7 +218,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 {
 	double percent = baseline_percent(he);
 
-	if (hist_entry__has_pairs(he))
+	if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
 		return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
 	else
 		return scnprintf(hpp->buf, hpp->size, "        ");
@@ -196,44 +235,6 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 		return scnprintf(hpp->buf, hpp->size, "            ");
 }
 
-static int hpp__header_samples(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
-}
-
-static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
-{
-	return 11;
-}
-
-static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
-
-	return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
-}
-
-static int hpp__header_period(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Period");
-}
-
-static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
-{
-	return 12;
-}
-
-static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
-
-	return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
-}
-
 static int hpp__header_period_baseline(struct perf_hpp *hpp)
 {
 	const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
@@ -254,6 +255,7 @@ static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *h
 
 	return scnprintf(hpp->buf, hpp->size, fmt, period);
 }
+
 static int hpp__header_delta(struct perf_hpp *hpp)
 {
 	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
@@ -408,9 +410,20 @@ struct perf_hpp_fmt perf_hpp__format[] = {
 
 LIST_HEAD(perf_hpp__list);
 
+
 #undef HPP__COLOR_PRINT_FNS
 #undef HPP__PRINT_FNS
 
+#undef HPP_PERCENT_FNS
+#undef HPP_RAW_FNS
+
+#undef __HPP_HEADER_FN
+#undef __HPP_WIDTH_FN
+#undef __HPP_COLOR_PERCENT_FN
+#undef __HPP_ENTRY_PERCENT_FN
+#undef __HPP_ENTRY_RAW_FN
+
+
 void perf_hpp__init(void)
 {
 	if (symbol_conf.show_cpu_utilization) {
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index f9798298e3e0..ff1f60cf442e 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -3,6 +3,7 @@
 #include "../../util/util.h"
 #include "../../util/hist.h"
 #include "../../util/sort.h"
+#include "../../util/evsel.h"
 
 
 static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -347,6 +348,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 	struct perf_hpp dummy_hpp = {
 		.buf	= bf,
 		.size	= sizeof(bf),
+		.ptr	= hists_to_evsel(hists),
 	};
 	bool first = true;
 
-- 
1.7.11.7


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

* [PATCH 07/13] perf hist browser: Add support for event group view
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (5 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 06/13] perf ui/hist: Add support for event group view Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15 18:32   ` Arnaldo Carvalho de Melo
  2013-01-15  7:31 ` [PATCH 08/13] perf gtk/browser: " Namhyung Kim
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

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

Show group members' overhead also when showing the leader's if event
group is enabled.  Use macro for defining hpp functions which looks
almost identical.

Also move coloring logic into the hpp function so that each value can
be colored independently.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/browsers/hists.c | 153 ++++++++++++++++++++++++++++++++---------
 tools/perf/ui/hist.c           |   5 +-
 2 files changed, 126 insertions(+), 32 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 57b82c26cd05..65e6c005f8e9 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -567,23 +567,126 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
 	return row - first_row;
 }
 
-#define HPP__COLOR_FN(_name, _field)					\
-static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp,	\
-					     struct hist_entry *he)	\
+struct hpp_arg {
+	struct ui_browser *b;
+	char folded_sign;
+	bool current_entry;
+};
+
+static int hist_browser__hpp_color_callchain(struct hpp_arg *arg)
+{
+	if (!symbol_conf.use_callchain)
+		return 0;
+
+	slsmg_printf("%c ", arg->folded_sign);
+	return 2;
+}
+
+static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
+			    u64 (*get_field)(struct hist_entry *),
+			    int (*callchain_cb)(struct hpp_arg *))
+{
+	int ret = 0;
+	double percent = 0.0;
+	struct hists *hists = he->hists;
+	struct hpp_arg *arg = hpp->ptr;
+
+	if (hists->stats.total_period)
+		percent = 100.0 * get_field(he) / hists->stats.total_period;
+
+	ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
+
+	if (callchain_cb)
+		ret += callchain_cb(arg);
+
+	ret += scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
+	slsmg_printf("%s", hpp->buf);
+
+	if (symbol_conf.event_group) {
+		int prev_idx, idx_delta, i;
+		struct perf_evsel *evsel = hists_to_evsel(hists);
+		struct hist_entry *pair;
+		int nr_members = evsel->nr_members;
+
+		if (nr_members <= 1)
+			goto out;
+
+		prev_idx = perf_evsel__group_idx(evsel);
+
+		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+			u64 period = get_field(pair);
+			u64 total = pair->hists->stats.total_period;
+
+			if (!total)
+				continue;
+
+			evsel = hists_to_evsel(pair->hists);
+			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
+
+			for (i = 0; i < idx_delta; i++) {
+				ui_browser__set_percent_color(arg->b, 0.0,
+							arg->current_entry);
+				ret += scnprintf(hpp->buf, hpp->size,
+						 " %6.2f%%", 0.0);
+				slsmg_printf("%s", hpp->buf);
+			}
+
+			percent = 100.0 * period / total;
+			ui_browser__set_percent_color(arg->b, percent,
+						      arg->current_entry);
+			ret += scnprintf(hpp->buf, hpp->size,
+					 " %6.2f%%", percent);
+			slsmg_printf("%s", hpp->buf);
+
+			prev_idx += 1 + idx_delta;
+		}
+
+		idx_delta = nr_members - prev_idx - 1;
+
+		for (i = 0; i < idx_delta; i++) {
+			ui_browser__set_percent_color(arg->b, 0.0,
+						      arg->current_entry);
+			ret += scnprintf(hpp->buf, hpp->size, " %6.2f%%", 0.0);
+			slsmg_printf("%s", hpp->buf);
+		}
+	}
+out:
+	if (!arg->current_entry || !arg->b->navkeypressed)
+		ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
+
+	return ret;
+}
+
+static u64 __hpp_get_period(struct hist_entry *he)
+{
+	return he->stat.period;
+}
+
+static int hist_browser__hpp_color_overhead(struct perf_hpp *hpp,
+					    struct hist_entry *he)
+{
+	return __hpp__color_fmt(hpp, he, __hpp_get_period,
+				hist_browser__hpp_color_callchain);
+}
+
+#define __HPP_COLOR_PERCENT_FN(_type, _field)				\
+static u64 __hpp_get_##_field(struct hist_entry *he)			\
+{									\
+	return he->stat._field;						\
+}									\
+									\
+static int hist_browser__hpp_color_##_type(struct perf_hpp *hpp,	\
+					   struct hist_entry *he)	\
 {									\
-	struct hists *hists = he->hists;				\
-	double percent = 100.0 * he->stat._field / hists->stats.total_period; \
-	*(double *)hpp->ptr = percent;					\
-	return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);	\
+	return __hpp__color_fmt(hpp, he, __hpp_get_##_field, NULL);	\
 }
 
-HPP__COLOR_FN(overhead, period)
-HPP__COLOR_FN(overhead_sys, period_sys)
-HPP__COLOR_FN(overhead_us, period_us)
-HPP__COLOR_FN(overhead_guest_sys, period_guest_sys)
-HPP__COLOR_FN(overhead_guest_us, period_guest_us)
+__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
+__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
+__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
+__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
 
-#undef HPP__COLOR_FN
+#undef __HPP_COLOR_PERCENT_FN
 
 void hist_browser__init_hpp(void)
 {
@@ -608,7 +711,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 				    unsigned short row)
 {
 	char s[256];
-	double percent;
 	int printed = 0;
 	int width = browser->b.width;
 	char folded_sign = ' ';
@@ -628,11 +730,16 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 	}
 
 	if (row_offset == 0) {
+		struct hpp_arg arg = {
+			.b		= &browser->b,
+			.folded_sign	= folded_sign,
+			.current_entry	= current_entry,
+		};
 		struct perf_hpp hpp = {
 			.buf		= s,
 			.size		= sizeof(s),
+			.ptr		= &arg,
 		};
-		int i = 0;
 
 		ui_browser__gotorc(&browser->b, row, 0);
 
@@ -645,27 +752,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 			first = false;
 
 			if (fmt->color) {
-				hpp.ptr = &percent;
-				/* It will set percent for us. See HPP__COLOR_FN above. */
 				width -= fmt->color(&hpp, entry);
-
-				ui_browser__set_percent_color(&browser->b, percent, current_entry);
-
-				if (!i && symbol_conf.use_callchain) {
-					slsmg_printf("%c ", folded_sign);
-					width -= 2;
-				}
-
-				slsmg_printf("%s", s);
-
-				if (!current_entry || !browser->b.navkeypressed)
-					ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
 			} else {
 				width -= fmt->entry(&hpp, entry);
 				slsmg_printf("%s", s);
 			}
-
-			i++;
 		}
 
 		/* The scroll bar isn't being used */
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index ec14335a9713..be9152cd4c76 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -521,12 +521,15 @@ unsigned int hists__sort_list_width(struct hists *hists)
 	struct perf_hpp_fmt *fmt;
 	struct sort_entry *se;
 	int i = 0, ret = 0;
+	struct perf_hpp dummy_hpp = {
+		.ptr	= hists_to_evsel(hists),
+	};
 
 	perf_hpp__for_each_format(fmt) {
 		if (i)
 			ret += 2;
 
-		ret += fmt->width(NULL);
+		ret += fmt->width(&dummy_hpp);
 	}
 
 	list_for_each_entry(se, &hist_entry__sort_list, list)
-- 
1.7.11.7


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

* [PATCH 08/13] perf gtk/browser: Add support for event group view
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (6 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 07/13] perf hist browser: " Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15 18:34   ` Arnaldo Carvalho de Melo
  2013-01-15  7:31 ` [PATCH 09/13] perf gtk/browser: Trim column header string when event group enabled Namhyung Kim
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

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

Show group members' overhead also when showing the leader's if event
group is enabled.  Use macro for defining hpp functions which looks
almost identical.

Unlike other hpp backend, GTK+ needs to print dummy 0.00% output since
it's displayed with variable width fonts.  So that simply skipping
with %*s trick won't work well here.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/gtk/hists.c | 114 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 92 insertions(+), 22 deletions(-)

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index c03da79d524f..a4d951ea919a 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -8,32 +8,102 @@
 
 #define MAX_COLUMNS			32
 
-#define HPP__COLOR_FN(_name, _field)						\
-static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,			\
-					 struct hist_entry *he)			\
+static int perf_gtk__percent_color_snprintf(char *buf, size_t size,
+					    double percent)
+{
+	int ret = 0;
+	const char *markup;
+
+	markup = perf_gtk__get_percent_color(percent);
+	if (markup)
+		ret += scnprintf(buf, size, markup);
+
+	ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent);
+
+	if (markup)
+		ret += scnprintf(buf + ret, size - ret, "</span>");
+
+	return ret;
+}
+
+
+static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
+			    u64 (*get_field)(struct hist_entry *))
+{
+	int ret;
+	double percent = 0.0;
+	struct hists *hists = he->hists;
+
+	if (hists->stats.total_period)
+		percent = 100.0 * get_field(he) / hists->stats.total_period;
+
+	ret = perf_gtk__percent_color_snprintf(hpp->buf, hpp->size, percent);
+
+	if (symbol_conf.event_group) {
+		int prev_idx, idx_delta;
+		struct perf_evsel *evsel = hists_to_evsel(hists);
+		struct hist_entry *pair;
+		int nr_members = evsel->nr_members;
+
+		if (nr_members <= 1)
+			return ret;
+
+		prev_idx = perf_evsel__group_idx(evsel);
+
+		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+			u64 period = get_field(pair);
+			u64 total = pair->hists->stats.total_period;
+
+			evsel = hists_to_evsel(pair->hists);
+			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
+
+			while (idx_delta--) {
+				ret += scnprintf(hpp->buf + ret, hpp->size -ret, " ");
+				ret += perf_gtk__percent_color_snprintf(hpp->buf + ret,
+									hpp->size - ret,
+									0.0);
+			}
+
+			percent = 100.0 * period / total;
+			ret += scnprintf(hpp->buf + ret, hpp->size -ret, " ");
+			ret += perf_gtk__percent_color_snprintf(hpp->buf + ret,
+								hpp->size - ret,
+								percent);
+
+			prev_idx = perf_evsel__group_idx(evsel);
+		}
+
+		idx_delta = nr_members - prev_idx - 1;
+
+		while (idx_delta--) {
+			ret += scnprintf(hpp->buf + ret, hpp->size -ret, " ");
+			ret += perf_gtk__percent_color_snprintf(hpp->buf + ret,
+								hpp->size - ret,
+								0.0);
+		}
+	}
+	return ret;
+}
+
+#define __HPP_COLOR_PERCENT_FN(_type, _field)					\
+static u64 he_get_##_field(struct hist_entry *he)				\
 {										\
-	struct hists *hists = he->hists;					\
-	double percent = 100.0 * he->stat._field / hists->stats.total_period;	\
-	const char *markup;							\
-	int ret = 0;								\
+	return he->stat._field;							\
+}										\
 										\
-	markup = perf_gtk__get_percent_color(percent);				\
-	if (markup)								\
-		ret += scnprintf(hpp->buf, hpp->size, "%s", markup);		\
-	ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); 	\
-	if (markup)								\
-		ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); 	\
-										\
-	return ret;								\
+static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp,			\
+				       struct hist_entry *he)			\
+{										\
+	return __hpp__color_fmt(hpp, he, he_get_##_field);			\
 }
 
-HPP__COLOR_FN(overhead, period)
-HPP__COLOR_FN(overhead_sys, period_sys)
-HPP__COLOR_FN(overhead_us, period_us)
-HPP__COLOR_FN(overhead_guest_sys, period_guest_sys)
-HPP__COLOR_FN(overhead_guest_us, period_guest_us)
+__HPP_COLOR_PERCENT_FN(overhead, period)
+__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
+__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
+__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
+__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
 
-#undef HPP__COLOR_FN
+#undef __HPP_COLOR_PERCENT_FN
 
 
 void perf_gtk__init_hpp(void)
@@ -70,6 +140,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 	struct perf_hpp hpp = {
 		.buf		= s,
 		.size		= sizeof(s),
+		.ptr		= hists_to_evsel(hists),
 	};
 
 	nr_cols = 0;
@@ -94,7 +165,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 
 	perf_hpp__for_each_format(fmt) {
 		fmt->header(&hpp);
-
 		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
 							    -1, s,
 							    renderer, "markup",
-- 
1.7.11.7


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

* [PATCH 09/13] perf gtk/browser: Trim column header string when event group enabled
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (7 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 08/13] perf gtk/browser: " Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 10/13] perf report: Bypass non-leader events when event group is enabled Namhyung Kim
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg, Feng Tang

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

When event group feature is enabled, each column header is expanded to
match with the whole group column width.  But this is not needed for
GTK+ browser since it usually use variable-width fonts.  So trim it.

As we have ltrim() implementation in builtin-script.c move it to the
more generic location of util/string.c.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Feng Tang <feng.tang@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-script.c | 12 ------------
 tools/perf/ui/gtk/hists.c   |  2 +-
 tools/perf/util/string.c    | 18 ++++++++++++++++++
 tools/perf/util/util.h      |  1 +
 4 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3314ef2ec83e..fee4c9a8aee5 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -909,18 +909,6 @@ static const char *ends_with(const char *str, const char *suffix)
 	return NULL;
 }
 
-static char *ltrim(char *str)
-{
-	int len = strlen(str);
-
-	while (len && isspace(*str)) {
-		len--;
-		str++;
-	}
-
-	return str;
-}
-
 static int read_script_info(struct script_desc *desc, const char *filename)
 {
 	char line[BUFSIZ], *p;
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index a4d951ea919a..8ab2c492a6fd 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -166,7 +166,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 	perf_hpp__for_each_format(fmt) {
 		fmt->header(&hpp);
 		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-							    -1, s,
+							    -1, ltrim(s),
 							    renderer, "markup",
 							    col_idx++, NULL);
 	}
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 346707df04b9..29c7b2cb2521 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -332,6 +332,24 @@ char *strxfrchar(char *s, char from, char to)
 }
 
 /**
+ * ltrim - Removes leading whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Return pointer to the first non-whitespace character in @s.
+ */
+char *ltrim(char *s)
+{
+	int len = strlen(s);
+
+	while (len && isspace(*s)) {
+		len--;
+		s++;
+	}
+
+	return s;
+}
+
+/**
  * rtrim - Removes trailing whitespace from @s.
  * @s: The string to be stripped.
  *
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index ec5de5e3330c..09b4c26b71aa 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -265,6 +265,7 @@ bool is_power_of_2(unsigned long n)
 size_t hex_width(u64 v);
 int hex2u64(const char *ptr, u64 *val);
 
+char *ltrim(char *s);
 char *rtrim(char *s);
 
 void dump_stack(void);
-- 
1.7.11.7


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

* [PATCH 10/13] perf report: Bypass non-leader events when event group is enabled
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (8 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 09/13] perf gtk/browser: Trim column header string when event group enabled Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 11/13] perf report: Show group description " Namhyung Kim
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

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

Since we have all necessary information in the leader events and
other members don't, bypass members.  Member events will be shown
along with the leaders if event group is enabled.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Pekka Enberg <penberg@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-report.c    |  4 ++++
 tools/perf/ui/browsers/hists.c | 41 +++++++++++++++++++++++++++++++++++------
 tools/perf/ui/gtk/hists.c      |  4 ++++
 3 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index fd2503a5f876..9cc768ecacad 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -319,6 +319,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 		struct hists *hists = &pos->hists;
 		const char *evname = perf_evsel__name(pos);
 
+		if (symbol_conf.event_group &&
+		    !perf_evsel__is_group_leader(pos))
+			continue;
+
 		hists__fprintf_nr_sample_events(hists, evname, stdout);
 		hists__fprintf(hists, true, 0, 0, stdout);
 		fprintf(stdout, "\n\n");
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 65e6c005f8e9..17c1753d5fe1 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1699,8 +1699,19 @@ out:
 	return key;
 }
 
+static bool filter_group_entries(struct ui_browser *self __maybe_unused,
+				 void *entry)
+{
+	struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
+
+	if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel))
+		return true;
+
+	return false;
+}
+
 static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
-					   const char *help,
+					   int nr_entries, const char *help,
 					   struct hist_browser_timer *hbt,
 					   struct perf_session_env *env)
 {
@@ -1711,7 +1722,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
 			.refresh    = ui_browser__list_head_refresh,
 			.seek	    = ui_browser__list_head_seek,
 			.write	    = perf_evsel_menu__write,
-			.nr_entries = evlist->nr_entries,
+			.filter	    = filter_group_entries,
+			.nr_entries = nr_entries,
 			.priv	    = evlist,
 		},
 		.env = env,
@@ -1727,20 +1739,37 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
 			menu.b.width = line_len;
 	}
 
-	return perf_evsel_menu__run(&menu, evlist->nr_entries, help, hbt);
+	return perf_evsel_menu__run(&menu, nr_entries, help, hbt);
 }
 
 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
 				  struct hist_browser_timer *hbt,
 				  struct perf_session_env *env)
 {
-	if (evlist->nr_entries == 1) {
+	int nr_entries = evlist->nr_entries;
+
+single_entry:
+	if (nr_entries == 1) {
 		struct perf_evsel *first = list_entry(evlist->entries.next,
 						      struct perf_evsel, node);
 		const char *ev_name = perf_evsel__name(first);
-		return perf_evsel__hists_browse(first, evlist->nr_entries, help,
+
+		return perf_evsel__hists_browse(first, nr_entries, help,
 						ev_name, false, hbt, env);
 	}
 
-	return __perf_evlist__tui_browse_hists(evlist, help, hbt, env);
+	if (symbol_conf.event_group) {
+		struct perf_evsel *pos;
+
+		nr_entries = 0;
+		list_for_each_entry(pos, &evlist->entries, node)
+			if (perf_evsel__is_group_leader(pos))
+				nr_entries++;
+
+		if (nr_entries == 1)
+			goto single_entry;
+	}
+
+	return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
+					       hbt, env);
 }
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 8ab2c492a6fd..d6eb50d2aa26 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -267,6 +267,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 		GtkWidget *scrolled_window;
 		GtkWidget *tab_label;
 
+		if (symbol_conf.event_group &&
+		    !perf_evsel__is_group_leader(pos))
+			continue;
+
 		scrolled_window = gtk_scrolled_window_new(NULL, NULL);
 
 		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
-- 
1.7.11.7


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

* [PATCH 11/13] perf report: Show group description when event group is enabled
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (9 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 10/13] perf report: Bypass non-leader events when event group is enabled Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 12/13] perf report: Add --group option Namhyung Kim
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

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

When using event group viewer, it's better to show the group
description rather than the leader information alone.

If a leader did not contain any member, it's a non-group event.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Pekka Enberg <penberg@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-report.c    | 15 +++++++++++++++
 tools/perf/ui/browsers/hists.c | 25 +++++++++++++++++++++++++
 tools/perf/ui/gtk/hists.c      | 14 +++++++++++---
 tools/perf/util/evsel.c        | 25 +++++++++++++++++++++++++
 tools/perf/util/evsel.h        |  8 ++++++++
 5 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 9cc768ecacad..ce518c48a525 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -299,6 +299,21 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
 	char unit;
 	unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE];
 	u64 nr_events = self->stats.total_period;
+	struct perf_evsel *evsel = hists_to_evsel(self);
+	char buf[512];
+	size_t size = sizeof(buf);
+
+	if (symbol_conf.event_group && evsel->nr_members > 1) {
+		struct perf_evsel *pos;
+
+		perf_evsel__group_desc(evsel, buf, size);
+		evname = buf;
+
+		for_each_group_member(pos, evsel) {
+			nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+			nr_events += pos->hists.stats.total_period;
+		}
+	}
 
 	nr_samples = convert_unit(nr_samples, &unit);
 	ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 17c1753d5fe1..7a132fc3a4c9 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1193,6 +1193,21 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
 	const struct thread *thread = hists->thread_filter;
 	unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
 	u64 nr_events = hists->stats.total_period;
+	struct perf_evsel *evsel = hists_to_evsel(hists);
+	char buf[512];
+	size_t buflen = sizeof(buf);
+
+	if (symbol_conf.event_group && evsel->nr_members > 1) {
+		struct perf_evsel *pos;
+
+		perf_evsel__group_desc(evsel, buf, buflen);
+		ev_name = buf;
+
+		for_each_group_member(pos, evsel) {
+			nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+			nr_events += pos->hists.stats.total_period;
+		}
+	}
 
 	nr_samples = convert_unit(nr_samples, &unit);
 	printed = scnprintf(bf, size,
@@ -1589,6 +1604,16 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
 	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
 						       HE_COLORSET_NORMAL);
 
+	if (symbol_conf.event_group && evsel->nr_members > 1) {
+		struct perf_evsel *pos;
+
+		ev_name = perf_evsel__group_name(evsel);
+
+		for_each_group_member(pos, evsel) {
+			nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+		}
+	}
+
 	nr_events = convert_unit(nr_events, &unit);
 	printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
 			   unit, unit == ' ' ? "" : " ", ev_name);
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index d6eb50d2aa26..101a208e1b95 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -266,10 +266,18 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 		const char *evname = perf_evsel__name(pos);
 		GtkWidget *scrolled_window;
 		GtkWidget *tab_label;
+		char buf[512];
+		size_t size = sizeof(buf);
 
-		if (symbol_conf.event_group &&
-		    !perf_evsel__is_group_leader(pos))
-			continue;
+		if (symbol_conf.event_group) {
+			if (!perf_evsel__is_group_leader(pos))
+				continue;
+
+			if (pos->nr_members > 1) {
+				perf_evsel__group_desc(pos, buf, size);
+				evname = buf;
+			}
+		}
 
 		scrolled_window = gtk_scrolled_window_new(NULL, NULL);
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e45332d08a58..35b2a0a0a490 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -434,6 +434,31 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
 	return evsel->name ?: "unknown";
 }
 
+const char *perf_evsel__group_name(struct perf_evsel *evsel)
+{
+	return evsel->group_name ?: "anon group";
+}
+
+int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
+{
+	int ret;
+	struct perf_evsel *pos;
+	const char *group_name = perf_evsel__group_name(evsel);
+
+	ret = scnprintf(buf, size, "%s", group_name);
+
+	ret += scnprintf(buf + ret, size - ret, " { %s",
+			 perf_evsel__name(evsel));
+
+	for_each_group_member(pos, evsel)
+		ret += scnprintf(buf + ret, size - ret, ", %s",
+				 perf_evsel__name(pos));
+
+	ret += scnprintf(buf + ret, size - ret, " }");
+
+	return ret;
+}
+
 /*
  * The enable_on_exec/disabled value strategy:
  *
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 24225d728ba4..491e17242e78 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -113,6 +113,8 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
 					    char *bf, size_t size);
 const char *perf_evsel__name(struct perf_evsel *evsel);
+const char *perf_evsel__group_name(struct perf_evsel *evsel);
+int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
@@ -265,4 +267,10 @@ static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
 {
 	return evsel->idx - evsel->leader->idx;
 }
+
+#define for_each_group_member(_evsel, _leader) 					\
+for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); 	\
+     (_evsel) && (_evsel)->leader == (_leader);					\
+     (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
+
 #endif /* __PERF_EVSEL_H */
-- 
1.7.11.7


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

* [PATCH 12/13] perf report: Add --group option
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (10 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 11/13] perf report: Show group description " Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15  7:31 ` [PATCH 13/13] perf report: Add report.group config option Namhyung Kim
  2013-01-15 18:38 ` [PATCHSET 00/13] perf report: Add support for event group view (v8) Arnaldo Carvalho de Melo
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

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

Add --group option to enable event grouping.  When enabled, all the
group members information will be shown together with the leader.

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Documentation/perf-report.txt | 3 +++
 tools/perf/builtin-report.c              | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 848a0dcb6dfd..02284a0067f0 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -203,6 +203,9 @@ OPTIONS
 --objdump=<path>::
         Path to objdump binary.
 
+--group::
+	Show event group information together.
+
 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 ce518c48a525..9ef38424f7c3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -668,6 +668,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
 	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
 		    "Show a column with the sum of periods"),
+	OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
+		    "Show event group information together"),
 	OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
 		    "use branch records for histogram filling", parse_branch_mode),
 	OPT_STRING(0, "objdump", &objdump_path, "path",
-- 
1.7.11.7


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

* [PATCH 13/13] perf report: Add report.group config option
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (11 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 12/13] perf report: Add --group option Namhyung Kim
@ 2013-01-15  7:31 ` Namhyung Kim
  2013-01-15 18:38 ` [PATCHSET 00/13] perf report: Add support for event group view (v8) Arnaldo Carvalho de Melo
  13 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-15  7:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

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

Add report.group config option for setting default value of event
group view.  It affects the report output only if perf.data contains
event group info.

A user can write .perfconfig file like below to enable group view by
default:

  $ cat ~/.perfconfig
  [report]
  group = true

And it can be disabled through command line:

  $ perf report --no-group

Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-report.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 9ef38424f7c3..0d221870561a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -8,6 +8,7 @@
 #include "builtin.h"
 
 #include "util/util.h"
+#include "util/cache.h"
 
 #include "util/annotate.h"
 #include "util/color.h"
@@ -54,6 +55,16 @@ struct perf_report {
 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
+static int perf_report_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "report.group")) {
+		symbol_conf.event_group = perf_config_bool(var, value);
+		return 0;
+	}
+
+	return perf_default_config(var, value, cb);
+}
+
 static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
 					struct addr_location *al,
 					struct perf_sample *sample,
@@ -677,6 +688,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_END()
 	};
 
+	perf_config(perf_report_config, NULL);
+
 	argc = parse_options(argc, argv, options, report_usage, 0);
 
 	if (report.use_stdio)
-- 
1.7.11.7


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

* Re: [PATCH 05/13] perf hists: Resort hist entries using group members for output
  2013-01-15  7:31 ` [PATCH 05/13] perf hists: Resort hist entries using group members for output Namhyung Kim
@ 2013-01-15 18:29   ` Arnaldo Carvalho de Melo
  2013-01-16  9:20     ` Namhyung Kim
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-15 18:29 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Em Tue, Jan 15, 2013 at 04:31:49PM +0900, Namhyung Kim escreveu:
> From: Namhyung Kim <namhyung.kim@lge.com>
> 
> When event group is enabled, sorting hist entries on periods for output
> should consider groups members' period also.  To do that, build period
> table using link/pair information and compare the table.
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> Acked-by: Jiri Olsa <jolsa@redhat.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Cc: Stephane Eranian <eranian@google.com>
> Link: http://lkml.kernel.org/r/1355726345-29553-7-git-send-email-namhyung@kernel.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> ---
>  tools/perf/util/evsel.h |  2 ++
>  tools/perf/util/hist.c  | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> index f5d22f12ccd8..24225d728ba4 100644
> --- a/tools/perf/util/evsel.h
> +++ b/tools/perf/util/evsel.h
> @@ -78,6 +78,8 @@ struct perf_evsel {
>  	char			*group_name;
>  };
>  
> +#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
> +
>  struct cpu_map;
>  struct thread_map;
>  struct perf_evlist;
> diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
> index 8170a3d11ffa..f855941bebea 100644
> --- a/tools/perf/util/hist.c
> +++ b/tools/perf/util/hist.c
> @@ -4,6 +4,7 @@
>  #include "hist.h"
>  #include "session.h"
>  #include "sort.h"
> +#include "evsel.h"
>  #include <math.h>
>  
>  static bool hists__filter_entry_by_dso(struct hists *hists,
> @@ -540,6 +541,62 @@ void hists__collapse_resort_threaded(struct hists *hists)
>   * reverse the map, sort on period.
>   */
>  
> +static int period_cmp(u64 period_a, u64 period_b)
> +{
> +	if (period_a > period_b)
> +		return 1;
> +	if (period_a < period_b)
> +		return -1;
> +	return 0;
> +}
> +
> +static int hist_entry__sort_on_period(struct hist_entry *a,
> +				      struct hist_entry *b)
> +{
> +	int ret;
> +	int i, nr_members;
> +	struct perf_evsel *evsel;
> +	struct hist_entry *pair;
> +	u64 *periods_a, *periods_b;
> +
> +	ret = period_cmp(a->stat.period, b->stat.period);
> +	if (ret || !symbol_conf.event_group)

Why do we need to call period_cmp() when symbol_conf.event_group is
false?

I see, confusing neverthless :-\

> +		return ret;

I would expect two functions, one for sorting on period and another for
not sorting on period, i.e. don't call a function called
'sort_on_period' when _not_ sorting on period.

- Arnaldo

> +
> +	evsel = hists_to_evsel(a->hists);
> +	nr_members = evsel->nr_members;
> +	if (nr_members <= 1)
> +		return ret;
> +
> +	periods_a = zalloc(sizeof(periods_a) * nr_members);
> +	periods_b = zalloc(sizeof(periods_b) * nr_members);
> +
> +	if (!periods_a || !periods_b)
> +		goto out;
> +
> +	list_for_each_entry(pair, &a->pairs.head, pairs.node) {
> +		evsel = hists_to_evsel(pair->hists);
> +		periods_a[perf_evsel__group_idx(evsel)] = pair->stat.period;
> +	}
> +
> +	list_for_each_entry(pair, &b->pairs.head, pairs.node) {
> +		evsel = hists_to_evsel(pair->hists);
> +		periods_b[perf_evsel__group_idx(evsel)] = pair->stat.period;
> +	}
> +
> +	for (i = 1; i < nr_members; i++) {
> +		ret = period_cmp(periods_a[i], periods_b[i]);
> +		if (ret)
> +			break;
> +	}
> +
> +out:
> +	free(periods_a);
> +	free(periods_b);
> +
> +	return ret;
> +}
> +
>  static void __hists__insert_output_entry(struct rb_root *entries,
>  					 struct hist_entry *he,
>  					 u64 min_callchain_hits)
> @@ -556,7 +613,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
>  		parent = *p;
>  		iter = rb_entry(parent, struct hist_entry, rb_node);
>  
> -		if (he->stat.period > iter->stat.period)
> +		if (hist_entry__sort_on_period(he, iter) > 0)
>  			p = &(*p)->rb_left;
>  		else
>  			p = &(*p)->rb_right;
> -- 
> 1.7.11.7

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

* Re: [PATCH 06/13] perf ui/hist: Add support for event group view
  2013-01-15  7:31 ` [PATCH 06/13] perf ui/hist: Add support for event group view Namhyung Kim
@ 2013-01-15 18:31   ` Arnaldo Carvalho de Melo
  2013-01-16  9:22     ` Namhyung Kim
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-15 18:31 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Em Tue, Jan 15, 2013 at 04:31:50PM +0900, Namhyung Kim escreveu:
> From: Namhyung Kim <namhyung.kim@lge.com>
> 
> Show group members' overhead also when showing the leader's if event
> group is enabled.  Use macro for defining hpp functions which looks
> almost identical.
> 
> Thanks to Arnaldo for suggesting a better way to print group members
> without allocating temporary array.

Thanks! Its a pity the patch ended up mixing up things, I'll have to
apply it and look at the end result.
 
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Stephane Eranian <eranian@google.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/ui/hist.c       | 311 +++++++++++++++++++++++----------------------
>  tools/perf/ui/stdio/hist.c |   2 +
>  2 files changed, 164 insertions(+), 149 deletions(-)
> 
> diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
> index 1889c12ca81f..ec14335a9713 100644
> --- a/tools/perf/ui/hist.c
> +++ b/tools/perf/ui/hist.c
> @@ -3,151 +3,190 @@
>  #include "../util/hist.h"
>  #include "../util/util.h"
>  #include "../util/sort.h"
> -
> +#include "../util/evsel.h"
>  
>  /* hist period print (hpp) functions */
> -static int hpp__header_overhead(struct perf_hpp *hpp)
> -{
> -	return scnprintf(hpp->buf, hpp->size, "Overhead");
> -}
>  
> -static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 8;
> -}
> +typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...);
>  
> -static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
> +static int __hpp__percent_fmt(struct perf_hpp *hpp, struct hist_entry *he,
> +			      u64 (*get_field)(struct hist_entry *),
> +			      const char *fmt, hpp_snprint_fn print_fn)
>  {
> +	int ret;
> +	double percent = 0.0;
>  	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period / hists->stats.total_period;
>  
> -	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
> -}
> +	if (hists->stats.total_period)
> +		percent = 100.0 * get_field(he) / hists->stats.total_period;
>  
> -static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period / hists->stats.total_period;
> -	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
> +	ret = print_fn(hpp->buf, hpp->size, fmt, percent);
>  
> -	return scnprintf(hpp->buf, hpp->size, fmt, percent);
> -}
> +	if (symbol_conf.event_group) {
> +		int prev_idx, idx_delta, i;
> +		struct perf_evsel *evsel = hists_to_evsel(hists);
> +		struct hist_entry *pair;
> +		int nr_members = evsel->nr_members;
>  
> -static int hpp__header_overhead_sys(struct perf_hpp *hpp)
> -{
> -	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
> +		if (nr_members <= 1)
> +			return ret;
>  
> -	return scnprintf(hpp->buf, hpp->size, fmt, "sys");
> -}
> +		prev_idx = perf_evsel__group_idx(evsel);
>  
> -static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 7;
> -}
> +		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
> +			u64 period = get_field(pair);
> +			u64 total = pair->hists->stats.total_period;
>  
> -static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
> +			if (!total)
> +				continue;
>  
> -	return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
> -}
> +			evsel = hists_to_evsel(pair->hists);
> +			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
>  
> -static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
> -	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
> +			for (i = 0; i < idx_delta; i++) {
> +				ret += print_fn(hpp->buf + ret, hpp->size - ret,
> +						fmt, 0.0);
> +			}
>  
> -	return scnprintf(hpp->buf, hpp->size, fmt, percent);
> -}
> +			ret += print_fn(hpp->buf + ret, hpp->size - ret,
> +					fmt, 100.0 * period / total);
>  
> -static int hpp__header_overhead_us(struct perf_hpp *hpp)
> -{
> -	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
> +			prev_idx += 1 + idx_delta;
> +		}
>  
> -	return scnprintf(hpp->buf, hpp->size, fmt, "user");
> -}
> +		idx_delta = nr_members - prev_idx - 1;
>  
> -static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 7;
> +		for (i = 0; i < idx_delta; i++) {
> +			ret += print_fn(hpp->buf + ret, hpp->size - ret,
> +					fmt, 0.0);
> +		}
> +	}
> +	return ret;
>  }
>  
> -static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
> +static int __hpp__raw_fmt(struct perf_hpp *hpp, struct hist_entry *he,
> +			  u64 (*get_field)(struct hist_entry *),
> +			  const char *fmt, hpp_snprint_fn print_fn)
>  {
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
> -
> -	return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
> -}
> +	int ret;
> +	ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he));
>  
> -static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
> -	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
> +	if (symbol_conf.event_group) {
> +		int prev_idx, idx_delta, i;
> +		struct perf_evsel *evsel = hists_to_evsel(he->hists);
> +		struct hist_entry *pair;
> +		int nr_members = evsel->nr_members;
>  
> -	return scnprintf(hpp->buf, hpp->size, fmt, percent);
> -}
> +		if (nr_members <= 1)
> +			return ret;
>  
> -static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
> -{
> -	return scnprintf(hpp->buf, hpp->size, "guest sys");
> -}
> +		prev_idx = perf_evsel__group_idx(evsel);
>  
> -static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 9;
> -}
> +		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
> +			evsel = hists_to_evsel(pair->hists);
> +			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
>  
> -static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
> -					 struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
> +			for (i = 0; i < idx_delta; i++) {
> +				ret += print_fn(hpp->buf + ret, hpp->size - ret,
> +						fmt, 0.0);
> +			}
>  
> -	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
> -}
> +			ret += print_fn(hpp->buf + ret, hpp->size - ret,
> +					fmt, get_field(pair));
>  
> -static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
> -					 struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
> -	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
> -
> -	return scnprintf(hpp->buf, hpp->size, fmt, percent);
> -}
> +			prev_idx += 1 + idx_delta;
> +		}
>  
> -static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
> -{
> -	return scnprintf(hpp->buf, hpp->size, "guest usr");
> -}
> +		idx_delta = nr_members - prev_idx - 1;
>  
> -static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 9;
> +		for (i = 0; i < idx_delta; i++) {
> +			ret += print_fn(hpp->buf + ret, hpp->size - ret,
> +					fmt, 0.0);
> +		}
> +	}
> +	return ret;
>  }
>  
> -static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
> -					struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
> -
> -	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
> -}
>  
> -static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
> -					struct hist_entry *he)
> -{
> -	struct hists *hists = he->hists;
> -	double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
> -	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
> +#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) 		\
> +static int hpp__header_##_type(struct perf_hpp *hpp)			\
> +{									\
> +	int len = _min_width;						\
> +									\
> +	if (symbol_conf.event_group) {					\
> +		struct perf_evsel *evsel = hpp->ptr;			\
> +									\
> +		len = max(len, evsel->nr_members * _unit_width);	\
> +	}								\
> +	return scnprintf(hpp->buf, hpp->size, "%*s", len, _str);	\
> +}
> +
> +#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) 			\
> +static int hpp__width_##_type(struct perf_hpp *hpp)			\
> +{									\
> +	int len = _min_width;						\
> +									\
> +	if (symbol_conf.event_group) {					\
> +		struct perf_evsel *evsel = hpp->ptr;			\
> +									\
> +		len = max(len, evsel->nr_members * _unit_width);	\
> +	}								\
> +	return len;							\
> +}
> +
> +#define __HPP_COLOR_PERCENT_FN(_type, _field)					\
> +static u64 he_get_##_field(struct hist_entry *he)				\
> +{										\
> +	return he->stat._field;							\
> +}										\
> +										\
> +static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
> +{										\
> +	return __hpp__percent_fmt(hpp, he, he_get_##_field, " %6.2f%%",		\
> +				  (hpp_snprint_fn)percent_color_snprintf); 	\
> +}
> +
> +#define __HPP_ENTRY_PERCENT_FN(_type, _field)					\
> +static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
> +{										\
> +	const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%";		\
> +	return __hpp__percent_fmt(hpp, he, he_get_##_field, fmt,		\
> +				  scnprintf);					\
> +}
> +
> +#define __HPP_ENTRY_RAW_FN(_type, _field)					\
> +static u64 he_get_raw_##_field(struct hist_entry *he)				\
> +{										\
> +	return he->stat._field;							\
> +}										\
> +										\
> +static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
> +{										\
> +	const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64;	\
> +	return __hpp__raw_fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf);	\
> +}
> +
> +#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width)	\
> +__HPP_HEADER_FN(_type, _str, _min_width, _unit_width)			\
> +__HPP_WIDTH_FN(_type, _min_width, _unit_width)				\
> +__HPP_COLOR_PERCENT_FN(_type, _field)					\
> +__HPP_ENTRY_PERCENT_FN(_type, _field)
> +
> +#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width)	\
> +__HPP_HEADER_FN(_type, _str, _min_width, _unit_width)			\
> +__HPP_WIDTH_FN(_type, _min_width, _unit_width)				\
> +__HPP_ENTRY_RAW_FN(_type, _field)
> +
> +
> +HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8)
> +HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8)
> +HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8)
> +HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8)
> +HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
> +
> +HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12)
> +HPP_RAW_FNS(period, "Period", period, 12, 12)
>  
> -	return scnprintf(hpp->buf, hpp->size, fmt, percent);
> -}
>  
>  static int hpp__header_baseline(struct perf_hpp *hpp)
>  {
> @@ -179,7 +218,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
>  {
>  	double percent = baseline_percent(he);
>  
> -	if (hist_entry__has_pairs(he))
> +	if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
>  		return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
>  	else
>  		return scnprintf(hpp->buf, hpp->size, "        ");
> @@ -196,44 +235,6 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
>  		return scnprintf(hpp->buf, hpp->size, "            ");
>  }
>  
> -static int hpp__header_samples(struct perf_hpp *hpp)
> -{
> -	const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
> -
> -	return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
> -}
> -
> -static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 11;
> -}
> -
> -static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
> -{
> -	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
> -
> -	return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
> -}
> -
> -static int hpp__header_period(struct perf_hpp *hpp)
> -{
> -	const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
> -
> -	return scnprintf(hpp->buf, hpp->size, fmt, "Period");
> -}
> -
> -static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
> -{
> -	return 12;
> -}
> -
> -static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
> -{
> -	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
> -
> -	return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
> -}
> -
>  static int hpp__header_period_baseline(struct perf_hpp *hpp)
>  {
>  	const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
> @@ -254,6 +255,7 @@ static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *h
>  
>  	return scnprintf(hpp->buf, hpp->size, fmt, period);
>  }
> +
>  static int hpp__header_delta(struct perf_hpp *hpp)
>  {
>  	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
> @@ -408,9 +410,20 @@ struct perf_hpp_fmt perf_hpp__format[] = {
>  
>  LIST_HEAD(perf_hpp__list);
>  
> +
>  #undef HPP__COLOR_PRINT_FNS
>  #undef HPP__PRINT_FNS
>  
> +#undef HPP_PERCENT_FNS
> +#undef HPP_RAW_FNS
> +
> +#undef __HPP_HEADER_FN
> +#undef __HPP_WIDTH_FN
> +#undef __HPP_COLOR_PERCENT_FN
> +#undef __HPP_ENTRY_PERCENT_FN
> +#undef __HPP_ENTRY_RAW_FN
> +
> +
>  void perf_hpp__init(void)
>  {
>  	if (symbol_conf.show_cpu_utilization) {
> diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
> index f9798298e3e0..ff1f60cf442e 100644
> --- a/tools/perf/ui/stdio/hist.c
> +++ b/tools/perf/ui/stdio/hist.c
> @@ -3,6 +3,7 @@
>  #include "../../util/util.h"
>  #include "../../util/hist.h"
>  #include "../../util/sort.h"
> +#include "../../util/evsel.h"
>  
>  
>  static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
> @@ -347,6 +348,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
>  	struct perf_hpp dummy_hpp = {
>  		.buf	= bf,
>  		.size	= sizeof(bf),
> +		.ptr	= hists_to_evsel(hists),
>  	};
>  	bool first = true;
>  
> -- 
> 1.7.11.7

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

* Re: [PATCH 07/13] perf hist browser: Add support for event group view
  2013-01-15  7:31 ` [PATCH 07/13] perf hist browser: " Namhyung Kim
@ 2013-01-15 18:32   ` Arnaldo Carvalho de Melo
  2013-01-16  9:52     ` Namhyung Kim
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-15 18:32 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Em Tue, Jan 15, 2013 at 04:31:51PM +0900, Namhyung Kim escreveu:
> From: Namhyung Kim <namhyung.kim@lge.com>
> 
> Show group members' overhead also when showing the leader's if event
> group is enabled.  Use macro for defining hpp functions which looks
> almost identical.
> 
> Also move coloring logic into the hpp function so that each value can
> be colored independently.

Just from reading the description: when we have this "Also do this extra
thing" it smells like we need to break the patch in two... Can this be
done?

- Arnaldo
 
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Stephane Eranian <eranian@google.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/ui/browsers/hists.c | 153 ++++++++++++++++++++++++++++++++---------
>  tools/perf/ui/hist.c           |   5 +-
>  2 files changed, 126 insertions(+), 32 deletions(-)
> 
> diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
> index 57b82c26cd05..65e6c005f8e9 100644
> --- a/tools/perf/ui/browsers/hists.c
> +++ b/tools/perf/ui/browsers/hists.c
> @@ -567,23 +567,126 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
>  	return row - first_row;
>  }
>  
> -#define HPP__COLOR_FN(_name, _field)					\
> -static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp,	\
> -					     struct hist_entry *he)	\
> +struct hpp_arg {
> +	struct ui_browser *b;
> +	char folded_sign;
> +	bool current_entry;
> +};
> +
> +static int hist_browser__hpp_color_callchain(struct hpp_arg *arg)
> +{
> +	if (!symbol_conf.use_callchain)
> +		return 0;
> +
> +	slsmg_printf("%c ", arg->folded_sign);
> +	return 2;
> +}
> +
> +static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
> +			    u64 (*get_field)(struct hist_entry *),
> +			    int (*callchain_cb)(struct hpp_arg *))
> +{
> +	int ret = 0;
> +	double percent = 0.0;
> +	struct hists *hists = he->hists;
> +	struct hpp_arg *arg = hpp->ptr;
> +
> +	if (hists->stats.total_period)
> +		percent = 100.0 * get_field(he) / hists->stats.total_period;
> +
> +	ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
> +
> +	if (callchain_cb)
> +		ret += callchain_cb(arg);
> +
> +	ret += scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
> +	slsmg_printf("%s", hpp->buf);
> +
> +	if (symbol_conf.event_group) {
> +		int prev_idx, idx_delta, i;
> +		struct perf_evsel *evsel = hists_to_evsel(hists);
> +		struct hist_entry *pair;
> +		int nr_members = evsel->nr_members;
> +
> +		if (nr_members <= 1)
> +			goto out;
> +
> +		prev_idx = perf_evsel__group_idx(evsel);
> +
> +		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
> +			u64 period = get_field(pair);
> +			u64 total = pair->hists->stats.total_period;
> +
> +			if (!total)
> +				continue;
> +
> +			evsel = hists_to_evsel(pair->hists);
> +			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
> +
> +			for (i = 0; i < idx_delta; i++) {
> +				ui_browser__set_percent_color(arg->b, 0.0,
> +							arg->current_entry);
> +				ret += scnprintf(hpp->buf, hpp->size,
> +						 " %6.2f%%", 0.0);
> +				slsmg_printf("%s", hpp->buf);
> +			}
> +
> +			percent = 100.0 * period / total;
> +			ui_browser__set_percent_color(arg->b, percent,
> +						      arg->current_entry);
> +			ret += scnprintf(hpp->buf, hpp->size,
> +					 " %6.2f%%", percent);
> +			slsmg_printf("%s", hpp->buf);
> +
> +			prev_idx += 1 + idx_delta;
> +		}
> +
> +		idx_delta = nr_members - prev_idx - 1;
> +
> +		for (i = 0; i < idx_delta; i++) {
> +			ui_browser__set_percent_color(arg->b, 0.0,
> +						      arg->current_entry);
> +			ret += scnprintf(hpp->buf, hpp->size, " %6.2f%%", 0.0);
> +			slsmg_printf("%s", hpp->buf);
> +		}
> +	}
> +out:
> +	if (!arg->current_entry || !arg->b->navkeypressed)
> +		ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
> +
> +	return ret;
> +}
> +
> +static u64 __hpp_get_period(struct hist_entry *he)
> +{
> +	return he->stat.period;
> +}
> +
> +static int hist_browser__hpp_color_overhead(struct perf_hpp *hpp,
> +					    struct hist_entry *he)
> +{
> +	return __hpp__color_fmt(hpp, he, __hpp_get_period,
> +				hist_browser__hpp_color_callchain);
> +}
> +
> +#define __HPP_COLOR_PERCENT_FN(_type, _field)				\
> +static u64 __hpp_get_##_field(struct hist_entry *he)			\
> +{									\
> +	return he->stat._field;						\
> +}									\
> +									\
> +static int hist_browser__hpp_color_##_type(struct perf_hpp *hpp,	\
> +					   struct hist_entry *he)	\
>  {									\
> -	struct hists *hists = he->hists;				\
> -	double percent = 100.0 * he->stat._field / hists->stats.total_period; \
> -	*(double *)hpp->ptr = percent;					\
> -	return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);	\
> +	return __hpp__color_fmt(hpp, he, __hpp_get_##_field, NULL);	\
>  }
>  
> -HPP__COLOR_FN(overhead, period)
> -HPP__COLOR_FN(overhead_sys, period_sys)
> -HPP__COLOR_FN(overhead_us, period_us)
> -HPP__COLOR_FN(overhead_guest_sys, period_guest_sys)
> -HPP__COLOR_FN(overhead_guest_us, period_guest_us)
> +__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
> +__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
> +__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
> +__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
>  
> -#undef HPP__COLOR_FN
> +#undef __HPP_COLOR_PERCENT_FN
>  
>  void hist_browser__init_hpp(void)
>  {
> @@ -608,7 +711,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
>  				    unsigned short row)
>  {
>  	char s[256];
> -	double percent;
>  	int printed = 0;
>  	int width = browser->b.width;
>  	char folded_sign = ' ';
> @@ -628,11 +730,16 @@ static int hist_browser__show_entry(struct hist_browser *browser,
>  	}
>  
>  	if (row_offset == 0) {
> +		struct hpp_arg arg = {
> +			.b		= &browser->b,
> +			.folded_sign	= folded_sign,
> +			.current_entry	= current_entry,
> +		};
>  		struct perf_hpp hpp = {
>  			.buf		= s,
>  			.size		= sizeof(s),
> +			.ptr		= &arg,
>  		};
> -		int i = 0;
>  
>  		ui_browser__gotorc(&browser->b, row, 0);
>  
> @@ -645,27 +752,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
>  			first = false;
>  
>  			if (fmt->color) {
> -				hpp.ptr = &percent;
> -				/* It will set percent for us. See HPP__COLOR_FN above. */
>  				width -= fmt->color(&hpp, entry);
> -
> -				ui_browser__set_percent_color(&browser->b, percent, current_entry);
> -
> -				if (!i && symbol_conf.use_callchain) {
> -					slsmg_printf("%c ", folded_sign);
> -					width -= 2;
> -				}
> -
> -				slsmg_printf("%s", s);
> -
> -				if (!current_entry || !browser->b.navkeypressed)
> -					ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
>  			} else {
>  				width -= fmt->entry(&hpp, entry);
>  				slsmg_printf("%s", s);
>  			}
> -
> -			i++;
>  		}
>  
>  		/* The scroll bar isn't being used */
> diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
> index ec14335a9713..be9152cd4c76 100644
> --- a/tools/perf/ui/hist.c
> +++ b/tools/perf/ui/hist.c
> @@ -521,12 +521,15 @@ unsigned int hists__sort_list_width(struct hists *hists)
>  	struct perf_hpp_fmt *fmt;
>  	struct sort_entry *se;
>  	int i = 0, ret = 0;
> +	struct perf_hpp dummy_hpp = {
> +		.ptr	= hists_to_evsel(hists),
> +	};
>  
>  	perf_hpp__for_each_format(fmt) {
>  		if (i)
>  			ret += 2;
>  
> -		ret += fmt->width(NULL);
> +		ret += fmt->width(&dummy_hpp);
>  	}
>  
>  	list_for_each_entry(se, &hist_entry__sort_list, list)
> -- 
> 1.7.11.7

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

* Re: [PATCH 08/13] perf gtk/browser: Add support for event group view
  2013-01-15  7:31 ` [PATCH 08/13] perf gtk/browser: " Namhyung Kim
@ 2013-01-15 18:34   ` Arnaldo Carvalho de Melo
  2013-01-16 10:25     ` Namhyung Kim
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-15 18:34 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

Em Tue, Jan 15, 2013 at 04:31:52PM +0900, Namhyung Kim escreveu:
> From: Namhyung Kim <namhyung.kim@lge.com>
> 
> Show group members' overhead also when showing the leader's if event
> group is enabled.  Use macro for defining hpp functions which looks
> almost identical.
> 
> Unlike other hpp backend, GTK+ needs to print dummy 0.00% output since
> it's displayed with variable width fonts.  So that simply skipping
> with %*s trick won't work well here.

I'm illiterate on GTK+ internals, but I kinda expected that it could
provide a way to avoid such things, i.e. a way to position the cursor
in such circumstance without having to actually print the '0.00%' :-\

- Arnaldo
 
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Stephane Eranian <eranian@google.com>
> Cc: Pekka Enberg <penberg@kernel.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/ui/gtk/hists.c | 114 +++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 92 insertions(+), 22 deletions(-)
> 
> diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
> index c03da79d524f..a4d951ea919a 100644
> --- a/tools/perf/ui/gtk/hists.c
> +++ b/tools/perf/ui/gtk/hists.c
> @@ -8,32 +8,102 @@
>  
>  #define MAX_COLUMNS			32
>  
> -#define HPP__COLOR_FN(_name, _field)						\
> -static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,			\
> -					 struct hist_entry *he)			\
> +static int perf_gtk__percent_color_snprintf(char *buf, size_t size,
> +					    double percent)
> +{
> +	int ret = 0;
> +	const char *markup;
> +
> +	markup = perf_gtk__get_percent_color(percent);
> +	if (markup)
> +		ret += scnprintf(buf, size, markup);
> +
> +	ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent);
> +
> +	if (markup)
> +		ret += scnprintf(buf + ret, size - ret, "</span>");
> +
> +	return ret;
> +}
> +
> +
> +static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
> +			    u64 (*get_field)(struct hist_entry *))
> +{
> +	int ret;
> +	double percent = 0.0;
> +	struct hists *hists = he->hists;
> +
> +	if (hists->stats.total_period)
> +		percent = 100.0 * get_field(he) / hists->stats.total_period;
> +
> +	ret = perf_gtk__percent_color_snprintf(hpp->buf, hpp->size, percent);
> +
> +	if (symbol_conf.event_group) {
> +		int prev_idx, idx_delta;
> +		struct perf_evsel *evsel = hists_to_evsel(hists);
> +		struct hist_entry *pair;
> +		int nr_members = evsel->nr_members;
> +
> +		if (nr_members <= 1)
> +			return ret;
> +
> +		prev_idx = perf_evsel__group_idx(evsel);
> +
> +		list_for_each_entry(pair, &he->pairs.head, pairs.node) {
> +			u64 period = get_field(pair);
> +			u64 total = pair->hists->stats.total_period;
> +
> +			evsel = hists_to_evsel(pair->hists);
> +			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
> +
> +			while (idx_delta--) {
> +				ret += scnprintf(hpp->buf + ret, hpp->size -ret, " ");
> +				ret += perf_gtk__percent_color_snprintf(hpp->buf + ret,
> +									hpp->size - ret,
> +									0.0);
> +			}
> +
> +			percent = 100.0 * period / total;
> +			ret += scnprintf(hpp->buf + ret, hpp->size -ret, " ");
> +			ret += perf_gtk__percent_color_snprintf(hpp->buf + ret,
> +								hpp->size - ret,
> +								percent);
> +
> +			prev_idx = perf_evsel__group_idx(evsel);
> +		}
> +
> +		idx_delta = nr_members - prev_idx - 1;
> +
> +		while (idx_delta--) {
> +			ret += scnprintf(hpp->buf + ret, hpp->size -ret, " ");
> +			ret += perf_gtk__percent_color_snprintf(hpp->buf + ret,
> +								hpp->size - ret,
> +								0.0);
> +		}
> +	}
> +	return ret;
> +}
> +
> +#define __HPP_COLOR_PERCENT_FN(_type, _field)					\
> +static u64 he_get_##_field(struct hist_entry *he)				\
>  {										\
> -	struct hists *hists = he->hists;					\
> -	double percent = 100.0 * he->stat._field / hists->stats.total_period;	\
> -	const char *markup;							\
> -	int ret = 0;								\
> +	return he->stat._field;							\
> +}										\
>  										\
> -	markup = perf_gtk__get_percent_color(percent);				\
> -	if (markup)								\
> -		ret += scnprintf(hpp->buf, hpp->size, "%s", markup);		\
> -	ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); 	\
> -	if (markup)								\
> -		ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); 	\
> -										\
> -	return ret;								\
> +static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp,			\
> +				       struct hist_entry *he)			\
> +{										\
> +	return __hpp__color_fmt(hpp, he, he_get_##_field);			\
>  }
>  
> -HPP__COLOR_FN(overhead, period)
> -HPP__COLOR_FN(overhead_sys, period_sys)
> -HPP__COLOR_FN(overhead_us, period_us)
> -HPP__COLOR_FN(overhead_guest_sys, period_guest_sys)
> -HPP__COLOR_FN(overhead_guest_us, period_guest_us)
> +__HPP_COLOR_PERCENT_FN(overhead, period)
> +__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
> +__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
> +__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
> +__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
>  
> -#undef HPP__COLOR_FN
> +#undef __HPP_COLOR_PERCENT_FN
>  
>  
>  void perf_gtk__init_hpp(void)
> @@ -70,6 +140,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
>  	struct perf_hpp hpp = {
>  		.buf		= s,
>  		.size		= sizeof(s),
> +		.ptr		= hists_to_evsel(hists),
>  	};
>  
>  	nr_cols = 0;
> @@ -94,7 +165,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
>  
>  	perf_hpp__for_each_format(fmt) {
>  		fmt->header(&hpp);
> -
>  		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
>  							    -1, s,
>  							    renderer, "markup",
> -- 
> 1.7.11.7

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

* Re: [PATCHSET 00/13] perf report: Add support for event group view (v8)
  2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
                   ` (12 preceding siblings ...)
  2013-01-15  7:31 ` [PATCH 13/13] perf report: Add report.group config option Namhyung Kim
@ 2013-01-15 18:38 ` Arnaldo Carvalho de Melo
  2013-01-16 10:33   ` Namhyung Kim
  13 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-15 18:38 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Em Tue, Jan 15, 2013 at 04:31:44PM +0900, Namhyung Kim escreveu:
> This is my 8th attempt to enable the event group view for perf report.
> For basic idea and usage example, please see my initial post [1].
> 
> This version is rebased on the current acme/perf/core and it's mainly
> changed due to a refactoring of gtk browser.
> 
> You can get this via 'perf/group-v8' branch on my tree:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
> 
> Any comments are welcome, thanks,

It would be great if examples of this in use were provided.

Detailed ones at that, showing how things were in the past, how the info
can be retrieved when using 'perf report --stdio', perhaps 'perf evlist'
can show the stored group information too, how the 'perf report' output
looks like when showing group info, things like that.

- Arnaldo

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

* Re: [PATCH 05/13] perf hists: Resort hist entries using group members for output
  2013-01-15 18:29   ` Arnaldo Carvalho de Melo
@ 2013-01-16  9:20     ` Namhyung Kim
  0 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-16  9:20 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Hi Arnaldo,

On Tue, 15 Jan 2013 15:29:15 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 15, 2013 at 04:31:49PM +0900, Namhyung Kim escreveu:
>> From: Namhyung Kim <namhyung.kim@lge.com>
>> 
>> When event group is enabled, sorting hist entries on periods for output
>> should consider groups members' period also.  To do that, build period
>> table using link/pair information and compare the table.
[snip]
>> +static int hist_entry__sort_on_period(struct hist_entry *a,
>> +				      struct hist_entry *b)
>> +{
>> +	int ret;
>> +	int i, nr_members;
>> +	struct perf_evsel *evsel;
>> +	struct hist_entry *pair;
>> +	u64 *periods_a, *periods_b;
>> +
>> +	ret = period_cmp(a->stat.period, b->stat.period);
>> +	if (ret || !symbol_conf.event_group)
>
> Why do we need to call period_cmp() when symbol_conf.event_group is
> false?
>
> I see, confusing neverthless :-\

In this function @a and @b are entries of group leaders and should be
compared first - other group members are compared only if periods of
leader entries are same.

For non-group events or when event group view is disabled, this function
will be called for every events as if they're leaders.


>
>> +		return ret;
>
> I would expect two functions, one for sorting on period and another for
> not sorting on period, i.e. don't call a function called
> 'sort_on_period' when _not_ sorting on period.

Sorry, I can't understand.

This 'sort_on_period' function is called during the (final) output
resorting and it's unconditional.  IOW hist entries should be sorted by
their period to be shown accordingly in the output.

Am I missing something?

Thanks,
Namhyung

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

* Re: [PATCH 06/13] perf ui/hist: Add support for event group view
  2013-01-15 18:31   ` Arnaldo Carvalho de Melo
@ 2013-01-16  9:22     ` Namhyung Kim
  2013-01-16 18:14       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-16  9:22 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

On Tue, 15 Jan 2013 15:31:10 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 15, 2013 at 04:31:50PM +0900, Namhyung Kim escreveu:
>> From: Namhyung Kim <namhyung.kim@lge.com>
>> 
>> Show group members' overhead also when showing the leader's if event
>> group is enabled.  Use macro for defining hpp functions which looks
>> almost identical.
>> 
>> Thanks to Arnaldo for suggesting a better way to print group members
>> without allocating temporary array.
>
> Thanks! Its a pity the patch ended up mixing up things, I'll have to
> apply it and look at the end result.

Do you mean I have to separate this into two - one for converting to
macro and another for event group view itself?

Thanks,
Namhyung

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

* Re: [PATCH 07/13] perf hist browser: Add support for event group view
  2013-01-15 18:32   ` Arnaldo Carvalho de Melo
@ 2013-01-16  9:52     ` Namhyung Kim
  0 siblings, 0 replies; 29+ messages in thread
From: Namhyung Kim @ 2013-01-16  9:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

On Tue, 15 Jan 2013 15:32:26 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 15, 2013 at 04:31:51PM +0900, Namhyung Kim escreveu:
>> From: Namhyung Kim <namhyung.kim@lge.com>
>> 
>> Show group members' overhead also when showing the leader's if event
>> group is enabled.  Use macro for defining hpp functions which looks
>> almost identical.
>> 
>> Also move coloring logic into the hpp function so that each value can
>> be colored independently.
>
> Just from reading the description: when we have this "Also do this extra
> thing" it smells like we need to break the patch in two... Can this be
> done?

Sure.  I'll break it.

Thanks,
Namhyung

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

* Re: [PATCH 08/13] perf gtk/browser: Add support for event group view
  2013-01-15 18:34   ` Arnaldo Carvalho de Melo
@ 2013-01-16 10:25     ` Namhyung Kim
  2013-01-16 18:28       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-16 10:25 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

On Tue, 15 Jan 2013 15:34:05 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 15, 2013 at 04:31:52PM +0900, Namhyung Kim escreveu:
>> From: Namhyung Kim <namhyung.kim@lge.com>
>> 
>> Show group members' overhead also when showing the leader's if event
>> group is enabled.  Use macro for defining hpp functions which looks
>> almost identical.
>> 
>> Unlike other hpp backend, GTK+ needs to print dummy 0.00% output since
>> it's displayed with variable width fonts.  So that simply skipping
>> with %*s trick won't work well here.
>
> I'm illiterate on GTK+ internals, but I kinda expected that it could
> provide a way to avoid such things, i.e. a way to position the cursor
> in such circumstance without having to actually print the '0.00%' :-\

I also don't understand the internals so I just guess that it might
(only?) be acheived by adding new columns for each group members.

Of course I'm fine with this way too, but one thing I'm not sure is how
the column header look like.  Currently "Overhead" is displayed on the
header for period of every group members - say, there's a group consists
of two events: {branches,branch-misses}.  It'd look like:

        Overhead  Command  Shared Object   Symbol
  ..............  .......  .............  .......
  98.32%  31.16%    a.out          a.out  [.] foo


Maybe we can use simple event name for this, but it seems it makes to
hard to recognize which one is which if other output options like
--show-total-period, --showcpuutilization and/or --show-nr-samples.

Adding current header name to event name will fix the problem but it
probably occupies too much screen width especially for long named
tracepoint or PMU-specific events like
"compaction:mm_compaction_isolate_migratepages".

  Overhead/branches  Overhead/branch-misses  sys/branches  sys/branch-misses  usr/branches  usr/branch-misses  Command  Shared Object   Symbol
  .................  ......................  ............  .................  ............  .................  .......  .............  .......
             98.32%                  31.16%         0.00%              0.00%        98.32%             31.16%    a.out          a.out  [.] foo


If you have a better idea or other way to place the cursor without
printing bogus 0.00% on GTK, please let me know.

Thanks,
Namhyung

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

* Re: [PATCHSET 00/13] perf report: Add support for event group view (v8)
  2013-01-15 18:38 ` [PATCHSET 00/13] perf report: Add support for event group view (v8) Arnaldo Carvalho de Melo
@ 2013-01-16 10:33   ` Namhyung Kim
  2013-01-16 18:29     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-16 10:33 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

On Tue, 15 Jan 2013 15:38:58 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 15, 2013 at 04:31:44PM +0900, Namhyung Kim escreveu:
>> This is my 8th attempt to enable the event group view for perf report.
>> For basic idea and usage example, please see my initial post [1].
>> 
>> This version is rebased on the current acme/perf/core and it's mainly
>> changed due to a refactoring of gtk browser.
>> 
>> You can get this via 'perf/group-v8' branch on my tree:
>> 
>> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
>> 
>> Any comments are welcome, thanks,
>
> It would be great if examples of this in use were provided.
>
> Detailed ones at that, showing how things were in the past, how the info
> can be retrieved when using 'perf report --stdio', perhaps 'perf evlist'
> can show the stored group information too, how the 'perf report' output
> looks like when showing group info, things like that.

I think most of aforementioned things were on the initial post.  I
thought it's too verbose to be contained to the cover letter every time
so I just put the link.

But I'll include it next time and work on the perf evlist too.

Thanks,
Namhyung

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

* Re: [PATCH 06/13] perf ui/hist: Add support for event group view
  2013-01-16  9:22     ` Namhyung Kim
@ 2013-01-16 18:14       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-16 18:14 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Em Wed, Jan 16, 2013 at 06:22:49PM +0900, Namhyung Kim escreveu:
> On Tue, 15 Jan 2013 15:31:10 -0300, Arnaldo Carvalho de Melo wrote:
> > Em Tue, Jan 15, 2013 at 04:31:50PM +0900, Namhyung Kim escreveu:
> >> From: Namhyung Kim <namhyung.kim@lge.com>
> >> 
> >> Show group members' overhead also when showing the leader's if event
> >> group is enabled.  Use macro for defining hpp functions which looks
> >> almost identical.
> >> 
> >> Thanks to Arnaldo for suggesting a better way to print group members
> >> without allocating temporary array.
> >
> > Thanks! Its a pity the patch ended up mixing up things, I'll have to
> > apply it and look at the end result.
> 
> Do you mean I have to separate this into two - one for converting to
> macro and another for event group view itself?

If you can, please, that way we may see more clearly each of these
changes in the separated patches.

Thanks,

- Arnaldo

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

* Re: [PATCH 08/13] perf gtk/browser: Add support for event group view
  2013-01-16 10:25     ` Namhyung Kim
@ 2013-01-16 18:28       ` Arnaldo Carvalho de Melo
  2013-01-22  5:58         ` Namhyung Kim
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-16 18:28 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

Em Wed, Jan 16, 2013 at 07:25:02PM +0900, Namhyung Kim escreveu:
> Adding current header name to event name will fix the problem but it
> probably occupies too much screen width especially for long named
> tracepoint or PMU-specific events like
> "compaction:mm_compaction_isolate_migratepages".
> 
>   Overhead/branches  Overhead/branch-misses  sys/branches  sys/branch-misses  usr/branches  usr/branch-misses  Command  Shared Object   Symbol
>   .................  ......................  ............  .................  ............  .................  .......  .............  .......
>              98.32%                  31.16%         0.00%              0.00%        98.32%             31.16%    a.out          a.out  [.] foo
> 
> 
> If you have a better idea or other way to place the cursor without
> printing bogus 0.00% on GTK, please let me know.

Compacting it using an extra line:

 Overhead...............  sys....................  usr....................
 branches  branch-misses  branches  branch-misses  branches  branch-misses  Command  Shared Object   Symbol
 ........  .............  ........  .............  ........  .............  .......  .............  .......
   98.32%         31.16%     0.00%          0.00%    98.32%         31.16%    a.out          a.out  [.] foo

It could even use some reference:

 Overhead.....................  sys.........  usr...........
 branches(1)  branch-misses(2)  (1)    (2)    (1)     (2)     Command  Shared Object   Symbol
 ...........  ................  .....  .....  ......  ......  .......  .............  .......
      98.32%            31.16%  0.00%  0.00%  98.32%  31.16%    a.out          a.out  [.] foo

The (1) could be done with a superscript number or even just using a
different fore/background color, to use fewer columns.

One other way, that would scale for really long event names, would be to
have the event list in the first few lines and then:

Events:
1. branches
2. branch-misses

 Overhead......  sys.........  usr...........
 (1)     (2)     (1)    (2)    (1)     (2)     Command  Shared Object   Symbol
 ......  ......  .....  .....  ......  ......  .......  .............  .......
 98.32%  31.16%  0.00%  0.00%  98.32%  31.16%   a.out           a.out  [.] foo

I think you could switch to/from each of these forms using a hotkey,
that would influence how the hist_entry__snprintf() routine would work,
either using perf_evsel__name() or evsel->idx :-)

This way if at some point the user wants to expand/compress the lines,
it will be possible to do so quickly, just pressing the hotkey.

- Arnaldo

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

* Re: [PATCHSET 00/13] perf report: Add support for event group view (v8)
  2013-01-16 10:33   ` Namhyung Kim
@ 2013-01-16 18:29     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-16 18:29 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim

Em Wed, Jan 16, 2013 at 07:33:52PM +0900, Namhyung Kim escreveu:
> On Tue, 15 Jan 2013 15:38:58 -0300, Arnaldo Carvalho de Melo wrote:
> > It would be great if examples of this in use were provided.

> > Detailed ones at that, showing how things were in the past, how the info
> > can be retrieved when using 'perf report --stdio', perhaps 'perf evlist'
> > can show the stored group information too, how the 'perf report' output
> > looks like when showing group info, things like that.

> I think most of aforementioned things were on the initial post.  I
> thought it's too verbose to be contained to the cover letter every time
> so I just put the link.

> But I'll include it next time and work on the perf evlist too.

Thank you!

- Arnaldo

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

* Re: [PATCH 08/13] perf gtk/browser: Add support for event group view
  2013-01-16 18:28       ` Arnaldo Carvalho de Melo
@ 2013-01-22  5:58         ` Namhyung Kim
  2013-01-23 17:59           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 29+ messages in thread
From: Namhyung Kim @ 2013-01-22  5:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

Hi Arnaldo,

On Wed, 16 Jan 2013 15:28:59 -0300, Arnaldo Carvalho de Melo wrote:
> Em Wed, Jan 16, 2013 at 07:25:02PM +0900, Namhyung Kim escreveu:
>> Adding current header name to event name will fix the problem but it
>> probably occupies too much screen width especially for long named
>> tracepoint or PMU-specific events like
>> "compaction:mm_compaction_isolate_migratepages".
>> 
>>   Overhead/branches  Overhead/branch-misses  sys/branches  sys/branch-misses  usr/branches  usr/branch-misses  Command  Shared Object   Symbol
>>   .................  ......................  ............  .................  ............  .................  .......  .............  .......
>>              98.32%                  31.16%         0.00%              0.00%        98.32%             31.16%    a.out          a.out  [.] foo
>> 
>> 
>> If you have a better idea or other way to place the cursor without
>> printing bogus 0.00% on GTK, please let me know.
>
> Compacting it using an extra line:
>
>  Overhead...............  sys....................  usr....................
>  branches  branch-misses  branches  branch-misses  branches  branch-misses  Command  Shared Object   Symbol
>  ........  .............  ........  .............  ........  .............  .......  .............  .......
>    98.32%         31.16%     0.00%          0.00%    98.32%         31.16%    a.out          a.out  [.] foo
>
> It could even use some reference:
>
>  Overhead.....................  sys.........  usr...........
>  branches(1)  branch-misses(2)  (1)    (2)    (1)     (2)     Command  Shared Object   Symbol
>  ...........  ................  .....  .....  ......  ......  .......  .............  .......
>       98.32%            31.16%  0.00%  0.00%  98.32%  31.16%    a.out          a.out  [.] foo
>
> The (1) could be done with a superscript number or even just using a
> different fore/background color, to use fewer columns.
>
> One other way, that would scale for really long event names, would be to
> have the event list in the first few lines and then:
>
> Events:
> 1. branches
> 2. branch-misses
>
>  Overhead......  sys.........  usr...........
>  (1)     (2)     (1)    (2)    (1)     (2)     Command  Shared Object   Symbol
>  ......  ......  .....  .....  ......  ......  .......  .............  .......
>  98.32%  31.16%  0.00%  0.00%  98.32%  31.16%   a.out           a.out  [.] foo
>
> I think you could switch to/from each of these forms using a hotkey,
> that would influence how the hist_entry__snprintf() routine would work,
> either using perf_evsel__name() or evsel->idx :-)
>
> This way if at some point the user wants to expand/compress the lines,
> it will be possible to do so quickly, just pressing the hotkey.

By saying hotkey, I guess you meant to use it for TUI.  However TUI
doesn't provide those header lines. ;-)

As this extra line (and hotkey) thing might add complexity to the
patchset, I'd like to separate it to a different work and to focus on
the basic feature with current behavior.  Is it acceptable for you?

Thanks,
Namhyung

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

* Re: [PATCH 08/13] perf gtk/browser: Add support for event group view
  2013-01-22  5:58         ` Namhyung Kim
@ 2013-01-23 17:59           ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-01-23 17:59 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, LKML, Jiri Olsa,
	Stephane Eranian, Namhyung Kim, Pekka Enberg

Em Tue, Jan 22, 2013 at 02:58:36PM +0900, Namhyung Kim escreveu:
> Hi Arnaldo,
> 
> On Wed, 16 Jan 2013 15:28:59 -0300, Arnaldo Carvalho de Melo wrote:
> > Em Wed, Jan 16, 2013 at 07:25:02PM +0900, Namhyung Kim escreveu:
> >> Adding current header name to event name will fix the problem but it
> >> probably occupies too much screen width especially for long named
> >> tracepoint or PMU-specific events like
> >> "compaction:mm_compaction_isolate_migratepages".
> >> 
> >>   Overhead/branches  Overhead/branch-misses  sys/branches  sys/branch-misses  usr/branches  usr/branch-misses  Command  Shared Object   Symbol
> >>   .................  ......................  ............  .................  ............  .................  .......  .............  .......
> >>              98.32%                  31.16%         0.00%              0.00%        98.32%             31.16%    a.out          a.out  [.] foo
> >> 
> >> 
> >> If you have a better idea or other way to place the cursor without
> >> printing bogus 0.00% on GTK, please let me know.
> >
> > Compacting it using an extra line:
> >
> >  Overhead...............  sys....................  usr....................
> >  branches  branch-misses  branches  branch-misses  branches  branch-misses  Command  Shared Object   Symbol
> >  ........  .............  ........  .............  ........  .............  .......  .............  .......
> >    98.32%         31.16%     0.00%          0.00%    98.32%         31.16%    a.out          a.out  [.] foo
> >
> > It could even use some reference:
> >
> >  Overhead.....................  sys.........  usr...........
> >  branches(1)  branch-misses(2)  (1)    (2)    (1)     (2)     Command  Shared Object   Symbol
> >  ...........  ................  .....  .....  ......  ......  .......  .............  .......
> >       98.32%            31.16%  0.00%  0.00%  98.32%  31.16%    a.out          a.out  [.] foo
> >
> > The (1) could be done with a superscript number or even just using a
> > different fore/background color, to use fewer columns.
> >
> > One other way, that would scale for really long event names, would be to
> > have the event list in the first few lines and then:
> >
> > Events:
> > 1. branches
> > 2. branch-misses
> >
> >  Overhead......  sys.........  usr...........
> >  (1)     (2)     (1)    (2)    (1)     (2)     Command  Shared Object   Symbol
> >  ......  ......  .....  .....  ......  ......  .......  .............  .......
> >  98.32%  31.16%  0.00%  0.00%  98.32%  31.16%   a.out           a.out  [.] foo
> >
> > I think you could switch to/from each of these forms using a hotkey,
> > that would influence how the hist_entry__snprintf() routine would work,
> > either using perf_evsel__name() or evsel->idx :-)
> >
> > This way if at some point the user wants to expand/compress the lines,
> > it will be possible to do so quickly, just pressing the hotkey.
> 
> By saying hotkey, I guess you meant to use it for TUI.  However TUI
> doesn't provide those header lines. ;-)

See? I was trying to hit two rabbits with one stone, but you realised
that...

> As this extra line (and hotkey) thing might add complexity to the
> patchset, I'd like to separate it to a different work and to focus on
> the basic feature with current behavior.  Is it acceptable for you?

Sure thing.

- Arnaldo

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

end of thread, other threads:[~2013-01-23 17:59 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-15  7:31 [PATCHSET 00/13] perf report: Add support for event group view (v8) Namhyung Kim
2013-01-15  7:31 ` [PATCH 01/13] perf tools: Keep group information Namhyung Kim
2013-01-15  7:31 ` [PATCH 02/13] perf tests: Add group test conditions Namhyung Kim
2013-01-15  7:31 ` [PATCH 03/13] perf header: Add HEADER_GROUP_DESC feature Namhyung Kim
2013-01-15  7:31 ` [PATCH 04/13] perf report: Make another loop for linking group hists Namhyung Kim
2013-01-15  7:31 ` [PATCH 05/13] perf hists: Resort hist entries using group members for output Namhyung Kim
2013-01-15 18:29   ` Arnaldo Carvalho de Melo
2013-01-16  9:20     ` Namhyung Kim
2013-01-15  7:31 ` [PATCH 06/13] perf ui/hist: Add support for event group view Namhyung Kim
2013-01-15 18:31   ` Arnaldo Carvalho de Melo
2013-01-16  9:22     ` Namhyung Kim
2013-01-16 18:14       ` Arnaldo Carvalho de Melo
2013-01-15  7:31 ` [PATCH 07/13] perf hist browser: " Namhyung Kim
2013-01-15 18:32   ` Arnaldo Carvalho de Melo
2013-01-16  9:52     ` Namhyung Kim
2013-01-15  7:31 ` [PATCH 08/13] perf gtk/browser: " Namhyung Kim
2013-01-15 18:34   ` Arnaldo Carvalho de Melo
2013-01-16 10:25     ` Namhyung Kim
2013-01-16 18:28       ` Arnaldo Carvalho de Melo
2013-01-22  5:58         ` Namhyung Kim
2013-01-23 17:59           ` Arnaldo Carvalho de Melo
2013-01-15  7:31 ` [PATCH 09/13] perf gtk/browser: Trim column header string when event group enabled Namhyung Kim
2013-01-15  7:31 ` [PATCH 10/13] perf report: Bypass non-leader events when event group is enabled Namhyung Kim
2013-01-15  7:31 ` [PATCH 11/13] perf report: Show group description " Namhyung Kim
2013-01-15  7:31 ` [PATCH 12/13] perf report: Add --group option Namhyung Kim
2013-01-15  7:31 ` [PATCH 13/13] perf report: Add report.group config option Namhyung Kim
2013-01-15 18:38 ` [PATCHSET 00/13] perf report: Add support for event group view (v8) Arnaldo Carvalho de Melo
2013-01-16 10:33   ` Namhyung Kim
2013-01-16 18:29     ` Arnaldo Carvalho de Melo

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).