Support Intel uncore event lists v4
This adds uncore support on top of the recently merged JSON event list infrastructure for core events. Uncore is everything outside the core, including memory controllers, PCI, interconnect etc.
Uncore is more complicated to handle than core events because it uses many duplicated PMUs, which leads to long event lists and verbose duplicated outputs.
In fact previously it was nearly unusable for many cases without special tools to generate event list and aggregate data (such as
https://github.com/andikleen/pmu-tools/tree/master/ucevent)
With this patchkit we add:
- Basic support for uncore events in JSON events
- Support aliases that get duplicated over many PMUs transparently
- Support summing up duplicated PMUs per socket
- Support extending the perf stat builtin metrics with simple expressions specified in the event list.
So far mainly servers are supported. Also this is not using full event lists (which are full of very obscure events) but only for a smaller subset of curated useful and understandable metrics.
The actual event lists are not posted, but available atgit://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc perf/intel-uncore-json-files-3
The code is available heregit://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc perf/builtin-json-22
v1: Initial post
v2: Address review feedback. See changelog in commits.
v3: Repost. Rebase to latest tree.
v4: Rebase. Change DividedBy to generic simple expression parser. Fix refactoring problem that broke git bisect.
-Andi
PATCH 1/11 perf, tools: Factor out scale conversion code
From: Andi Kleen <[email protected]>
Move the scale factor parsing code to an own function to reuse it in an upcoming patch.
v2: Return error in case strdup returns NULL.
squash! perf, tools: Factor out scale conversion code
--- tools/perf/util/pmu.c | 64 ++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 29 deletions(-)
tools/perf/util/pmu.c +35 -29
@@ -94,32 +94,10 @@ static int pmu_format(const char *name, struct list_head *format)return 0 ; } -static int perf_pmu__parse_scale (struct perf_pmu_alias *alias,char *dir,char *name) +static int convert_scale (const char *scale,char **end,double *sval) { -struct stat st; -ssize_t sret; -char scale[128 ]; -int fd, ret =-1 ; -char path[PATH_MAX ];char *lc; - -snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name); - - fd =open (path,O_RDONLY ); -if (fd ==-1 ) -return -1 ; - -if (fstat (fd, &st) <0 ) - goto error; - - sret =read (fd, scale,sizeof (scale)-1 ); -if (sret <0 ) - goto error; - -if (scale[sret -1 ] =='\n' ) - scale[sret -1 ] ='\0' ; -else - scale[sret] ='\0' ; +int ret =0 ;/* * save current locale
@@ -133,8 +111,8 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ lc =strdup (lc);if (!lc) { - ret = -ENOMEM ; - goto error; + ret =-1 ; + goto out; }/*
@@ -144,14 +122,42 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ setlocale (LC_NUMERIC ,"C" ); - alias->scale =strtod (scale,NULL ); + *sval =strtod (scale, end); +out:/* restore locale */ setlocale (LC_NUMERIC , lc); -free (lc); +return ret; +} + +static int perf_pmu__parse_scale (struct perf_pmu_alias *alias,char *dir,char *name) +{ +struct stat st; +ssize_t sret; +char scale[128 ]; +int fd, ret =-1 ; +char path[PATH_MAX ]; + +snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name); + + fd =open (path,O_RDONLY ); +if (fd ==-1 ) +return -1 ; + +if (fstat (fd, &st) <0 ) + goto error; + + sret =read (fd, scale,sizeof (scale)-1 ); +if (sret <0 ) + goto error; + +if (scale[sret -1 ] =='\n' ) + scale[sret -1 ] ='\0' ; +else + scale[sret] ='\0' ; - ret =0 ; + ret =convert_scale (scale,NULL , &alias->scale); error:close (fd);return ret;
Signature · 1 line
2.9.3
Re: [PATCH 01/11] perf, tools: Factor out scale conversion code
Quoted 9 lines · Andi Kleen
From: Andi Kleen <[email protected]>
Move the scale factor parsing code to an own function to reuse it in an upcoming patch.
v2: Return error in case strdup returns NULL.
Signed-off-by Andi Kleen <[email protected]>squash! perf, tools: Factor out scale conversion code
hm? ^^^
jirka
Re: [PATCH 01/11] perf, tools: Factor out scale conversion code
In reply to Andi KleenOn Tue, Jan 03, 2017 at 07:08:23AM -0800, Andi Kleen wrote:
SNIP
Quoted 11 lines
tools/perf/util/pmu.c +1
-6- goto error; - -if (scale[sret -1 ] =='\n' ) - scale[sret -1 ] ='\0' ; -else - scale[sret] ='\0' ; +int ret =0 ;/* * save current locale
tools/perf/util/pmu.c static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * · line 115
Quoted 7 lines
tools/perf/util/pmu.c +2
-2@@ -133,8 +111,8 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ lc =strdup (lc);if (!lc) { - ret = -ENOMEM ; - goto error; + ret =-1 ; + goto out;
not sure why you changed the -ENOMEM to -1 ;-) but it's ok anyway
thanks,
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 01/11] perf, tools: Factor out scale conversion code
Em Sun, Jan 08, 2017 at 07:57:53PM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Andi Kleen
SNIP
Quoted 8 lines
tools/perf/util/pmu.c +1
-6- goto error; - -if (scale[sret -1 ] =='\n' ) - scale[sret -1 ] ='\0' ; -else - scale[sret] ='\0' ; +int ret =0 ;
Quoted 12 lines
tools/perf/util/pmu.c static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * · line 115
Quoted 10 lines
tools/perf/util/pmu.c +2
-2/* * save current locale @@ -133,8 +111,8 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ lc =strdup (lc);if (!lc) { - ret = -ENOMEM ; - goto error; + ret =-1 ; + goto out;not sure why you changed the
-ENOMEMto -1 ;-) but it's ok anyway
These unrelated things are just that, noise, I'll ditch it to reduce patch size while not introducing any functional change.
Quoted 1 line
Acked-by Jiri Olsa <[email protected]>
Will keep your ack tho :-)
- Arnaldo
Quoted 2 lines
thanks,
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 01/11] perf, tools: Factor out scale conversion code
Em Thu, Jan 12, 2017 at 10:31:57AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 26 lines
Em Sun, Jan 08, 2017 at 07:57:53PM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Andi Kleen
SNIP
Quoted 8 lines
tools/perf/util/pmu.c +1
-6- goto error; - -if (scale[sret -1 ] =='\n' ) - scale[sret -1 ] ='\0' ; -else - scale[sret] ='\0' ; +int ret =0 ;Quoted 12 lines
tools/perf/util/pmu.c static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * · line 115
Quoted 10 lines
tools/perf/util/pmu.c +2
-2/* * save current locale @@ -133,8 +111,8 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ lc =strdup (lc);if (!lc) { - ret = -ENOMEM ; - goto error; + ret =-1 ; + goto out;not sure why you changed the
-ENOMEMto -1 ;-) but it's ok anyway
Quoted 2 lines
These unrelated things are just that, noise, I'll ditch it to reduce patch size while not introducing any functional change.
But then this return is not even being looked at anywhere :-\
Quoted 8 lines
Quoted 1 line
Acked-by Jiri Olsa <[email protected]>Will keep your ack tho :-)
- Arnaldo
Quoted 2 lines
thanks,
jirka
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf pmu: Factor out scale conversion code
In reply to Andi Kleenperf pmu: Factor out scale conversion code
Commit-ID: d02fc6bcd53721cf8588633409157c232f2418e0 Gitweb: http://git.kernel.org/tip/d02fc6bcd53721cf8588633409157c232f2418e0 Author: Andi Kleen <[email protected]> AuthorDate: Tue, 3 Jan 2017 07:08:23 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 16 Jan 2017 14:59:15 -0300
perf pmu: Factor out scale conversion code
Move the scale factor parsing code to an own function to reuse it in an upcoming patch.
v2: Return error in case strdup returns NULL.
--- tools/perf/util/pmu.c | 62 ++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 28 deletions(-)
tools/perf/util/pmu.c +34 -28
@@ -94,32 +94,10 @@ static int pmu_format(const char *name, struct list_head *format)return 0 ; } -static int perf_pmu__parse_scale (struct perf_pmu_alias *alias,char *dir,char *name) +static int convert_scale (const char *scale,char **end,double *sval) { -struct stat st; -ssize_t sret; -char scale[128 ]; -int fd, ret =-1 ; -char path[PATH_MAX ];char *lc; - -snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name); - - fd =open (path,O_RDONLY ); -if (fd ==-1 ) -return -1 ; - -if (fstat (fd, &st) <0 ) - goto error; - - sret =read (fd, scale,sizeof (scale)-1 ); -if (sret <0 ) - goto error; - -if (scale[sret -1 ] =='\n' ) - scale[sret -1 ] ='\0' ; -else - scale[sret] ='\0' ; +int ret =0 ;/* * save current locale
@@ -134,7 +112,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * lc =strdup (lc);if (!lc) { ret = -ENOMEM ; - goto error; + goto out; }/*
@@ -144,14 +122,42 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ setlocale (LC_NUMERIC ,"C" ); - alias->scale =strtod (scale,NULL ); + *sval =strtod (scale, end); +out:/* restore locale */ setlocale (LC_NUMERIC , lc); -free (lc); +return ret; +} + +static int perf_pmu__parse_scale (struct perf_pmu_alias *alias,char *dir,char *name) +{ +struct stat st; +ssize_t sret; +char scale[128 ]; +int fd, ret =-1 ; +char path[PATH_MAX ]; + +snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name); + + fd =open (path,O_RDONLY ); +if (fd ==-1 ) +return -1 ; + +if (fstat (fd, &st) <0 ) + goto error; + + sret =read (fd, scale,sizeof (scale)-1 ); +if (sret <0 ) + goto error; + +if (scale[sret -1 ] =='\n' ) + scale[sret -1 ] ='\0' ; +else + scale[sret] ='\0' ; - ret =0 ; + ret =convert_scale (scale,NULL , &alias->scale); error:close (fd);return ret;
PATCH 2/11 perf, tools: Parse eventcode as number in jevents
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
The next patch needs to modify event code. Previously eventcode was just passed through as a string. Now parse it as a number.
--- tools/perf/pmu-events/jevents.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
tools/perf/pmu-events/jevents.c +13 -1
@@ -135,7 +135,6 @@ static struct field {const char *field;const char *kernel; } fields[] = { - { "EventCode", "event=" }, { "UMask", "umask=" }, { "CounterMask", "cmask=" }, { "Invert", "inv=" },
@@ -164,6 +163,10 @@ static int match_field(char *map, jsmntok_t *field, int nz,for (f = fields; f->field; f++)if (json_streq (map, field, f->field) && nz) { +/* Handle all variations of 0 encounted in JSON */ +if (json_streq (map, val,"0x00" ) || +json_streq (map, val,"0x0" )) +return 1 ;cut_comma (map, &newval);addfield (map, event,"," , f->kernel, &newval);return 1 ;
@@ -343,6 +346,7 @@ int json_events(const char *fn,jsmntok_t *tokens, *tok;int i, j, len;char *map; +char buf[128 ];if (!fn)return -ENOENT ;
@@ -356,6 +360,7 @@ int json_events(const char *fn,char *event =NULL , *desc =NULL , *name =NULL ;char *long_desc =NULL ;char *extra_desc =NULL ; +unsigned long long eventcode =0 ;struct msrmap *msr =NULL ;jsmntok_t *msrval =NULL ;jsmntok_t *precise =NULL ;
@@ -376,6 +381,11 @@ int json_events(const char *fn, nz = !json_streq (map, val,"0" );if (match_field (map, field, nz, &event, val)) {/* ok */ + }else if (json_streq (map, field,"EventCode" )) { +char *code =NULL ; +addfield (map, &code,"" ,"" , val); + eventcode |=strtoul (code,NULL ,0 ); +free (code); }else if (json_streq (map, field,"EventName" )) {addfield (map, &name,"" ,"" , val); }else if (json_streq (map, field,"BriefDescription" )) {
@@ -410,6 +420,8 @@ int json_events(const char *fn,addfield (map, &extra_desc," " ,"(Precise event)" ,NULL ); } +snprintf (buf,sizeof buf,"event=%#llx" , eventcode); +addfield (map, &event,"," , buf,NULL );if (desc && extra_desc)addfield (map, &desc," " , extra_desc,NULL );if (long_desc && extra_desc)
Signature · 1 line
2.9.3
Re: [PATCH 02/11] perf, tools: Parse eventcode as number in jevents
Quoted 23 lines · Andi Kleen
From: Andi Kleen <[email protected]>
The next patch needs to modify event code. Previously eventcode was just passed through as a string. Now parse it as a number.
Signed-off-by Andi Kleen <[email protected]>--- tools/perf/pmu-events/jevents.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)tools/perf/pmu-events/jevents.c +0
-1@@ -135,7 +135,6 @@ static struct field {const char *field;const char *kernel; } fields[] = { - { "EventCode", "event=" }, { "UMask", "umask=" }, { "CounterMask", "cmask=" }, { "Invert", "inv=" },
tools/perf/pmu-events/jevents.c static int match_field(char *map, jsmntok_t *field, int nz, · line 169
Quoted 7 lines
tools/perf/pmu-events/jevents.c +4
-0@@ -164,6 +163,10 @@ static int match_field(char *map, jsmntok_t *field, int nz,for (f = fields; f->field; f++)if (json_streq (map, field, f->field) && nz) { +/* Handle all variations of 0 encounted in JSON */ +if (json_streq (map, val,"0x00" ) || +json_streq (map, val,"0x0" )) +return 1 ;
how is this related to the patch? also shouldn't it return 0 ?
jirka
Re: [PATCH 02/11] perf, tools: Parse eventcode as number in jevents
Quoted 8 lines
tools/perf/pmu-events/jevents.c static int match_field(char *map, jsmntok_t *field, int nz, · line 169
Quoted 6 lines
tools/perf/pmu-events/jevents.c +4
-0for (f = fields; f->field; f++)if (json_streq (map, field, f->field) && nz) { +/* Handle all variations of 0 encounted in JSON */ +if (json_streq (map, val,"0x00" ) || +json_streq (map, val,"0x0" )) +return 1 ;how is this related to the patch? also shouldn't it return 0 ?
I removed it now. It avoids some extra umask=0x0 entries, but these don't hurt.
-Andi
Re: [PATCH 02/11] perf, tools: Parse eventcode as number in jevents
Quoted 11 lines · Andi Kleen
Quoted 8 lines
tools/perf/pmu-events/jevents.c static int match_field(char *map, jsmntok_t *field, int nz, · line 169
Quoted 6 lines
tools/perf/pmu-events/jevents.c +4
-0for (f = fields; f->field; f++)if (json_streq (map, field, f->field) && nz) { +/* Handle all variations of 0 encounted in JSON */ +if (json_streq (map, val,"0x00" ) || +json_streq (map, val,"0x0" )) +return 1 ;how is this related to the patch? also shouldn't it return 0 ?
I removed it now. It avoids some extra umask=0x0 entries, but these don't hurt.
ack on the version in the branch, but you haven't posted that one
jirka
PATCH 3/11 perf, tools: Add support for parsing uncore json files
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Handle the Unit field, which is needed to find the right PMU for an event. We call it "pmu" and convert it to the perf pmu name with an uncore prefix.
Handle the ExtSel field, which just extends the event mask with an additional bit.
Handle the Filter field which adds parameters to the main event to configure filtering.
Handle the Unit field which declares the unit the values should be scaled too (similar to what the kernel exports)
Set up the perpkg field for uncore events so that perf knows they are per package (similar to what the kernel exports)
Then output the fields into the pmu-events data structures which are compiled into perf.
Filter out zero fields, except for the event itself.
v2: Fix compilation. Add uncore_ prefix at pre-processing time. Move eventcode change to separate patch.
--- tools/perf/pmu-events/jevents.c | 74 +++++++++++++++++++++++++++++++++++--- tools/perf/pmu-events/jevents.h | 4 ++- tools/perf/pmu-events/pmu-events.h | 3 ++ tools/perf/util/pmu.c | 27 +++++++++----- 4 files changed, 95 insertions(+), 13 deletions(-)
tools/perf/pmu-events/jevents.c +70 -4
@@ -192,6 +192,27 @@ static struct msrmap *lookup_msr(char *map, jsmntok_t *val)return NULL ; } +static struct map { +const char *json; +const char *perf; +} unit_to_pmu[] = { + {"CBO" ,"uncore_cbox" }, + {"QPI LL" ,"uncore_qpi" }, + {"SBO" ,"uncore_sbox" }, + {} +}; + +static const char *field_to_perf (struct map *table,char *map,jsmntok_t *val) +{ +int i; + +for (i =0 ; table[i].json; i++) { +if (json_streq (map, val, table[i].json)) +return table[i].perf; + } +return NULL ; +} +#define EXPECT (e, t, m) do { if (!(e)) { \ jsmntok_t *loc = (t); \ if (!(t)->start && (t) > tokens) \
@@ -273,7 +294,8 @@ static void print_events_table_prefix(FILE *fp, const char *tblname) }static int print_events_table_entry (void *data,char *name,char *event, -char *desc,char *long_desc) +char *desc,char *long_desc, +char *pmu,char *unit,char *perpkg) {struct perf_entry_data *pd = data;FILE *outfp = pd->outfp;
@@ -291,7 +313,12 @@ static int print_events_table_entry(void *data, char *name, char *event,fprintf (outfp,"\t.topic = \"%s\",\n" , topic);if (long_desc && long_desc[0 ])fprintf (outfp,"\t.long_desc = \"%s\",\n" , long_desc); - +if (pmu) +fprintf (outfp,"\t.pmu = \"%s\",\n" , pmu); +if (unit) +fprintf (outfp,"\t.unit = \"%s\",\n" , unit); +if (perpkg) +fprintf (outfp,"\t.perpkg = \"%s\",\n" , perpkg);fprintf (outfp,"},\n" );return 0 ;
@@ -338,7 +365,8 @@ static char *real_event(const char *name, char *event)/* Call func with each event in the json file */ int json_events (const char *fn,int (*func)(void *data,char *name,char *event,char *desc, -char *long_desc), +char *long_desc, +char *pmu,char *unit,char *perpkg),void *data) {int err = -EIO ;
@@ -360,6 +388,10 @@ int json_events(const char *fn,char *event =NULL , *desc =NULL , *name =NULL ;char *long_desc =NULL ;char *extra_desc =NULL ; +char *pmu =NULL ; +char *filter =NULL ; +char *perpkg =NULL ; +char *unit =NULL ;unsigned long long eventcode =0 ;struct msrmap *msr =NULL ;jsmntok_t *msrval =NULL ;
@@ -386,6 +418,11 @@ int json_events(const char *fn,addfield (map, &code,"" ,"" , val); eventcode |=strtoul (code,NULL ,0 );free (code); + }else if (json_streq (map, field,"ExtSel" )) { +char *code =NULL ; +addfield (map, &code,"" ,"" , val); + eventcode |=strtoul (code,NULL ,0 ) <<21 ; +free (code); }else if (json_streq (map, field,"EventName" )) {addfield (map, &name,"" ,"" , val); }else if (json_streq (map, field,"BriefDescription" )) {
@@ -409,6 +446,28 @@ int json_events(const char *fn,addfield (map, &extra_desc,". " ," Supports address when precise" ,NULL ); + }else if (json_streq (map, field,"Unit" )) { +const char *ppmu; +char *s; + + ppmu =field_to_perf (unit_to_pmu, map, val); +if (ppmu) { + pmu =strdup (ppmu); + }else { +if (!pmu) + pmu =strdup ("uncore_" ); +addfield (map, &pmu,"" ,"" , val); +for (s = pmu; *s; s++) + *s =tolower (*s); + } +addfield (map, &desc,". " ,"Unit: " ,NULL ); +addfield (map, &desc,"" , pmu,NULL ); + }else if (json_streq (map, field,"Filter" )) { +addfield (map, &filter,"" ,"" , val); + }else if (json_streq (map, field,"ScaleUnit" )) { +addfield (map, &unit,"" ,"" , val); + }else if (json_streq (map, field,"PerPkg" )) { +addfield (map, &perpkg,"" ,"" , val); }/* ignore unknown fields */ }
@@ -426,16 +485,23 @@ int json_events(const char *fn,addfield (map, &desc," " , extra_desc,NULL );if (long_desc && extra_desc)addfield (map, &long_desc," " , extra_desc,NULL ); +if (filter) +addfield (map, &event,"," , filter,NULL );if (msr !=NULL )addfield (map, &event,"," , msr->pname, msrval);fixname (name); - err =func (data, name,real_event (name, event), desc, long_desc); + err =func (data, name,real_event (name, event), desc, long_desc, + pmu, unit, perpkg);free (event);free (desc);free (name);free (long_desc);free (extra_desc); +free (pmu); +free (filter); +free (perpkg); +free (unit);if (err)break ; tok += j;
tools/perf/pmu-events/jevents.h +3 -1
@@ -3,7 +3,9 @@int json_events (const char *fn,int (*func)(void *data,char *name,char *event,char *desc, -char *long_desc), +char *long_desc, +char *pmu, +char *unit,char *perpkg),void *data);char *get_cpu_str (void );
tools/perf/pmu-events/pmu-events.h +3 -0
@@ -10,6 +10,9 @@ struct pmu_event {const char *desc;const char *topic;const char *long_desc; +const char *pmu; +const char *unit; +const char *perpkg; };/*
tools/perf/util/pmu.c +19 -8
@@ -229,11 +229,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, }static int __perf_pmu__new_alias (struct list_head *list,char *dir,char *name, -char *desc,char *val,char *long_desc, -char *topic) +char *desc__maybe_unused ,char *val, +char *long_desc,char *topic, +char *unit,char *perpkg) {struct perf_pmu_alias *alias;int ret; +int num; alias =malloc (sizeof (*alias));if (!alias)
@@ -267,7 +269,12 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, alias->long_desc = long_desc ?strdup (long_desc) : desc ?strdup (desc) :NULL ; alias->topic = topic ?strdup (topic) :NULL ; - +if (unit) { +if (convert_scale (unit, &unit, &alias->scale) <0 ) +return -1 ; +snprintf (alias->unit,sizeof (alias->unit),"%s" , unit); + } + alias->per_pkg = perpkg &&sscanf (perpkg,"%d" , &num) ==1 && num ==1 ;list_add_tail (&alias->list, list);return 0 ;
@@ -284,7 +291,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI buf[ret] =0 ; -return __perf_pmu__new_alias (list, dir, name,NULL , buf,NULL ,NULL ); +return __perf_pmu__new_alias (list, dir, name,NULL , buf,NULL ,NULL ,NULL , +NULL ); }static inline bool pmu_alias_info_file (char *name)
@@ -504,7 +512,7 @@ char * __weak get_cpuid_str(void)* to the current running CPU. Then, add all PMU events from that table * as aliases. */ -static void pmu_add_cpu_aliases (struct list_head *head) +static void pmu_add_cpu_aliases (struct list_head *head,const char *name) {int i;struct pmu_events_map *map;
@@ -544,10 +552,14 @@ static void pmu_add_cpu_aliases(struct list_head *head)if (!pe->name)break ; +if (pe->pmu &&strncmp (pe->pmu, name,strlen (pe->pmu))) +continue ; +/* need type casts to override 'const' */ __perf_pmu__new_alias (head,NULL , (char *)pe->name, (char *)pe->desc, (char *)pe->event, - (char *)pe->long_desc, (char *)pe->topic); + (char *)pe->long_desc, (char *)pe->topic, + (char *)pe->unit, (char *)pe->perpkg); } out:
@@ -578,8 +590,7 @@ static struct perf_pmu *pmu_lookup(const char *name)if (pmu_aliases (name, &aliases))return NULL ; -if (!strcmp (name,"cpu" )) -pmu_add_cpu_aliases (&aliases); +pmu_add_cpu_aliases (&aliases, name);if (pmu_type (name, &type))return NULL ;
Signature · 1 line
2.9.3
Re: [PATCH 03/11] perf, tools: Add support for parsing uncore json files
On Tue, Jan 03, 2017 at 07:08:25AM -0800, Andi Kleen wrote:
SNIP
tools/perf/util/pmu.c static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, · line 232
Quoted 12 lines
/*
tools/perf/util/pmu.c +1
-2@@ -229,11 +229,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, } static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, -char *desc,char *val,char *long_desc, -char *topic) + char *desc __maybe_unused, char *val,
no need for 'desc' to be __maybe_unused
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 03/11] perf, tools: Add support for parsing uncore json files
Em Sun, Jan 08, 2017 at 07:58:00PM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Andi Kleen
SNIP
Quoted 8 lines
/*
tools/perf/util/pmu.c +0
-0@@ -229,11 +229,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, }
Quoted 6 lines
tools/perf/util/pmu.c static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, · line 232
Quoted 4 lines
tools/perf/util/pmu.c +1
-2static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, -char *desc,char *val,char *long_desc, -char *topic) + char *desc __maybe_unused, char *val,no need for 'desc' to be
__maybe_unused
I'll check and remove it...
- Arnaldo
Re: [PATCH 03/11] perf, tools: Add support for parsing uncore json files
In reply to Andi KleenQuoted 18 lines · Andi Kleen
From: Andi Kleen <[email protected]>
Handle the Unit field, which is needed to find the right PMU for an event. We call it "pmu" and convert it to the perf pmu name with an uncore prefix.
Handle the ExtSel field, which just extends the event mask with an additional bit.
Handle the Filter field which adds parameters to the main event to configure filtering.
Handle the Unit field which declares the unit the values should be scaled too (similar to what the kernel exports)
Set up the perpkg field for uncore events so that perf knows they are per package (similar to what the kernel exports)
Quoted 8 lines
Then output the fields into the pmu-events data structures which are compiled into perf.
Filter out zero fields, except for the event itself.
v2: Fix compilation. Add
uncore_prefix at pre-processing time. Move eventcode change to separate patch.Signed-off-by Andi Kleen <[email protected]>
thanks,
jirka
PATCH 4/11 perf, tools: Support per pmu json aliases
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add support for registering json aliases per PMU. Any alias with an unit matching the prefix is registered to the PMU. Uncore has multiple instances of most units, so all these aliases get registered for each individual PMU (this is important later to run the event on every instance of the PMU).
To avoid printing the events multiple times in perf list filter out duplicated events during printing.
v2: Rely on uncore_ prefix already in unit
--- tools/perf/util/pmu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
tools/perf/util/pmu.c +6 -4
@@ -587,14 +587,13 @@ static struct perf_pmu *pmu_lookup(const char *name)if (pmu_format (name, &format))return NULL ; -if (pmu_aliases (name, &aliases)) +if (pmu_type (name, &type))return NULL ; -pmu_add_cpu_aliases (&aliases, name); - -if (pmu_type (name, &type)) +if (pmu_aliases (name, &aliases))return NULL ; +pmu_add_cpu_aliases (&aliases, name); pmu =zalloc (sizeof (*pmu));if (!pmu)return NULL ;
@@ -1192,6 +1191,9 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, len = j;qsort (aliases, len,sizeof (struct sevent ), cmp_sevent);for (j =0 ; j < len; j++) { +/* Skip duplicates */ +if (j >0 && !strcmp (aliases[j].name, aliases[j -1 ].name)) +continue ;if (name_only) {printf ("%s " , aliases[j].name);continue ;
Signature · 1 line
2.9.3
Re: [PATCH 04/11] perf, tools: Support per pmu json aliases
Quoted 27 lines · Andi Kleen
From: Andi Kleen <[email protected]>
Add support for registering json aliases per PMU. Any alias with an unit matching the prefix is registered to the PMU. Uncore has multiple instances of most units, so all these aliases get registered for each individual PMU (this is important later to run the event on every instance of the PMU).
To avoid printing the events multiple times in perf list filter out duplicated events during printing.
v2: Rely on
uncore_prefix already in unitSigned-off-by Andi Kleen <[email protected]>--- tools/perf/util/pmu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)tools/perf/util/pmu.c +0
-1@@ -587,14 +587,13 @@ static struct perf_pmu *pmu_lookup(const char *name)if (pmu_format (name, &format))return NULL ; -if (pmu_aliases (name, &aliases))
tools/perf/util/pmu.c static struct perf_pmu *pmu_lookup(const char *name) · line 596
Quoted 10 lines
tools/perf/util/pmu.c +3
-3+if (pmu_type (name, &type))return NULL ; -pmu_add_cpu_aliases (&aliases, name); - -if (pmu_type (name, &type)) +if (pmu_aliases (name, &aliases))return NULL ; +pmu_add_cpu_aliases (&aliases, name);
AFAICS you switched the calls.. how does it matter?
jirka
Quoted 16 lines
tools/perf/util/pmu.c +3
-0pmu =zalloc (sizeof (*pmu));if (!pmu)return NULL ;@@ -1192,6 +1191,9 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, len = j;qsort (aliases, len,sizeof (struct sevent ), cmp_sevent);for (j =0 ; j < len; j++) { +/* Skip duplicates */ +if (j >0 && !strcmp (aliases[j].name, aliases[j -1 ].name)) +continue ;if (name_only) {printf ("%s " , aliases[j].name);continue ;Signature · 1 line
2.9.3
Re: [PATCH 04/11] perf, tools: Support per pmu json aliases
Quoted 17 lines
Quoted 17 lines
index
8bffe99d8e3f..4bfc98953aba100644tools/perf/util/pmu.c +2
-4@@ -587,14 +587,13 @@ static struct perf_pmu *pmu_lookup(const char *name)if (pmu_format (name, &format))return NULL ; -if (pmu_aliases (name, &aliases)) +if (pmu_type (name, &type))return NULL ; -pmu_add_cpu_aliases (&aliases, name); - -if (pmu_type (name, &type)) +if (pmu_aliases (name, &aliases))return NULL ;
Quoted 3 lines
tools/perf/util/pmu.c static struct perf_pmu *pmu_lookup(const char *name) · line 596
Quoted 1 line
tools/perf/util/pmu.c +1
-0+pmu_add_cpu_aliases (&aliases, name);AFAICS you switched the calls.. how does it matter?
It avoids lots of duplicate messages with -v (and also is more efficient)
-Andi
Re: [PATCH 04/11] perf, tools: Support per pmu json aliases
Quoted 17 lines · Andi Kleen
Quoted 17 lines
Quoted 17 lines
index
8bffe99d8e3f..4bfc98953aba100644tools/perf/util/pmu.c +2
-4@@ -587,14 +587,13 @@ static struct perf_pmu *pmu_lookup(const char *name)if (pmu_format (name, &format))return NULL ; -if (pmu_aliases (name, &aliases)) +if (pmu_type (name, &type))return NULL ; -pmu_add_cpu_aliases (&aliases, name); - -if (pmu_type (name, &type)) +if (pmu_aliases (name, &aliases))return NULL ;
Quoted 5 lines
Quoted 3 lines
tools/perf/util/pmu.c static struct perf_pmu *pmu_lookup(const char *name) · line 596
Quoted 1 line
tools/perf/util/pmu.c +1
-0+pmu_add_cpu_aliases (&aliases, name);AFAICS you switched the calls.. how does it matter?
It avoids lots of duplicate messages with -v (and also is more efficient)
cool, please state that in chagelog.. before/after
thanks,
jirka
PATCH 5/11 perf, tools: Support event aliases for non cpu// pmus
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
The code for handling pmu aliases without specifying the PMU hardcoded only supported the cpu PMU.
This patch extends it to work for all PMUs. We always duplicate the event for all PMUs that have an matching alias. This allows to automatically expand an alias for all instances of a PMU (so for example you can monitor all cache boxes with a single event)
--- tools/perf/util/parse-events.c | 46 ++++++++++++++++++++++++------------------ tools/perf/util/parse-events.y | 32 ++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 27 deletions(-)
tools/perf/util/parse-events.c +26 -20
@@ -1504,35 +1504,41 @@ static void perf_pmu__parse_init(void)struct perf_pmu_alias *alias;int len =0 ; - pmu =perf_pmu__find ("cpu" ); -if ((pmu ==NULL ) ||list_empty (&pmu->aliases)) { + pmu =NULL ; +while ((pmu =perf_pmu__scan (pmu)) !=NULL ) { +list_for_each_entry (alias, &pmu->aliases, list) { +if (strchr (alias->name,'-' )) + len++; + len++; + } + } + +if (len ==0 ) { perf_pmu_events_list_num =-1 ;return ; } -list_for_each_entry (alias, &pmu->aliases, list) { -if (strchr (alias->name,'-' )) - len++; - len++; - } perf_pmu_events_list =malloc (sizeof (struct perf_pmu_event_symbol ) * len);if (!perf_pmu_events_list)return ; perf_pmu_events_list_num = len; len =0 ; -list_for_each_entry (alias, &pmu->aliases, list) { -struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; -char *tmp =strchr (alias->name,'-' ); - -if (tmp !=NULL ) { -SET_SYMBOL (strndup (alias->name, tmp - alias->name), -PMU_EVENT_SYMBOL_PREFIX ); - p++; -SET_SYMBOL (strdup (++tmp),PMU_EVENT_SYMBOL_SUFFIX ); - len +=2 ; - }else { -SET_SYMBOL (strdup (alias->name),PMU_EVENT_SYMBOL ); - len++; + pmu =NULL ; +while ((pmu =perf_pmu__scan (pmu)) !=NULL ) { +list_for_each_entry (alias, &pmu->aliases, list) { +struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; +char *tmp =strchr (alias->name,'-' ); + +if (tmp !=NULL ) { +SET_SYMBOL (strndup (alias->name, tmp - alias->name), +PMU_EVENT_SYMBOL_PREFIX ); + p++; +SET_SYMBOL (strdup (++tmp),PMU_EVENT_SYMBOL_SUFFIX ); + len +=2 ; + }else { +SET_SYMBOL (strdup (alias->name),PMU_EVENT_SYMBOL ); + len++; + } } } qsort(perf_pmu_events_list, len,
tools/perf/util/parse-events.y +25 -7
@@ -12,6 +12,7 @@ #include <linux/list.h> #include <linux/types.h> #include "util.h" +#include "pmu.h" #include "parse-events.h" #include "parse-events-bison.h"
@@ -236,15 +237,32 @@ PE_KERNEL_PMU_EVENT sep_dc struct list_head *head; struct parse_events_term *term; struct list_head *list; + struct perf_pmu *pmu = NULL; + int ok = 0; - ALLOC_LIST(head); - ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, - $1, 1, &@1, NULL)); - list_add_tail(&term->list, head); - + /* Add it for all PMUs that support the alias */ ALLOC_LIST(list); - ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); - parse_events_terms__delete(head); + while ((pmu = perf_pmu__scan(pmu)) != NULL) { + struct perf_pmu_alias *alias; + + list_for_each_entry(alias, &pmu->aliases, list) { + if (!strcasecmp(alias->name, $1)) { + ALLOC_LIST(head); + ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, + $1, 1, &@1, NULL)); + list_add_tail(&term->list, head); + + if (!parse_events_add_pmu(data, list, + pmu->name, head)) { + ok++; + } + + parse_events_terms__delete(head); + } + } + } + if (!ok) + YYABORT; $$ = list; } |
Signature · 1 line
2.9.3
Re: [PATCH 05/11] perf, tools: Support event aliases for non cpu// pmus
Quoted 5 lines · Andi Kleen
From: Andi Kleen <[email protected]>
The code for handling pmu aliases without specifying the PMU hardcoded only supported the cpu PMU.
Quoted 7 lines
This patch extends it to work for all PMUs. We always duplicate the event for all PMUs that have an matching alias. This allows to automatically expand an alias for all instances of a PMU (so for example you can monitor all cache boxes with a single event)
Signed-off-by Andi Kleen <[email protected]>
thanks,
jirka
Quoted 126 lines
--- tools/perf/util/parse-events.c | 46 ++++++++++++++++++++++++------------------ tools/perf/util/parse-events.y | 32 ++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 27 deletions(-)tools/perf/util/parse-events.c +26
-20@@ -1504,35 +1504,41 @@ static void perf_pmu__parse_init(void)struct perf_pmu_alias *alias;int len =0 ; - pmu =perf_pmu__find ("cpu" ); -if ((pmu ==NULL ) ||list_empty (&pmu->aliases)) { + pmu =NULL ; +while ((pmu =perf_pmu__scan (pmu)) !=NULL ) { +list_for_each_entry (alias, &pmu->aliases, list) { +if (strchr (alias->name,'-' )) + len++; + len++; + } + } + +if (len ==0 ) { perf_pmu_events_list_num =-1 ;return ; } -list_for_each_entry (alias, &pmu->aliases, list) { -if (strchr (alias->name,'-' )) - len++; - len++; - } perf_pmu_events_list =malloc (sizeof (struct perf_pmu_event_symbol ) * len);if (!perf_pmu_events_list)return ; perf_pmu_events_list_num = len; len =0 ; -list_for_each_entry (alias, &pmu->aliases, list) { -struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; -char *tmp =strchr (alias->name,'-' ); - -if (tmp !=NULL ) { -SET_SYMBOL (strndup (alias->name, tmp - alias->name), -PMU_EVENT_SYMBOL_PREFIX ); - p++; -SET_SYMBOL (strdup (++tmp),PMU_EVENT_SYMBOL_SUFFIX ); - len +=2 ; - }else { -SET_SYMBOL (strdup (alias->name),PMU_EVENT_SYMBOL ); - len++; + pmu =NULL ; +while ((pmu =perf_pmu__scan (pmu)) !=NULL ) { +list_for_each_entry (alias, &pmu->aliases, list) { +struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; +char *tmp =strchr (alias->name,'-' ); + +if (tmp !=NULL ) { +SET_SYMBOL (strndup (alias->name, tmp - alias->name), +PMU_EVENT_SYMBOL_PREFIX ); + p++; +SET_SYMBOL (strdup (++tmp),PMU_EVENT_SYMBOL_SUFFIX ); + len +=2 ; + }else { +SET_SYMBOL (strdup (alias->name),PMU_EVENT_SYMBOL ); + len++; + } } } qsort(perf_pmu_events_list, len,tools/perf/util/parse-events.y +25
-7@@ -12,6 +12,7 @@ #include <linux/list.h> #include <linux/types.h> #include "util.h" +#include "pmu.h" #include "parse-events.h" #include "parse-events-bison.h"@@ -236,15 +237,32 @@ PE_KERNEL_PMU_EVENT sep_dc struct list_head *head; struct parse_events_term *term; struct list_head *list; + struct perf_pmu *pmu = NULL; + int ok = 0; - ALLOC_LIST(head); - ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, - $1, 1, &@1, NULL)); - list_add_tail(&term->list, head); - + /* Add it for all PMUs that support the alias */ ALLOC_LIST(list); - ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); - parse_events_terms__delete(head); + while ((pmu = perf_pmu__scan(pmu)) != NULL) { + struct perf_pmu_alias *alias; + + list_for_each_entry(alias, &pmu->aliases, list) { + if (!strcasecmp(alias->name, $1)) { + ALLOC_LIST(head); + ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, + $1, 1, &@1, NULL)); + list_add_tail(&term->list, head); + + if (!parse_events_add_pmu(data, list, + pmu->name, head)) { + ok++; + } + + parse_events_terms__delete(head); + } + } + } + if (!ok) + YYABORT; $$ = list; } |Signature · 1 line
2.9.3
PATCH 6/11 perf, tools: Add debug support for outputing alias string
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
For debugging and testing it is useful to see the converted alias string. Add support to perf stat/record and perf list to print the alias conversion. The text string is saved in the alias structure. For perf stat/record it is folded into the normal -v. For perf list -v was taken, so we use --debug.
--- tools/perf/builtin-list.c | 3 +++ tools/perf/util/parse-events.y | 3 +++ tools/perf/util/pmu.c | 8 ++++++++ tools/perf/util/pmu.h | 1 + 4 files changed, 15 insertions(+)
tools/perf/builtin-list.c +3 -0
@@ -14,6 +14,7 @@#include "util/parse-events.h" #include "util/cache.h" #include "util/pmu.h" +#include "util/debug.h" #include <subcmd/parse-options.h> static bool desc_flag = true;
@@ -29,6 +30,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) "Print extra event descriptions. --no-desc to not print."),OPT_BOOLEAN ('v' ,"long-desc" , &long_desc_flag,"Print longer event descriptions." ), +OPT_INCR (0 ,"debug" , &verbose, +"Enable debugging output" ),OPT_END () }; const char * const list_usage[] = {
tools/perf/util/parse-events.y +3 -0
@@ -13,6 +13,7 @@ #include <linux/types.h> #include "util.h" #include "pmu.h" +#include "debug.h" #include "parse-events.h" #include "parse-events-bison.h"
@@ -254,6 +255,8 @@ PE_KERNEL_PMU_EVENT sep_dc if (!parse_events_add_pmu(data, list, pmu->name, head)) { + pr_debug("%s -> %s/%s/\n", $1, + pmu->name, alias->str); ok++; }
tools/perf/util/pmu.c +8 -0
@@ -275,6 +275,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,snprintf (alias->unit,sizeof (alias->unit),"%s" , unit); } alias->per_pkg = perpkg &&sscanf (perpkg,"%d" , &num) ==1 && num ==1 ; + alias->str =strdup (val); +list_add_tail (&alias->list, list);return 0 ;
@@ -1081,6 +1083,8 @@ struct sevent {char *name;char *desc;char *topic; +char *str; +char *pmu; };static int cmp_sevent (const void *a,const void *b)
@@ -1177,6 +1181,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, aliases[j].desc = long_desc ? alias->long_desc : alias->desc; aliases[j].topic = alias->topic; + aliases[j].str = alias->str; + aliases[j].pmu = pmu->name; j++; } if (pmu->selectable &&
@@ -1211,6 +1217,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,printf ("%*s" ,8 ,"[" );wordwrap (aliases[j].desc,8 , columns,0 );printf ("]\n" ); +if (verbose) +printf ("%*s%s/%s/\n" ,8 ,"" , aliases[j].pmu, aliases[j].str); }else printf (" %-50s [Kernel PMU event]\n" , aliases[j].name); printed++;
tools/perf/util/pmu.h +1 -0
@@ -43,6 +43,7 @@ struct perf_pmu_alias {char *desc;char *long_desc;char *topic; +char *str;struct list_head terms;/* HEAD struct parse_events_term -> list */ struct list_head list;/* ELEM */ char unit[UNIT_MAX_LEN +1 ];
Signature · 1 line
2.9.3
Re: [PATCH 06/11] perf, tools: Add debug support for outputing alias string
Quoted 7 lines · Andi Kleen
From: Andi Kleen <[email protected]>
For debugging and testing it is useful to see the converted alias string. Add support to perf stat/record and perf list to print the alias conversion. The text string is saved in the alias structure. For perf stat/record it is folded into the normal -v. For perf list -v was taken, so we use --debug.
could you please show example output in here
thanks,
jirka
Re: [PATCH 06/11] perf, tools: Add debug support for outputing alias string
In reply to Andi KleenOn Tue, Jan 03, 2017 at 07:08:28AM -0800, Andi Kleen wrote:
SNIP
tools/perf/util/pmu.c static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, · line 278
Quoted 9 lines
tools/perf/util/pmu.c +1
-0@@ -275,6 +275,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,snprintf (alias->unit,sizeof (alias->unit),"%s" , unit); } alias->per_pkg = perpkg &&sscanf (perpkg,"%d" , &num) ==1 && num ==1 ; + alias->str =strdup (val);
where's this one released?
jirka
Re: [PATCH 06/11] perf, tools: Add debug support for outputing alias string
Quoted 4 lines · Jiri Olsa
On Tue, Jan 03, 2017 at 07:08:28AM -0800, Andi Kleen wrote:
SNIP
Quoted 11 lines
tools/perf/util/pmu.c static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, · line 278
Quoted 9 lines
tools/perf/util/pmu.c +1
-0@@ -275,6 +275,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,snprintf (alias->unit,sizeof (alias->unit),"%s" , unit); } alias->per_pkg = perpkg &&sscanf (perpkg,"%d" , &num) ==1 && num ==1 ; + alias->str =strdup (val);where's this one released?
Aliases are never released AFAIK?
-Andi
Re: [PATCH 06/11] perf, tools: Add debug support for outputing alias string
Quoted 17 lines · Andi Kleen
Quoted 4 lines · Jiri Olsa
On Tue, Jan 03, 2017 at 07:08:28AM -0800, Andi Kleen wrote:
SNIP
Quoted 11 lines
tools/perf/util/pmu.c static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, · line 278
Quoted 9 lines
tools/perf/util/pmu.c +1
-0@@ -275,6 +275,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,snprintf (alias->unit,sizeof (alias->unit),"%s" , unit); } alias->per_pkg = perpkg &&sscanf (perpkg,"%d" , &num) ==1 && num ==1 ; + alias->str =strdup (val);where's this one released?
Quoted 1 line
Aliases are never released AFAIK?
ok, I misplaced that one with the one from sevent struct.. sry
jirka
PATCH 7/11 perf, tools: Collapse identically named events in perf stat
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
The uncore PMU has a lot of duplicated PMUs for different subsystems. When expanding an uncore alias we usually end up with a large number of identically named aliases, which makes perf stat output difficult to read.
Automatically sum them up in perf stat, unless --no-merge is specified.
This can be default because only the uncores generally have duplicated aliases. Other PMUs have unique names.
Before:
% perf stat --no-merge -a -e unc_c_llc_lookup.any sleep 1
Performance counter stats for 'system wide':
694,976 Bytes unc_c_llc_lookup.any
706,304 Bytes unc_c_llc_lookup.any
956,608 Bytes unc_c_llc_lookup.any
782,720 Bytes unc_c_llc_lookup.any
605,696 Bytes unc_c_llc_lookup.any
442,816 Bytes unc_c_llc_lookup.any
659,328 Bytes unc_c_llc_lookup.any
509,312 Bytes unc_c_llc_lookup.any
263,936 Bytes unc_c_llc_lookup.any
592,448 Bytes unc_c_llc_lookup.any
672,448 Bytes unc_c_llc_lookup.any
608,640 Bytes unc_c_llc_lookup.any
641,024 Bytes unc_c_llc_lookup.any
856,896 Bytes unc_c_llc_lookup.any
808,832 Bytes unc_c_llc_lookup.any
684,864 Bytes unc_c_llc_lookup.any
710,464 Bytes unc_c_llc_lookup.any
538,304 Bytes unc_c_llc_lookup.any
1.002577660 seconds time elapsedAfter:
% perf stat -a -e unc_c_llc_lookup.any sleep 1
Performance counter stats for 'system wide':
2,685,120 Bytes unc_c_llc_lookup.any
1.002648032 seconds time elapsedv2: Split collect_aliases. Rename alias flag.
--- tools/perf/Documentation/perf-stat.txt | 3 + tools/perf/builtin-stat.c | 132 +++++++++++++++++++++++++++------ tools/perf/util/evsel.h | 1 + 3 files changed, 113 insertions(+), 23 deletions(-)
tools/perf/Documentation/perf-stat.txt +3 -0
@@ -237,6 +237,9 @@ To interpret the results it is usually needed to know on which CPUs the workload runs on. If needed the CPUs can be forced using taskset. +--no-merge:: +Do not merge results from same PMUs. + EXAMPLES --------
tools/perf/builtin-stat.c +109 -23
194 lines not on this page · raw message
tools/perf/util/evsel.h +1 -0
@@ -130,6 +130,7 @@ struct perf_evsel {bool cmdline_group_boundary;struct list_head config_terms;int bpf_fd; +bool merged_stat; };union u64_swap {
Signature · 1 line
2.9.3
Re: [PATCH 07/11] perf, tools: Collapse identically named events in perf stat
Quoted 41 lines · Andi Kleen
From: Andi Kleen <[email protected]>
The uncore PMU has a lot of duplicated PMUs for different subsystems. When expanding an uncore alias we usually end up with a large number of identically named aliases, which makes perf stat output difficult to read.
Automatically sum them up in perf stat, unless --no-merge is specified.
This can be default because only the uncores generally have duplicated aliases. Other PMUs have unique names.
Before:
% perf stat --no-merge -a -e unc_c_llc_lookup.any sleep 1
Performance counter stats for 'system wide':
694,976 Bytes unc_c_llc_lookup.any 706,304 Bytes unc_c_llc_lookup.any 956,608 Bytes unc_c_llc_lookup.any 782,720 Bytes unc_c_llc_lookup.any 605,696 Bytes unc_c_llc_lookup.any 442,816 Bytes unc_c_llc_lookup.any 659,328 Bytes unc_c_llc_lookup.any 509,312 Bytes unc_c_llc_lookup.any 263,936 Bytes unc_c_llc_lookup.any 592,448 Bytes unc_c_llc_lookup.any 672,448 Bytes unc_c_llc_lookup.any 608,640 Bytes unc_c_llc_lookup.any 641,024 Bytes unc_c_llc_lookup.any 856,896 Bytes unc_c_llc_lookup.any 808,832 Bytes unc_c_llc_lookup.any 684,864 Bytes unc_c_llc_lookup.any 710,464 Bytes unc_c_llc_lookup.any 538,304 Bytes unc_c_llc_lookup.any 1.002577660 seconds time elapsedAfter:
Quoted 7 lines
% perf stat -a -e unc_c_llc_lookup.any sleep 1
Performance counter stats for 'system wide':
2,685,120 Bytes unc_c_llc_lookup.any 1.002648032 seconds time elapsed
if one of them is not supported, we get wrong output:
[jolsa@krava perf]$ sudo ./perf stat --no-merge -a -e clockticks sleep 1
Performance counter stats for 'system wide':
<not supported> clockticks
4,925,158 clockticks
1.000982200 seconds time elapsed[jolsa@krava perf]$ sudo ./perf stat -a -e clockticks sleep 1
Performance counter stats for 'system wide':
<not supported> clockticks
1.000850195 seconds time elapsed
jirka
Re: [PATCH 07/11] perf, tools: Collapse identically named events in perf stat
Quoted 10 lines
Quoted 7 lines
% perf stat -a -e unc_c_llc_lookup.any sleep 1
Performance counter stats for 'system wide':
2,685,120 Bytes unc_c_llc_lookup.any 1.002648032 seconds time elapsedif one of them is not supported, we get wrong output:
I would argue the output is not incorrect, after all it is not supported if something is missing.
Imagine this is run with an interval:
If we changed the number of output lines based on some dynamic scheduling condition this could confuse post processing scripts or users. Some output records would be completely different than others. So marking everything merged <not supported> in these cases is better and more consistent.
It is also difficult to change and should be a rare condition.
-Andi
Re: [PATCH 07/11] perf, tools: Collapse identically named events in perf stat
Quoted 15 lines · Andi Kleen
Quoted 10 lines
Quoted 7 lines
% perf stat -a -e unc_c_llc_lookup.any sleep 1
Performance counter stats for 'system wide':
2,685,120 Bytes unc_c_llc_lookup.any 1.002648032 seconds time elapsedif one of them is not supported, we get wrong output:
I would argue the output is not incorrect, after all it is not supported if something is missing.
Quoted 8 lines
Imagine this is run with an interval:
If we changed the number of output lines based on some dynamic scheduling condition this could confuse post processing scripts or users. Some output records would be completely different than others. So marking everything merged <not supported> in these cases is better and more consistent.
It is also difficult to change and should be a rare condition.
will it always show 'not supported', as I haven't found this in the changelog I guess you did not know about this behaviour?
could you also please document it somewhere
jirka
Re: [PATCH 07/11] perf, tools: Collapse identically named events in perf stat
Quoted 2 lines
will it always show 'not supported', as I haven't found this in the changelog I guess you did not know about this behaviour?
Not guaranteed. Will fix that.
Quoted 2 lines
could you also please document it somewhere
Ok.
-Andi
PATCH 8/11 perf, tools: Expand PMU events by prefix match
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
When the user specifies a pmu directly, expand it automatically with a prefix match, similar as we do for the normal aliases now.
This allows to specify attributes for duplicated boxes quickly. For example uncore_cbox_{0,6}/.../ can be now specified as cbox/.../ and it gets automatically expanded.
Before
% perf stat -a -e uncore_cbox_0/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_1/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_2/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_3/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_4/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_5/event=0x35,umask=0x1,filter_opc=0x19C/ sleep 1
After
perf stat -a -e cbox/event=0x35,umask=0x1,filter_opc=0x19C/ sleep 1
v2: Handle all bison rules. Move multi add code to separate function. Handle uncore_ prefix correctly.
--- tools/perf/util/parse-events.c | 71 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.h | 8 +++++ tools/perf/util/parse-events.y | 73 +++++++++++++++++------------------------- 3 files changed, 109 insertions(+), 43 deletions(-)
tools/perf/util/parse-events.c +71 -0
@@ -1257,6 +1257,52 @@ int parse_events_add_pmu(struct parse_events_evlist *data,return evsel ?0 : -ENOMEM ; } +int parse_events_multi_pmu_add (struct parse_events_evlist *data, +char *str,struct list_head **listp) +{ +struct list_head *head; +struct parse_events_term *term; +struct list_head *list; +struct perf_pmu *pmu =NULL ; +int ok =0 ; + + *listp =NULL ; +/* Add it for all PMUs that support the alias */ + list =malloc (sizeof (struct list_head )); +if (!list) +return -1 ; +INIT_LIST_HEAD (list); +while ((pmu =perf_pmu__scan (pmu)) !=NULL ) { +struct perf_pmu_alias *alias; + +list_for_each_entry (alias, &pmu->aliases, list) { +if (!strcasecmp (alias->name, str)) { + head =malloc (sizeof (struct list_head )); +if (!head) +return -1 ; +INIT_LIST_HEAD (head); +if (parse_events_term__num (&term,PARSE_EVENTS__TERM_TYPE_USER , + str,1 , &str,NULL ) <0 ) +return -1 ; +list_add_tail (&term->list, head); + +if (!parse_events_add_pmu (data, list, + pmu->name, head)) { +pr_debug ("%s -> %s/%s/\n" , str, + pmu->name, alias->str); + ok++; + } + +parse_events_terms__delete (head); + } + } + } +if (!ok) +return -1 ; + *listp = list; +return 0 ; +} +int parse_events__modifier_group (struct list_head *list,char *event_mod) {
@@ -2406,6 +2452,31 @@ int parse_events_term__clone(struct parse_events_term **new, term->err_term, term->err_val); } +int parse_events_copy_term_list (struct list_head *old, +struct list_head **new) +{ +struct parse_events_term *term, *n; +int ret; + +if (!old) { + *new =NULL ; +return 0 ; + } + + *new =malloc (sizeof (struct list_head )); +if (!*new) +return -ENOMEM ; +INIT_LIST_HEAD (*new); + + list_for_each_entry (term, old, list) { + ret =parse_events_term__clone (&n, term); +if (ret) +return ret; +list_add_tail (&n->list, *new); + } +return 0 ; +} +void parse_events_terms__purge (struct list_head *terms) {struct parse_events_term *term, *h;
tools/perf/util/parse-events.h +8 -0
@@ -164,6 +164,14 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,int parse_events_add_pmu (struct parse_events_evlist *data,struct list_head *list,char *name,struct list_head *head_config); + +int parse_events_multi_pmu_add (struct parse_events_evlist *data, +char *str, +struct list_head **listp); + +int parse_events_copy_term_list (struct list_head *old, +struct list_head **new); +enum perf_pmu_event_symbol_type perf_pmu__parse_check (const char *name);void parse_events__set_leader (char *name,struct list_head *list);
tools/perf/util/parse-events.y +30 -43
98 lines not on this page · raw message
Signature · 1 line
2.9.3
PATCH 9/11 perf, tools: Add a simple expression parser for JSON
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add a simple expression parser good enough to parse JSON relation expressions. The parser is implemented using bison.
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++ tools/perf/tests/expr.c | 48 +++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/Build | 5 ++ tools/perf/util/expr.h | 23 ++++++ tools/perf/util/expr.y | 156 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 238 insertions(+) create mode 100644 tools/perf/tests/expr.c create mode 100644 tools/perf/util/expr.h create mode 100644 tools/perf/util/expr.y
tools/perf/tests/Build +1 -0
@@ -38,6 +38,7 @@ perf-y += cpumap.o perf-y += stat.o perf-y += event_update.o perf-y += event-times.o +perf-y += expr.o perf-y += backward-ring-buffer.o perf-y += sdt.o perf-y += is_printable_array.o
tools/perf/tests/builtin-test.c +4 -0
@@ -44,6 +44,10 @@ static struct test generic_tests[] = { .func = test__parse_events, }, { + .desc = "Simple expression parser", + .func = test__expr, + }, + { .desc = "PERF_RECORD_* events & perf_sample fields", .func = test__PERF_RECORD, },
tools/perf/tests/expr.c new file +48 -0
48 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -62,6 +62,7 @@ int test__sample_parsing(int subtest);int test__keep_tracking (int subtest);int test__parse_no_sample_id_all (int subtest);int test__dwarf_unwind (int subtest); +int test__expr (int subtest);int test__hists_filter (int subtest);int test__mmap_thread_lookup (int subtest);int test__thread_mg_share (int subtest);
tools/perf/util/Build +5 -0
@@ -88,6 +88,7 @@ libperf-y += mem-events.o libperf-y += vsprintf.o libperf-y += drv_configs.o libperf-y += time-utils.o +libperf-y += expr-bison.o libperf-$(CONFIG_LIBBPF) += bpf-loader.o libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -140,6 +141,10 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ +$(OUTPUT)util/expr-bison.c: util/expr.y + $(call rule_mkdir) + $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
tools/perf/util/expr.h new file +23 -0
@@ -0,0 +1,23 @@ +#ifndef PARSE_CTX_H +#define PARSE_CTX_H 1 + +#define MAX_PARSE_ID 2 + +struct parse_id { +const char *name; +double val; +}; + +struct parse_ctx { +int num_ids; +struct parse_id ids[MAX_PARSE_ID ]; +}; + +void expr_ctx_init (struct parse_ctx *ctx); +void expr_add_id (struct parse_ctx *ctx,const char *id,double val); +#ifndef IN_EXPR_Y +int expr_parse (double *final_val,struct parse_ctx *ctx,const char **pp); +#endif +int expr_find_other (const char *p,const char *one,const char **other); + +#endif
tools/perf/util/expr.y new file +156 -0
156 lines not on this page · raw message
Signature · 1 line
2.9.3
PATCH 10/11 perf, tools: Support MetricExpr header in JSON event list
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add support for parsing the MetricExpr header in the JSON event lists and storing them in the alias structure.
Used in the next patch.
v2: Change DividedBy to MetricExpr
--- tools/perf/pmu-events/jevents.c | 18 ++++++++++++++---- tools/perf/pmu-events/jevents.h | 2 +- tools/perf/pmu-events/pmu-events.h | 1 + tools/perf/util/pmu.c | 9 ++++++--- tools/perf/util/pmu.h | 1 + 5 files changed, 23 insertions(+), 8 deletions(-)
tools/perf/pmu-events/jevents.c +14 -4
@@ -295,7 +295,8 @@ static void print_events_table_prefix(FILE *fp, const char *tblname)static int print_events_table_entry (void *data,char *name,char *event,char *desc,char *long_desc, -char *pmu,char *unit,char *perpkg) +char *pmu,char *unit,char *perpkg, +char *metric_expr) {struct perf_entry_data *pd = data;FILE *outfp = pd->outfp;
@@ -319,6 +320,8 @@ static int print_events_table_entry(void *data, char *name, char *event,fprintf (outfp,"\t.unit = \"%s\",\n" , unit);if (perpkg)fprintf (outfp,"\t.perpkg = \"%s\",\n" , perpkg); +if (metric_expr) +fprintf (outfp,"\t.metric_expr = \"%s\",\n" , metric_expr);fprintf (outfp,"},\n" );return 0 ;
@@ -366,7 +369,8 @@ static char *real_event(const char *name, char *event)int json_events (const char *fn,int (*func)(void *data,char *name,char *event,char *desc,char *long_desc, -char *pmu,char *unit,char *perpkg), +char *pmu,char *unit,char *perpkg, +char *metric_expr),void *data) {int err = -EIO ;
@@ -392,6 +396,7 @@ int json_events(const char *fn,char *filter =NULL ;char *perpkg =NULL ;char *unit =NULL ; +char *metric_expr =NULL ;unsigned long long eventcode =0 ;struct msrmap *msr =NULL ;jsmntok_t *msrval =NULL ;
@@ -402,6 +407,7 @@ int json_events(const char *fn,for (j =0 ; j < obj->size; j +=2 ) {jsmntok_t *field, *val;int nz; +char *s; field = tok + j; EXPECT(field->type == JSMN_STRING, tok + j,
@@ -448,7 +454,6 @@ int json_events(const char *fn, NULL); }else if (json_streq (map, field,"Unit" )) {const char *ppmu; -char *s; ppmu =field_to_perf (unit_to_pmu, map, val);if (ppmu) {
@@ -468,6 +473,10 @@ int json_events(const char *fn,addfield (map, &unit,"" ,"" , val); }else if (json_streq (map, field,"PerPkg" )) {addfield (map, &perpkg,"" ,"" , val); + }else if (json_streq (map, field,"MetricExpr" )) { +addfield (map, &metric_expr,"" ,"" , val); +for (s = metric_expr; *s; s++) + *s =tolower (*s); }/* ignore unknown fields */ }
@@ -492,7 +501,7 @@ int json_events(const char *fn,fixname (name); err =func (data, name,real_event (name, event), desc, long_desc, - pmu, unit, perpkg); + pmu, unit, perpkg, metric_expr);free (event);free (desc);free (name);
@@ -502,6 +511,7 @@ int json_events(const char *fn,free (filter);free (perpkg);free (unit); +free (metric_expr);if (err)break ; tok += j;
tools/perf/pmu-events/jevents.h +1 -1
@@ -5,7 +5,7 @@ int json_events(const char *fn,int (*func)(void *data,char *name,char *event,char *desc,char *long_desc,char *pmu, -char *unit,char *perpkg), +char *unit,char *perpkg,char *metric_expr), void *data);char *get_cpu_str (void );
tools/perf/pmu-events/pmu-events.h +1 -0
@@ -13,6 +13,7 @@ struct pmu_event {const char *pmu;const char *unit;const char *perpkg; +const char *metric_expr; };/*
tools/perf/util/pmu.c +6 -3
@@ -231,7 +231,8 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,static int __perf_pmu__new_alias (struct list_head *list,char *dir,char *name,char *desc__maybe_unused ,char *val,char *long_desc,char *topic, -char *unit,char *perpkg) +char *unit,char *perpkg, +char *dividedby) {struct perf_pmu_alias *alias;int ret;
@@ -265,6 +266,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,perf_pmu__parse_snapshot (alias, dir, name); } + alias->dividedby = dividedby ?strdup (dividedby) :NULL ; alias->desc = desc ?strdup (desc) :NULL ; alias->long_desc = long_desc ?strdup (long_desc) : desc ?strdup (desc) :NULL ;
@@ -294,7 +296,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI buf[ret] =0 ;return __perf_pmu__new_alias (list, dir, name,NULL , buf,NULL ,NULL ,NULL , -NULL ); +NULL ,NULL ); }static inline bool pmu_alias_info_file (char *name)
@@ -561,7 +563,8 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)__perf_pmu__new_alias (head,NULL , (char *)pe->name, (char *)pe->desc, (char *)pe->event, (char *)pe->long_desc, (char *)pe->topic, - (char *)pe->unit, (char *)pe->perpkg); + (char *)pe->unit, (char *)pe->perpkg, + (char *)pe->dividedby); } out:
tools/perf/util/pmu.h +1 -0
@@ -50,6 +50,7 @@ struct perf_pmu_alias {double scale;bool per_pkg;bool snapshot; +char *dividedby; };struct perf_pmu *perf_pmu__find (const char *name);
Signature · 1 line
2.9.3
PATCH 11/11 perf, tools, stat: Output JSON MetricExpr metric
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add generic infrastructure to perf stat to output ratios for "MetricExpr" entries in the event lists. Many events are more useful as ratios than in raw form, typically some count in relation to total ticks.
Transfer the MetricExpr information from the alias to the evsel.
We mark the events that need to be collected for MetricExpr, and also link the events using them with a pointer. The code is careful to always prefer the right event in the same group to minimize multiplexing errors. At the moment only a single relation is supported.
Then add a rblist to the stat shadow code that remembers stats based on the cpu and context.
Then finally update and retrieve and print these values similarly to the existing hardcoded perf metrics. We use the simple expression parser added earlier to evaluate the expression.
Normally we just output the result without further commentary, but for --metric-only this would lead to empty columns. So for this case use the original event as description.
So far there is no attempt to automatically add the MetricExpr event, if it is missing, however we suggest it to the user.
$ perf stat -a -I 1000 -e '{unc_p_clockticks,unc_p_freq_max_os_cycles}'
1.000228813 800,139,950 unc_p_clockticks
1.000228813 789,833,783 unc_p_freq_max_os_cycles # 98.7
2.000654229 800,308,990 unc_p_clockticks
2.000654229 396,214,238 unc_p_freq_max_os_cycles # 49.5$ perf stat -a -I 1000 -e '{unc_p_clockticks,unc_p_freq_max_os_cycles}' --metric-only
1.000206740 48.0
2.000451543 48.1v2: Change from DivideBy to MetricExpr
--- tools/perf/builtin-stat.c | 3 + tools/perf/util/evsel.c | 3 + tools/perf/util/evsel.h | 3 + tools/perf/util/parse-events.c | 1 + tools/perf/util/pmu.c | 8 ++- tools/perf/util/pmu.h | 3 +- tools/perf/util/stat-shadow.c | 152 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 2 + 8 files changed, 171 insertions(+), 4 deletions(-)
tools/perf/builtin-stat.c +3 -0
@@ -1141,6 +1141,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, out.print_metric = pm; out.new_line = nl; out.ctx = &os; + out.force_header = false;if (csv_output && !metric_only) {print_noise (counter, noise);
@@ -1465,6 +1466,7 @@ static void print_metric_headers(const char *prefix, bool no_indent) out.ctx = &os; out.print_metric = print_metric_header; out.new_line = new_line_metric; + out.force_header = true; os.evsel = counter; perf_stat__print_shadow_stats(counter, 0, 0,
@@ -2447,6 +2449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) argc =parse_options_subcommand (argc, argv, stat_options, stat_subcommands, (const char **) stat_usage,PARSE_OPT_STOP_AT_NON_OPTION ); +perf_stat__collect_metric_expr (evsel_list);perf_stat__init_shadow_stats ();if (csv_sep) {
tools/perf/util/evsel.c +3 -0
@@ -236,6 +236,9 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->sample_size =__perf_evsel__sample_size (attr->sample_type);perf_evsel__calc_id_pos (evsel); evsel->cmdline_group_boundary = false; + evsel->metric_expr =NULL ; + evsel->metric_event =NULL ; + evsel->collect_stat = false; }struct perf_evsel *perf_evsel__new_idx (struct perf_event_attr *attr,int idx)
tools/perf/util/evsel.h +3 -0
@@ -131,6 +131,9 @@ struct perf_evsel {struct list_head config_terms;int bpf_fd;bool merged_stat; +const char * metric_expr; +struct perf_evsel *metric_event; +bool collect_stat; };union u64_swap {
tools/perf/util/parse-events.c +1 -0
@@ -1252,6 +1252,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data, evsel->scale = info.scale; evsel->per_pkg = info.per_pkg; evsel->snapshot = info.snapshot; + evsel->metric_expr = info.metric_expr; }return evsel ?0 : -ENOMEM ;
tools/perf/util/pmu.c +5 -3
@@ -232,7 +232,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, char *desc __maybe_unused, char *val, char *long_desc, char *topic, char *unit, char *perpkg, - char *dividedby) + char *metric_expr) { struct perf_pmu_alias *alias;int ret;
@@ -266,7 +266,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,perf_pmu__parse_snapshot (alias, dir, name); } - alias->dividedby = dividedby ?strdup (dividedby) :NULL ; + alias->metric_expr = metric_expr ?strdup (metric_expr) :NULL ; alias->desc = desc ?strdup (desc) :NULL ; alias->long_desc = long_desc ?strdup (long_desc) : desc ?strdup (desc) :NULL ;
@@ -564,7 +564,7 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name) (char *)pe->desc, (char *)pe->event, (char *)pe->long_desc, (char *)pe->topic, (char *)pe->unit, (char *)pe->perpkg, - (char *)pe->dividedby); + (char *)pe->metric_expr); } out:
@@ -979,6 +979,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, info->unit =NULL ; info->scale =0.0 ; info->snapshot = false; + info->metric_expr =NULL ;list_for_each_entry_safe (term, h, head_terms, list) { alias =pmu_find_alias (pmu, term);
@@ -994,6 +995,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,if (alias->per_pkg) info->per_pkg = true; + info->metric_expr = alias->metric_expr;list_del (&term->list);free (term);
tools/perf/util/pmu.h +2 -1
@@ -31,6 +31,7 @@ struct perf_pmu {struct perf_pmu_info {const char *unit; +const char *metric_expr;double scale;bool per_pkg;bool snapshot;
@@ -50,7 +51,7 @@ struct perf_pmu_alias {double scale;bool per_pkg;bool snapshot; -char *dividedby; +char *metric_expr; };struct perf_pmu *perf_pmu__find (const char *name);
tools/perf/util/stat-shadow.c +152 -0
201 lines not on this page · raw message
tools/perf/util/stat.h +2 -0
@@ -85,11 +85,13 @@ struct perf_stat_output_ctx {void *ctx;print_metric_t print_metric;new_line_t new_line; +bool force_header; };void perf_stat__print_shadow_stats (struct perf_evsel *evsel,double avg,int cpu,struct perf_stat_output_ctx *out); +void perf_stat__collect_metric_expr (struct perf_evlist *);int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw);void perf_evlist__free_stats (struct perf_evlist *evlist);
Signature · 1 line
2.9.3