perf report: Add support for event group view (v5)
Namhyung Kim
maintainercover perf report: Add support for event group view (v5)
Hi,
This is my v5 of event group view support patchset.
For basic idea and usage example, please see my original post [1].
This is mostly for rebasing on acme/perf/core, and report.group config option is added for those who wants to enable it by default.
You can get this series via my tree at:
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git perf/group-v5
Any comments are welcome, thanks,
Namhyung
v4 -> v5:
* rebase on top of current 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 (12):
perf tools: Keep group information
perf header: Add HEADER_GROUP_DESC feature
perf hists: Collapse group hist_entries to a leader perf hists: Maintain total periods of group members in the leader perf report: Make another loop for output resorting perf ui/hist: Add support for event group view
perf ui/browser: Add support for event group view
perf ui/gtk: Add support for event group view
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/builtin-record.c | 3 + tools/perf/builtin-report.c | 42 +++++++++++ tools/perf/ui/browsers/hists.c | 101 ++++++++++++++++++++++++-- tools/perf/ui/gtk/browser.c | 72 +++++++++++++++---- tools/perf/ui/hist.c | 71 +++++++++++++++++-- tools/perf/ui/stdio/hist.c | 2 + tools/perf/util/evlist.c | 10 ++- tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.c | 25 +++++++ tools/perf/util/evsel.h | 23 ++++++ tools/perf/util/header.c | 152 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 2 + tools/perf/util/hist.c | 133 ++++++++++++++++++++++++++++++++--- tools/perf/util/hist.h | 1 + tools/perf/util/parse-events.c | 1 + tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.y | 10 +++ tools/perf/util/sort.h | 1 + tools/perf/util/symbol.c | 4 ++ tools/perf/util/symbol.h | 3 +- 20 files changed, 620 insertions(+), 38 deletions(-)
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 1/12 perf tools: Keep group information
From: Namhyung Kim <[email protected]>
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.
--- tools/perf/util/evlist.c | 10 ++++++++-- tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.h | 10 ++++++++++ tools/perf/util/parse-events.c | 1 + tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.y | 10 ++++++++++ 6 files changed, 31 insertions(+), 2 deletions(-)
tools/perf/util/evlist.c +8 -2
@@ -111,20 +111,26 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,void __perf_evlist__set_leader (struct list_head *list) {struct perf_evsel *evsel, *leader; +int count =0 ; leader = list_entry(list->next, struct perf_evsel, node); leader->leader =NULL ;list_for_each_entry (evsel, list, node) { -if (evsel != leader) +if (evsel != leader) { evsel->leader = leader; + evsel->group_idx = count++; + } } + leader->nr_members = count; }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)
tools/perf/util/evlist.h +1 -0
@@ -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;
tools/perf/util/evsel.h +10 -0
@@ -74,6 +74,10 @@ struct perf_evsel {int exclude_GH;struct perf_evsel *leader;char *group_name; +union { +int nr_members; +int group_idx; + }; };struct cpu_map ;
@@ -225,4 +229,10 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) { return list_entry(evsel->node.next, struct perf_evsel, node); } + +/* Treat a non-group event as a leader */ +static inline bool perf_evsel__is_group_leader (struct perf_evsel *evsel) +{ +return evsel->leader ==NULL ; +}#endif /* __PERF_EVSEL_H */
tools/perf/util/parse-events.c +1 -0
@@ -819,6 +819,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 ; }
tools/perf/util/parse-events.h +1 -0
@@ -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 {
tools/perf/util/parse-events.y +10 -0
@@ -122,6 +122,11 @@ group_def: PE_NAME '{' events '}' { struct list_head *list = $3; + struct parse_events_data__events *data = _data; + + /* Count groups only have more than 1 members */ + if (!list_is_last(list->next, list)) + data->nr_groups++; parse_events__set_leader($1, list); $$ = list;
@@ -130,6 +135,11 @@ PE_NAME '{' events '}' '{' events '}' { struct list_head *list = $2; + struct parse_events_data__events *data = _data; + + /* Count groups only have more than 1 members */ + if (!list_is_last(list->next, list)) + data->nr_groups++; parse_events__set_leader(NULL, list); $$ = list;
Signature · 1 line
1.7.9.2
Re: [PATCH 01/12] perf tools: Keep group information
Em Sat, Nov 10, 2012 at 01:43:23AM +0900, Namhyung Kim escreveu:
Quoted 6 lines
From: Namhyung Kim <[email protected]>
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.
We don't need to add a group_idx, we can get it using evsel->idx - evsel->leader->idx, interdiff of this patch to what I think is equivalent:
tools/perf/util/evlist.c +3 -5
@@ -111,18 +111,16 @@void __perf_evlist__set_leader (struct list_head *list) {struct perf_evsel *evsel, *leader; -int count =0 ; leader = list_entry(list->next, struct perf_evsel, node); + evsel = list_entry(list->prev, struct perf_evsel, node); leader->leader =NULL ; + leader->nr_members = evsel->idx - leader->idx +1 ;list_for_each_entry (evsel, list, node) { -if (evsel != leader) { +if (evsel != leader) evsel->leader = leader; - evsel->group_idx = count++; - } } - leader->nr_members = count; }void perf_evlist__set_leader (struct perf_evlist *evlist)
tools/perf/util/evsel.h +10 -4
@@ -72,12 +72,9 @@bool needs_swap;/* parse modifier helper */ int exclude_GH; +int nr_members;struct perf_evsel *leader;char *group_name; -union { -int nr_members; -int group_idx; - }; };struct cpu_map ;
@@ -237,2 +234,11 @@ } + +static inline int perf_evsel__group_idx (struct perf_evsel *evsel) +{ + if (perf_evsel__is_group_leader(evsel) +return 0 ; + +return evsel->idx - evsel->leader->idx; +} +#endif /* __PERF_EVSEL_H */
Namhyung Kim
maintainerRe: [PATCH 01/12] perf tools: Keep group information
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Sat, Nov 10, 2012 at 01:43:23AM +0900, Namhyung Kim escreveu:
Quoted 6 lines
From: Namhyung Kim <[email protected]>
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.
We don't need to add a
group_idx, we can get it usingevsel->idx-evsel->leader->idx, interdiff of this patch to what I think is equivalent:
Looks good to me. Just a comment below..
Quoted 5 lines
diff -u
b/tools/perf/util/evlist.cb/tools/perf/util/evlist.c
tools/perf/util/evlist.c line 118
Quoted 9 lines
tools/perf/util/evlist.c +2
-1@@ -111,18 +111,16 @@void __perf_evlist__set_leader (struct list_head *list) {struct perf_evsel *evsel, *leader; -int count =0 ; leader = list_entry(list->next, struct perf_evsel, node); + evsel = list_entry(list->prev, struct perf_evsel, node); leader->leader =NULL ; + leader->nr_members = evsel->idx - leader->idx +1 ;
This will lead a off-by-one difference with my patches. I chose to use 0 nr_members for leader-only group. It was used for an additional allocation of group stats but it seems that it's not needed anymore with the hist_link change.
Thanks,
Namhyung
Namhyung Kim
maintainerPATCH 2/12 perf header: Add HEADER_GROUP_DESC feature
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Save group relationship information so that it can be restored when perf report is running.
--- tools/perf/builtin-record.c | 3 + tools/perf/util/header.c | 152 +++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 2 + 3 files changed, 157 insertions(+)
tools/perf/builtin-record.c +3 -0
@@ -587,6 +587,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() */
tools/perf/util/header.c +152 -0
176 lines not on this page · raw message
tools/perf/util/header.h +2 -0
@@ -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 {
Signature · 1 line
1.7.9.2
Re: [PATCH 02/12] perf header: Add HEADER_GROUP_DESC feature
Em Sat, Nov 10, 2012 at 01:43:24AM +0900, Namhyung Kim escreveu:
Quoted 9 lines
From: Namhyung Kim <[email protected]>
Save group relationship information so that it can be restored when perf report is running.
Cc Jiri Olsa <[email protected]>Cc Stephane Eranian <[email protected]>Acked-by Jiri Olsa <[email protected]>Signed-off-by Namhyung Kim <[email protected]>
<SNIP>
tools/perf/util/header.c error: · line 2014
Quoted 5 lines
tools/perf/util/header.c +5
-0+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 ;
why initialize ret if the first thing you do with it is...
tools/perf/util/header.c error: · line 2024
Quoted 10 lines
tools/perf/util/header.c +10
-0+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; + + ret =read (fd, &nr_groups,sizeof (nr_groups));
assign another value?
We need to use readn instead of read, and not use ret here, just do
if (read(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups))
Quoted 14 lines
tools/perf/util/header.c +14
-0+if (ret !=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)
tools/perf/util/header.c error: · line 2048
Quoted 10 lines
tools/perf/util/header.c +10
-0+return -1 ; + +for (i =0 ; i < nr_groups; i++) { + desc[i].name =do_read_string (fd, ph); +if (!desc[i].name) + goto out_free; + + ret =read (fd, &desc[i].leader_idx,sizeof (u32)); +if (ret !=sizeof (u32)) + goto out_free;
ditto
tools/perf/util/header.c error: · line 2052
Quoted 4 lines
tools/perf/util/header.c +4
-0+ + ret =read (fd, &desc[i].nr_members,sizeof (u32)); +if (ret !=sizeof (u32)) + goto out_free;
ditto
Quoted 7 lines
tools/perf/util/header.c +7
-0+ +if (ph->needs_swap) { + desc[i].leader_idx =bswap_32 (desc[i].leader_idx); + desc[i].nr_members =bswap_32 (desc[i].nr_members); + } + } +
tools/perf/util/header.c error: · line 2069
Quoted 10 lines
tools/perf/util/header.c +10
-0+/* +* 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 =NULL ;
Humm, isn't it better to set evsel->leader to evsel, that way all members in a group have its evsel->leader pointing to the leader and for things like the group idx we can do just:
evsel->idx - evsel->leader->idx
avoiding the need to special case the leader, will do that.
tools/perf/util/header.c error: · line 2076
Quoted 7 lines
tools/perf/util/header.c +7
-0+/* {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; + +BUG_ON (i >= nr_groups); +BUG_ON (nr >0 );
BUG_ON here is way too extreme, we should just bail out, testing and if the problem is found, goto out_free
tools/perf/util/header.c error: · line 2081
Quoted 4 lines
tools/perf/util/header.c +4
-0+ leader = evsel; + nr = evsel->nr_members; + i++; + }else if (nr) {
Humm, do we really need to test against nr? Or even use nr at all?
tools/perf/util/header.c error: · line 2091
Quoted 10 lines
tools/perf/util/header.c +10
-0+/* This is a group member */ + evsel->leader = leader; +/* group_idx starts from 0 */ + evsel->group_idx = leader->nr_members - nr; + nr--; + } + } + +BUG_ON (i != nr_groups); +BUG_ON (nr !=0 );
Too extreme, goto out_free.
And just before out_free we need to set ret = 0, otherwise we will return...
tools/perf/util/header.c error: · line 2096
Quoted 4 lines
tools/perf/util/header.c +4
-0+out_free: +while ((int ) --i >=0 ) +free (desc[i].name); +free (desc);
here, whatever value was in ret, in this patch it will be, if all goes well, sizeof(u32) :-)
Quoted 19 lines
tools/perf/util/header.c +4
-0+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);@@ -1986,6 +2137,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 {tools/perf/util/header.h +0
-0
tools/perf/util/header.h enum { · line 35
Quoted 7 lines
tools/perf/util/header.h +1
-0@@ -29,6 +29,7 @@ enum {HEADER_NUMA_TOPOLOGY ,HEADER_BRANCH_STACK ,HEADER_PMU_MAPPINGS , +HEADER_GROUP_DESC ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Here we're adding holes to the struct:
tools/perf/util/header.h struct perf_session_env { · line 81
Quoted 3 lines
tools/perf/util/header.h +0
-0@@ -79,6 +80,7 @@ struct perf_session_env {char *numa_nodes;int nr_pmu_mappings;
4 byte hole
tools/perf/util/header.h struct perf_session_env { · line 82
Quoted 1 line
tools/perf/util/header.h +0
-0char *pmu_mappings;
4 byte hole
tools/perf/util/header.h struct perf_session_env { · line 83
Quoted 1 line
tools/perf/util/header.h +1
-0+int nr_groups;
I'm working on a patch implementing my suggestions.
Quoted 5 lines
tools/perf/util/header.h +0
-0};struct perf_header {Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerRe: [PATCH 02/12] perf header: Add HEADER_GROUP_DESC feature
Quoted 34 lines · Arnaldo Carvalho de Melo
Em Sat, Nov 10, 2012 at 01:43:24AM +0900, Namhyung Kim escreveu:
Quoted 9 lines
From: Namhyung Kim <[email protected]>
Save group relationship information so that it can be restored when perf report is running.
Cc Jiri Olsa <[email protected]>Cc Stephane Eranian <[email protected]>Acked-by Jiri Olsa <[email protected]>Signed-off-by Namhyung Kim <[email protected]><SNIP>
tools/perf/util/header.c error: · line 2014
Quoted 5 lines
tools/perf/util/header.c +5
-0+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 ;why initialize ret if the first thing you do with it is...
tools/perf/util/header.c error: · line 2024
Quoted 10 lines
tools/perf/util/header.c +10
-0+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; + + ret =read (fd, &nr_groups,sizeof (nr_groups));assign another value?
Quoted 2 lines
We need to use readn instead of read, and not use ret here, just do
if (read(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups))
Will do.
Quoted 57 lines
Quoted 15 lines
tools/perf/util/header.c +14
-0+if (ret !=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)tools/perf/util/header.c error: · line 2048
Quoted 10 lines
tools/perf/util/header.c +10
-0+return -1 ; + +for (i =0 ; i < nr_groups; i++) { + desc[i].name =do_read_string (fd, ph); +if (!desc[i].name) + goto out_free; + + ret =read (fd, &desc[i].leader_idx,sizeof (u32)); +if (ret !=sizeof (u32)) + goto out_free;ditto
tools/perf/util/header.c error: · line 2052
Quoted 4 lines
tools/perf/util/header.c +4
-0+ + ret =read (fd, &desc[i].nr_members,sizeof (u32)); +if (ret !=sizeof (u32)) + goto out_free;ditto
Quoted 7 lines
tools/perf/util/header.c +7
-0+ +if (ph->needs_swap) { + desc[i].leader_idx =bswap_32 (desc[i].leader_idx); + desc[i].nr_members =bswap_32 (desc[i].nr_members); + } + } +tools/perf/util/header.c error: · line 2069
Quoted 10 lines
tools/perf/util/header.c +10
-0+/* +* 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 =NULL ;Humm, isn't it better to set
evsel->leaderto evsel, that way all members in a group have itsevsel->leaderpointing to the leader and for things like the group idx we can do just:
Quoted 3 lines
evsel->idx - evsel->leader->idxavoiding the need to special case the leader, will do that.
I just followed the existing behavior. I'm open to changing it. :)
Quoted 11 lines
tools/perf/util/header.c error: · line 2076
Quoted 8 lines
tools/perf/util/header.c +7
-0+/* {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; + +BUG_ON (i >= nr_groups); +BUG_ON (nr >0 );
BUG_ONhere is way too extreme, we should just bail out, testing and if the problem is found, gotoout_free
Okay, it was there to help me debugging the code. Will change.
Quoted 7 lines
tools/perf/util/header.c error: · line 2081
Quoted 5 lines
tools/perf/util/header.c +4
-0+ leader = evsel; + nr = evsel->nr_members; + i++; + }else if (nr) {Humm, do we really need to test against nr? Or even use nr at all?
The group descriptor misses leader-only groups intentionally. In that case I wanted to skip those events with nr == 0.
Quoted 14 lines
tools/perf/util/header.c error: · line 2091
Quoted 11 lines
tools/perf/util/header.c +10
-0+/* This is a group member */ + evsel->leader = leader; +/* group_idx starts from 0 */ + evsel->group_idx = leader->nr_members - nr; + nr--; + } + } + +BUG_ON (i != nr_groups); +BUG_ON (nr !=0 );Too extreme, goto
out_free.
Quoted 2 lines
And just before
out_freewe need to set ret = 0, otherwise we will return...
Right, will do.
Quoted 44 lines
tools/perf/util/header.c error: · line 2096
Quoted 5 lines
tools/perf/util/header.c +4
-0+out_free: +while ((int ) --i >=0 ) +free (desc[i].name); +free (desc);here, whatever value was in ret, in this patch it will be, if all goes well, sizeof(u32) :-)
Quoted 19 lines
tools/perf/util/header.c +4
-0+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);@@ -1986,6 +2137,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 {tools/perf/util/header.h +0
-0tools/perf/util/header.h enum { · line 35
Quoted 7 lines
tools/perf/util/header.h +1
-0@@ -29,6 +29,7 @@ enum {HEADER_NUMA_TOPOLOGY ,HEADER_BRANCH_STACK ,HEADER_PMU_MAPPINGS , +HEADER_GROUP_DESC ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };Here we're adding holes to the struct:
tools/perf/util/header.h struct perf_session_env { · line 81
Quoted 3 lines
tools/perf/util/header.h +0
-0@@ -79,6 +80,7 @@ struct perf_session_env {char *numa_nodes;int nr_pmu_mappings;4 byte hole
Quoted 3 lines
tools/perf/util/header.h struct perf_session_env { · line 82
Quoted 1 line
tools/perf/util/header.h +0
-0char *pmu_mappings;4 byte hole
Yes, I thought it's a in-memory struct for a session, so a couple of holes doesn't matter much. So I just wanted to keep the struct in a consistent and straight-forward way.
Quoted 4 lines
tools/perf/util/header.h struct perf_session_env { · line 83
Quoted 2 lines
tools/perf/util/header.h +1
-0+int nr_groups;I'm working on a patch implementing my suggestions.
Great!
Thanks,
Namhyung
Namhyung Kim
maintainerPATCH 3/12 perf hists: Collapse group hist_entries to a leader
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
To support viewing an event group together, collapse all of members in the group to the leader's tree. The entries in the leaders' tree will have group_stats to store those information.
This patch introduced an additional field 'event_group' in symbol_conf to distinguish whether event grouping is enabled or not.
--- tools/perf/util/evsel.h | 5 +++ tools/perf/util/hist.c | 108 ++++++++++++++++++++++++++++++++++++++++++---- tools/perf/util/sort.h | 1 + tools/perf/util/symbol.c | 4 ++ tools/perf/util/symbol.h | 3 +- 5 files changed, 112 insertions(+), 9 deletions(-)
tools/perf/util/evsel.h +5 -0
@@ -235,4 +235,9 @@ static inline bool perf_evsel__is_group_leader(struct perf_evsel *evsel) {return evsel->leader ==NULL ; } + +static inline struct perf_evsel *hists_2_evsel (struct hists *hists) +{ + return container_of(hists, struct perf_evsel, hists); +}#endif /* __PERF_EVSEL_H */
tools/perf/util/hist.c +100 -8
198 lines not on this page · raw message
tools/perf/util/sort.h +1 -0
@@ -78,6 +78,7 @@ struct hist_entry {struct rb_node rb_node_in;struct rb_node rb_node;struct he_stat stat; +struct he_stat *group_stats;struct map_symbol ms;struct thread *thread;u64 ip;
tools/perf/util/symbol.c +4 -0
@@ -11,6 +11,7 @@#include <inttypes.h> #include "build-id.h" #include "util.h" +#include "sort.h" #include "debug.h" #include "symbol.h" #include "strlist.h"
@@ -1649,6 +1650,9 @@ int symbol__init(void) symbol_conf.kptr_restrict =symbol__read_kptr_restrict (); +if (symbol_conf.event_group) + sort__need_collapse =1 ; + symbol_conf.initialized = true;return 0 ;
tools/perf/util/symbol.h +2 -1
@@ -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,
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 4/12 perf hists: Maintain total periods of group members in the leader
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Like group_stats in hist_entry, total periods information also need to be known to the leader.
--- tools/perf/util/hist.c | 25 +++++++++++++++++++++++++ tools/perf/util/hist.h | 1 + 2 files changed, 26 insertions(+)
tools/perf/util/hist.c +25 -0
@@ -194,6 +194,28 @@ static void hist_entry__add_group_stat(struct hist_entry *he_dest,he_stat__add_stat (&he_dest->group_stats[evsel->group_idx], src); } +static void hists__add_group_stat (struct hists *hists) +{ +struct perf_evsel *evsel =hists_2_evsel (hists); +struct perf_evsel *leader = evsel->leader; +struct hists *leader_hists; + +if (perf_evsel__is_group_leader (evsel)) +return ; + + leader_hists = &leader->hists; + +if (!leader_hists->group_stats) { + leader_hists->group_stats =calloc (leader->nr_members, +sizeof (struct events_stats )); +if (!leader_hists->group_stats) +return ; + } + +memcpy (&leader_hists->group_stats[evsel->group_idx], + &hists->stats,sizeof (struct events_stats )); +} +static void hist_entry__decay (struct hist_entry *he) { he->stat.period = (he->stat.period *7 ) /8 ;
@@ -561,6 +583,9 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded)hists__apply_filters (hists, n); } } + +if (symbol_conf.event_group) +hists__add_group_stat (hists); }void hists__collapse_resort (struct hists *hists)
tools/perf/util/hist.h +1 -0
@@ -67,6 +67,7 @@ struct hists {const char *symbol_filter_str;pthread_mutex_t lock;struct events_stats stats; +struct events_stats *group_stats;u64 event_stream;u16 col_len[HISTC_NR_COLS ]; };
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 5/12 perf report: Make another loop for output resorting
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Now the event grouping viewing requires collapsing all members in a group to the leader. Thus hists__output_resort should be called after collapsing all entries in evlist.
--- tools/perf/builtin-report.c | 5 +++++ 1 file changed, 5 insertions(+)
tools/perf/builtin-report.c +5 -0
@@ -416,6 +416,11 @@ static int __cmd_report(struct perf_report *rep) hists->symbol_filter_str = rep->symbol_filter_str;hists__collapse_resort (hists); + } + +list_for_each_entry (pos, &session->evlist->entries, node) { +struct hists *hists = &pos->hists; +hists__output_resort (hists); nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE ]; }
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 6/12 perf ui/hist: Add support for event group view
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down.
--- tools/perf/ui/hist.c | 66 ++++++++++++++++++++++++++++++++++++++++---- tools/perf/ui/stdio/hist.c | 2 ++ 2 files changed, 63 insertions(+), 5 deletions(-)
tools/perf/ui/hist.c +61 -5
@@ -3,34 +3,90 @@#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" ); +int len =8 ; + +if (symbol_conf.event_group) { +struct perf_evsel *evsel = hpp->ptr; + +BUG_ON (!perf_evsel__is_group_leader (evsel)); + + len += evsel->nr_members *8 ; + } +return scnprintf (hpp->buf, hpp->size,"%*s" , len,"Overhead" ); } -static int hpp__width_overhead (struct perf_hpp *hpp__maybe_unused ) +static int hpp__width_overhead (struct perf_hpp *hpp) { -return 8 ; +int len =8 ; + +if (symbol_conf.event_group) { +struct perf_evsel *evsel = hpp->ptr; + + len += evsel->nr_members *8 ; + } +return len; }static int hpp__color_overhead (struct perf_hpp *hpp,struct hist_entry *he) { +int ret;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); + ret =percent_color_snprintf (hpp->buf, hpp->size," %6.2f%%" , percent); + +if (symbol_conf.event_group) { +int i; +struct perf_evsel *evsel =hists_2_evsel (hists); + +for (i =0 ; i < evsel->nr_members; i++) { +u64 period = he->group_stats[i].period; +u64 total = hists->group_stats[i].total_period; + + percent =100.0 * period / total; + ret +=percent_color_snprintf (hpp->buf + ret, + hpp->size - ret, +" %6.2f%%" , percent); + } + + } +return ret; }static int hpp__entry_overhead (struct perf_hpp *hpp,struct hist_entry *he) { +int ret;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%%" ; -return scnprintf (hpp->buf, hpp->size, fmt, percent); + ret =scnprintf (hpp->buf, hpp->size, fmt, percent); + +if (symbol_conf.event_group) { +int i; +struct perf_evsel *evsel =hists_2_evsel (hists); + +for (i =0 ; i < evsel->nr_members; i++) { +u64 period = he->group_stats[i].period; +u64 total = hists->group_stats[i].total_period; + +if (symbol_conf.field_sep) { + ret +=scnprintf (hpp->buf + ret, + hpp->size - ret," " ); + } + percent =100.0 * period / total; + ret +=scnprintf (hpp->buf + ret, hpp->size - ret, + fmt, percent); + } + + } +return ret; }static int hpp__header_overhead_sys (struct perf_hpp *hpp)
tools/perf/ui/stdio/hist.c +2 -0
@@ -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)
@@ -346,6 +347,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_2_evsel (hists), };bool first = true;
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 7/12 perf ui/browser: Add support for event group view
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down.
--- tools/perf/ui/browsers/hists.c | 29 ++++++++++++++++++++++++++++- tools/perf/ui/hist.c | 5 ++++- 2 files changed, 32 insertions(+), 2 deletions(-)
tools/perf/ui/browsers/hists.c +28 -1
@@ -567,6 +567,34 @@ static int hist_browser__show_callchain(struct hist_browser *browser,return row - first_row; } +static int hist_browser__hpp_color_overhead (struct perf_hpp *hpp, +struct hist_entry *he) +{ +int ret; +struct hists *hists = he->hists; +double percent =100.0 * he->stat.period / hists->stats.total_period; + +/* the leader determines color */ + *(double *) hpp->ptr = percent; + + ret =scnprintf (hpp->buf, hpp->size,"%6.2f%%" , percent); + +if (symbol_conf.event_group) { +int i; +struct perf_evsel *evsel =hists_2_evsel (hists); + +for (i =0 ; i < evsel->nr_members; i++) { +u64 period = he->group_stats[i].period; +u64 total = hists->group_stats[i].total_period; + + percent =100.0 * period / total; + ret +=scnprintf (hpp->buf + ret, hpp->size - ret, +" %6.2f%%" , percent); + } + } +return ret; +} +#define HPP__COLOR_FN (_name, _field) \ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \
@@ -577,7 +605,6 @@ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \return scnprintf (hpp->buf, hpp->size,"%6.2f%%" , percent); \ } -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)
tools/perf/ui/hist.c +4 -1
@@ -562,6 +562,9 @@ unsigned int hists__sort_list_width(struct hists *hists) {struct sort_entry *se;int i, ret =0 ; +struct perf_hpp dummy_hpp = { + .ptr =hists_2_evsel (hists), + };for (i =0 ; i <PERF_HPP__MAX_INDEX ; i++) {if (!perf_hpp__format[i].cond)
@@ -569,7 +572,7 @@ unsigned int hists__sort_list_width(struct hists *hists)if (i) ret +=2 ; - ret += perf_hpp__format[i].width (NULL ); + ret += perf_hpp__format[i].width (&dummy_hpp); }list_for_each_entry (se, &hist_entry__sort_list, list)
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 8/12 perf ui/gtk: Add support for event group view
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down.
--- tools/perf/ui/gtk/browser.c | 60 +++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 14 deletions(-)
tools/perf/ui/gtk/browser.c +46 -14
@@ -45,26 +45,57 @@ static const char *perf_gtk__get_percent_color(double percent)return NULL ; } +static int perf_gtk__percent_color_snprintf (char *buf,size_t size, +u64 period,u64 total_period) +{ +int ret =0 ; +const char *markup; +double percent =100.0 * period / total_period; + + 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 perf_gtk__hpp_color_overhead (struct perf_hpp *hpp, +struct hist_entry *he) +{ +int ret; +struct hists *hists = he->hists; + + ret =perf_gtk__percent_color_snprintf (hpp->buf, hpp->size, + he->stat.period, hists->stats.total_period); + +if (symbol_conf.event_group) { +int i; +struct perf_evsel *evsel =hists_2_evsel (hists); + +for (i =0 ; i < evsel->nr_members; i++) { + ret +=scnprintf (hpp->buf + ret, hpp->size - ret," " ); + ret +=perf_gtk__percent_color_snprintf (hpp->buf + ret, + hpp->size - ret, + he->group_stats[i].period, + hists->group_stats[i].total_period); + } + } +return ret; +} +#define HPP__COLOR_FN (_name, _field) \ static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ 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; \ - \ - 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; \ + return perf_gtk__percent_color_snprintf(hpp->buf, hpp->size, \ + he->stat._field, he->hists->stats.total_period); \ } -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)
@@ -103,6 +134,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)struct perf_hpp hpp = { .buf = s, .size =sizeof (s), + .ptr =hists_2_evsel (hists), }; nr_cols =0 ;
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 9/12 perf report: Bypass non-leader events when event group is enabled
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
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.
--- tools/perf/builtin-report.c | 4 ++++ tools/perf/ui/browsers/hists.c | 41 ++++++++++++++++++++++++++++++++++------ tools/perf/ui/gtk/browser.c | 4 ++++ 3 files changed, 43 insertions(+), 6 deletions(-)
tools/perf/builtin-report.c +4 -0
@@ -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" );
tools/perf/ui/browsers/hists.c +35 -6
70 lines not on this page · raw message
tools/perf/ui/gtk/browser.c +4 -0
@@ -304,6 +304,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),
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 10/12 perf report: Show group description when event group is enabled
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
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.
--- tools/perf/builtin-report.c | 18 ++++++++++++++++++ tools/perf/ui/browsers/hists.c | 31 +++++++++++++++++++++++++++++++ tools/perf/ui/gtk/browser.c | 14 +++++++++++--- tools/perf/util/evsel.c | 25 +++++++++++++++++++++++++ tools/perf/util/evsel.h | 8 ++++++++ 5 files changed, 93 insertions(+), 3 deletions(-)
tools/perf/builtin-report.c +18 -0
@@ -299,6 +299,24 @@ 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_2_evsel (self); +char buf[512 ]; +size_t size =sizeof (buf); + +if (symbol_conf.event_group && evsel->nr_members) { +int i; +struct events_stats *stats; + +perf_evsel__group_desc (evsel, buf, size); + evname = buf; + +for (i =0 ; i < evsel->nr_members; i++) { + stats = &self->group_stats[i]; + + nr_samples += stats->nr_events[PERF_RECORD_SAMPLE ]; + nr_events += stats->total_period; + } + } nr_samples =convert_unit (nr_samples, &unit); ret =fprintf (fp,"# Samples: %lu%c" , nr_samples, unit);
tools/perf/ui/browsers/hists.c +31 -0
@@ -1125,6 +1125,24 @@ 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_2_evsel (hists); +char buf[512 ]; +size_t buflen =sizeof (buf); + +if (symbol_conf.event_group && evsel->nr_members) { +int i; +struct events_stats *stats; + +perf_evsel__group_desc (evsel, buf, buflen); + ev_name = buf; + +for (i =0 ; i < evsel->nr_members; i++) { + stats = &hists->group_stats[i]; + + nr_samples += stats->nr_events[PERF_RECORD_SAMPLE ]; + nr_events += stats->total_period; + } + } nr_samples =convert_unit (nr_samples, &unit); printed = scnprintf(bf, size,
@@ -1521,6 +1539,19 @@ 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) { +int i; +struct events_stats *stats; + + ev_name =perf_evsel__group_name (evsel); + +for (i =0 ; i < evsel->nr_members; i++) { + stats = &evsel->hists.group_stats[i]; + + nr_events += 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);
tools/perf/ui/gtk/browser.c +11 -3
@@ -303,10 +303,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) { +perf_evsel__group_desc (pos, buf, size); + evname = buf; + } + } scrolled_window =gtk_scrolled_window_new (NULL ,NULL );
tools/perf/util/evsel.c +25 -0
@@ -404,6 +404,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; +} +void perf_evsel__config (struct perf_evsel *evsel,struct perf_record_opts *opts,struct perf_evsel *first) {
tools/perf/util/evsel.h +8 -0
@@ -114,6 +114,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);
@@ -240,4 +242,10 @@ static inline struct perf_evsel *hists_2_evsel(struct hists *hists) { return container_of(hists, struct perf_evsel, hists); } + +#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 */
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 11/12 perf report: Add --group option
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Add --group option to enable event grouping. When enabled, all the group members information will be shown together with the leader.
--- tools/perf/builtin-report.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/builtin-report.c +2 -0
@@ -665,6 +665,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",
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 12/12 perf report: Add report.group config option
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
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
--- tools/perf/builtin-report.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
tools/perf/builtin-report.c +13 -0
@@ -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,
@@ -674,6 +685,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)
Signature · 1 line
1.7.9.2