perf stat: Separate shadow counters code
Jiri Olsa
reviewercover perf stat: Separate shadow counters code
hi,
sending cleanup/move of shadow counters. I need it for my other changes of stat scripting, but I think it can stand alone as a cleanup.
Also in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/shadow
I tested on Haswel with limited set of transaction events, but all seemed ok.
thanks,
jirka
Jiri Olsa (9):
perf tools: Add nameid value into evsel object
perf stat: Replace transaction event check with nameid perf stat: Remove setup_events function
perf stat: Remove transaction_run from shadow update/print code perf stat: Introduce reset_shadow_stats function
perf stat: Introduce print_shadow_stats function
perf stat: Add output file argument to print_shadow_stats function perf stat: Add aggr_mode argument to print_shadow_stats function perf stat: Move shadow stat counters into separate object
tools/perf/builtin-stat.c | 498 ++----------------------------------------------------------------------- tools/perf/util/Build | 1 + tools/perf/util/evsel.c | 26 ++++ tools/perf/util/evsel.h | 15 +++ tools/perf/util/parse-events.c | 2 +- tools/perf/util/stat-shadow.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 18 +++ 7 files changed, 507 insertions(+), 489 deletions(-) create mode 100644 tools/perf/util/stat-shadow.c
Jiri Olsa
reviewerPATCH 1/9 perf tools: Add nameid value into evsel object
Adding a way to tag an evsel object with ID value based on its name. It will be used for transaction events, but could be useful for others.
This way we can identify transactions events and get rid of the current position based way we use.
--- tools/perf/util/evsel.c | 22 ++++++++++++++++++++++ tools/perf/util/evsel.h | 11 +++++++++++ tools/perf/util/parse-events.c | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-)
tools/perf/util/evsel.c +22 -0
@@ -80,6 +80,28 @@ set_methods:return 0 ; } +#define ID (id, name) [PERF_EVSEL_NAMEID__##id] = #name +static const char *nameid_str[PERF_EVSEL_NAMEID__MAX ] = { +ID (NONE , x), +}; +#undef ID + +void perf_evsel__name_init (struct perf_evsel *evsel,char *name) +{ +enum perf_evsel_nameid nameid =PERF_EVSEL_NAMEID__NONE ; +int i; + +for (i =0 ; i <PERF_EVSEL_NAMEID__MAX ; i++) { +if (!strcmp (name, nameid_str[i])) { + nameid = i; +break ; + } + } + + evsel->nameid = nameid; + evsel->name =strdup (name); +} +#define FD (e, x, y) (*(int *)xyarray__entry(e->fd, x, y))int __perf_evsel__sample_size (u64 sample_type)
tools/perf/util/evsel.h +11 -0
@@ -46,6 +46,13 @@ struct perf_sample_id {struct cgroup_sel ; +enum perf_evsel_nameid { +PERF_EVSEL_NAMEID__NONE =0 , +PERF_EVSEL_NAMEID__MAX , +}; + +#define perf_evsel__is (evsel, id) (evsel->nameid == PERF_EVSEL_NAMEID__ ## id) +/** struct perf_evsel - event selector * * @name - Can be set to retain the original event name passed by the user,
@@ -100,6 +107,8 @@ struct perf_evsel {unsigned long *per_pkg_mask;struct perf_evsel *leader;char *group_name; + +enum perf_evsel_nameid nameid; };union u64_swap {
@@ -366,4 +375,6 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);int perf_event_attr__fprintf (FILE *fp,struct perf_event_attr *attr,attr__fprintf_f attr__fprintf,void *priv); +void perf_evsel__name_init (struct perf_evsel *evsel,char *name); +#endif /* __PERF_EVSEL_H */
tools/perf/util/parse-events.c +1 -1
@@ -890,7 +890,7 @@ int parse_events_name(struct list_head *list, char *name)__evlist__for_each (list, evsel) {if (!evsel->name) - evsel->name =strdup (name); +perf_evsel__name_init (evsel, name); }return 0 ;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 1/9] perf tools: Add nameid value into evsel object
Em Tue, Jun 02, 2015 at 12:59:55AM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Adding a way to tag an evsel object with ID value based on its name. It will be used for transaction events, but could be useful for others.
For what? Can you ellaborate? Just by looking at this commit message I can't figure out the value of this patch :-\
- Arnaldo
Quoted 93 lines
This way we can identify transactions events and get rid of the current position based way we use.
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evsel.c | 22 ++++++++++++++++++++++ tools/perf/util/evsel.h | 11 +++++++++++ tools/perf/util/parse-events.c | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-)tools/perf/util/evsel.c +22
-0@@ -80,6 +80,28 @@ set_methods:return 0 ; } +#define ID (id, name) [PERF_EVSEL_NAMEID__##id] = #name +static const char *nameid_str[PERF_EVSEL_NAMEID__MAX ] = { +ID (NONE , x), +}; +#undef ID + +void perf_evsel__name_init (struct perf_evsel *evsel,char *name) +{ +enum perf_evsel_nameid nameid =PERF_EVSEL_NAMEID__NONE ; +int i; + +for (i =0 ; i <PERF_EVSEL_NAMEID__MAX ; i++) { +if (!strcmp (name, nameid_str[i])) { + nameid = i; +break ; + } + } + + evsel->nameid = nameid; + evsel->name =strdup (name); +} +#define FD (e, x, y) (*(int *)xyarray__entry(e->fd, x, y))int __perf_evsel__sample_size (u64 sample_type)tools/perf/util/evsel.h +11
-0@@ -46,6 +46,13 @@ struct perf_sample_id {struct cgroup_sel ; +enum perf_evsel_nameid { +PERF_EVSEL_NAMEID__NONE =0 , +PERF_EVSEL_NAMEID__MAX , +}; + +#define perf_evsel__is (evsel, id) (evsel->nameid == PERF_EVSEL_NAMEID__ ## id) +/** struct perf_evsel - event selector * * @name - Can be set to retain the original event name passed by the user, @@ -100,6 +107,8 @@ struct perf_evsel {unsigned long *per_pkg_mask;struct perf_evsel *leader;char *group_name; + +enum perf_evsel_nameid nameid; };union u64_swap {@@ -366,4 +375,6 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);int perf_event_attr__fprintf (FILE *fp,struct perf_event_attr *attr,attr__fprintf_f attr__fprintf,void *priv); +void perf_evsel__name_init (struct perf_evsel *evsel,char *name); +#endif /* __PERF_EVSEL_H */ tools/perf/util/parse-events.c +1
-1@@ -890,7 +890,7 @@ int parse_events_name(struct list_head *list, char *name)__evlist__for_each (list, evsel) {if (!evsel->name) - evsel->name =strdup (name); +perf_evsel__name_init (evsel, name); }return 0 ;Signature · 1 line
1.9.3
Re: [PATCH 1/9] perf tools: Add nameid value into evsel object
Quoted 12 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 02, 2015 at 12:59:55AM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Adding a way to tag an evsel object with ID value based on its name. It will be used for transaction events, but could be useful for others.
For what? Can you ellaborate? Just by looking at this commit message I can't figure out the value of this patch :-\
- Arnaldo
Quoted 2 lines
This way we can identify transactions events and get rid of the current position based way we use.
well, right here ^^^
to get rid of getting ID of transaction events based on their possition in evlist
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 1/9] perf tools: Add nameid value into evsel object
Em Tue, Jun 02, 2015 at 08:46:36PM +0200, Jiri Olsa escreveu:
Quoted 11 lines · Arnaldo Carvalho de Melo
Quoted 10 lines
Em Tue, Jun 02, 2015 at 12:59:55AM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Adding a way to tag an evsel object with ID value based on its name. It will be used for transaction events, but could be useful for others.
For what? Can you ellaborate? Just by looking at this commit message I can't figure out the value of this patch :-\
- Arnaldo
Quoted 7 lines
Quoted 2 lines
Quoted 2 lines
This way we can identify transactions events and get rid of the current position based way we use.
well, right here ^^^
to get rid of getting ID of transaction events based on their possition in evlist
Well, as we discussed this may be implemented using evsel->priv/struct perf_stat, i.e. this seems something 'perf stat' specific, so no rush in moving this to the infrastructure available for all tools.
- Arnaldo
Jiri Olsa
reviewerPATCH 2/9 perf stat: Replace transaction event check with nameid
In reply to Jiri OlsaUsing nameids to check for transaction events,
instead of current possition based way.
--- tools/perf/builtin-stat.c | 55 ++++++----------------------------------------- tools/perf/util/evsel.c | 6 +++++- tools/perf/util/evsel.h | 4 ++++ 3 files changed, 16 insertions(+), 49 deletions(-)
tools/perf/builtin-stat.c +7 -48
@@ -96,17 +96,6 @@ static const char * const transaction_limited_attrs[] = {"}" }; -/* must match transaction_attrs and the beginning limited_attrs */ -enum { -T_TASK_CLOCK , -T_INSTRUCTIONS , -T_CYCLES , -T_CYCLES_IN_TX , -T_TRANSACTION_START , -T_ELISION_START , -T_CYCLES_IN_TX_CP , -}; -static struct perf_evlist *evsel_list;static struct target target = {
@@ -354,29 +343,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)return 0 ; } -static struct perf_evsel *nth_evsel (int n) -{ -static struct perf_evsel **array; -static int array_len; -struct perf_evsel *ev; -int j; - -/* Assumes this only called when evsel_list does not change anymore. */ -if (!array) { -evlist__for_each (evsel_list, ev) - array_len++; - array =malloc (array_len *sizeof (void *)); -if (!array) -exit (ENOMEM ); - j =0 ; -evlist__for_each (evsel_list, ev) - array[j++] = ev; - } -if (n < array_len) -return array[n]; -return NULL ; -} -/* * Update various tracking values we maintain to print * more semantic information such as miss/hit ratios,
@@ -391,14 +357,11 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count,update_stats (&runtime_nsecs_stats[cpu], count[0 ]); else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); - else if (transaction_run && -perf_evsel__cmp (counter ,nth_evsel (T_CYCLES_IN_TX ))) + else if (transaction_run && perf_evsel__is(counter, CYCLES_IN_TX)) update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); - else if (transaction_run && -perf_evsel__cmp (counter ,nth_evsel (T_TRANSACTION_START ))) + else if (transaction_run && perf_evsel__is(counter, TRANSACTION_START)) update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); - else if (transaction_run && -perf_evsel__cmp (counter ,nth_evsel (T_ELISION_START ))) + else if (transaction_run && perf_evsel__is(counter, ELISION_START)) update_stats(&runtime_elision_stats[ctx][cpu], count[0]); else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
@@ -1209,15 +1172,13 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) }else {fprintf (output," " ); } - }else if (transaction_run && -perf_evsel__cmp (evsel,nth_evsel (T_CYCLES_IN_TX ))) { + }else if (transaction_run &&perf_evsel__is (evsel,CYCLES_IN_TX )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]);if (total)fprintf (output," # %5.2f%% transactional cycles " ,100.0 * (avg / total)); - }else if (transaction_run && -perf_evsel__cmp (evsel,nth_evsel (T_CYCLES_IN_TX_CP ))) { + }else if (transaction_run &&perf_evsel__is (evsel,CYCLES_IN_TX_CP )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]); total2 =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]);if (total2 < avg)
@@ -1226,8 +1187,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)fprintf (output," # %5.2f%% aborted cycles " ,100.0 * ((total2-avg) / total)); - }else if (transaction_run && -perf_evsel__cmp (evsel,nth_evsel (T_TRANSACTION_START )) && + }else if (transaction_run &&perf_evsel__is (evsel,TRANSACTION_START ) && avg >0 && runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) { total =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]);
@@ -1236,8 +1196,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) ratio = total / avg;fprintf (output," # %8.0f cycles / transaction " , ratio); - }else if (transaction_run && -perf_evsel__cmp (evsel,nth_evsel (T_ELISION_START )) && + }else if (transaction_run &&perf_evsel__is (evsel,ELISION_START ) && avg >0 && runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) { total =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]);
tools/perf/util/evsel.c +5 -1
@@ -82,7 +82,11 @@ set_methods:#define ID (id, name) [PERF_EVSEL_NAMEID__##id] = #namestatic const char *nameid_str[PERF_EVSEL_NAMEID__MAX ] = { -ID (NONE , x), +ID (NONE , x), + ID(CYCLES_IN_TX, cpu/cycles-t/), + ID(TRANSACTION_START, cpu/tx-start/), + ID(ELISION_START, cpu/el-start/), + ID(CYCLES_IN_TX_CP, cpu/cycles-ct/), };#undef ID
tools/perf/util/evsel.h +4 -0
@@ -48,6 +48,10 @@ struct cgroup_sel;enum perf_evsel_nameid {PERF_EVSEL_NAMEID__NONE =0 , +PERF_EVSEL_NAMEID__CYCLES_IN_TX , +PERF_EVSEL_NAMEID__TRANSACTION_START , +PERF_EVSEL_NAMEID__ELISION_START , +PERF_EVSEL_NAMEID__CYCLES_IN_TX_CP ,PERF_EVSEL_NAMEID__MAX , };
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 3/9 perf stat: Remove setup_events function
In reply to Jiri OlsaWe can use already existing parse_events interface.
Both transaction_attrs and transaction_limited_attrs are changed to be single strings.
--- tools/perf/builtin-stat.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-)
tools/perf/builtin-stat.c +6 -19
@@ -73,8 +73,8 @@ static void print_counter(struct perf_evsel *counter, char *prefix);static void print_aggr (char *prefix);/* Default events used for perf stat -T */ -static const char *const transaction_attrs[] = { -"task-clock" , +static const char *transaction_attrs = { +"task-clock," "{" "instructions," "cycles,"
@@ -86,8 +86,8 @@ static const char * const transaction_attrs[] = { };/* More limited version when the CPU does not have all events. */ -static const char *const transaction_limited_attrs[] = { -"task-clock" , +static const char * transaction_limited_attrs = { +"task-clock," "{" "instructions," "cycles,"
@@ -1535,17 +1535,6 @@ static int perf_stat_init_aggr_mode(void)return 0 ; } -static int setup_events (const char *const *attrs,unsigned len) -{ -unsigned i; - -for (i =0 ; i < len; i++) { -if (parse_events (evsel_list, attrs[i],NULL )) -return -1 ; - } -return 0 ; -} -/* * Add default attributes, if there were no attributes specified or * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1667,11 +1656,9 @@ static int add_default_attributes(void)int err;if (pmu_have_event ("cpu" ,"cycles-ct" ) &&pmu_have_event ("cpu" ,"el-start" )) - err =setup_events (transaction_attrs, -ARRAY_SIZE (transaction_attrs)); + err =parse_events (evsel_list, transaction_attrs,NULL );else - err =setup_events (transaction_limited_attrs, -ARRAY_SIZE (transaction_limited_attrs)); + err =parse_events (evsel_list, transaction_limited_attrs,NULL );if (err <0 ) {fprintf (stderr,"Cannot set up transaction events\n" );return -1 ;
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 4/9 perf stat: Remove transaction_run from shadow update/print code
In reply to Jiri OlsaIt's no longer needed, because we use nameid to recognize transaction events.
Keeping it only in stat code to initialize transaction events.
--- tools/perf/builtin-stat.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
tools/perf/builtin-stat.c +11 -9
@@ -357,11 +357,11 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count,update_stats (&runtime_nsecs_stats[cpu], count[0 ]); else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); - else if (transaction_run && perf_evsel__is(counter, CYCLES_IN_TX)) + else if (perf_evsel__is(counter, CYCLES_IN_TX)) update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); - else if (transaction_run && perf_evsel__is(counter, TRANSACTION_START)) + else if (perf_evsel__is(counter, TRANSACTION_START)) update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); - else if (transaction_run && perf_evsel__is(counter, ELISION_START)) + else if (perf_evsel__is(counter, ELISION_START)) update_stats(&runtime_elision_stats[ctx][cpu], count[0]); else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
@@ -1172,22 +1172,24 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) }else {fprintf (output," " ); } - }else if (transaction_run &&perf_evsel__is (evsel,CYCLES_IN_TX )) { + }else if (perf_evsel__is (evsel,CYCLES_IN_TX )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]); -if (total) +if (total) {fprintf (output," # %5.2f%% transactional cycles " ,100.0 * (avg / total)); - }else if (transaction_run &&perf_evsel__is (evsel,CYCLES_IN_TX_CP )) { + } + }else if (perf_evsel__is (evsel,CYCLES_IN_TX_CP )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]); total2 =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]);if (total2 < avg) total2 = avg; -if (total) +if (total) {fprintf (output," # %5.2f%% aborted cycles " ,100.0 * ((total2-avg) / total)); - }else if (transaction_run &&perf_evsel__is (evsel,TRANSACTION_START ) && + } + }else if (perf_evsel__is (evsel,TRANSACTION_START ) && avg >0 && runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) { total =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]);
@@ -1196,7 +1198,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) ratio = total / avg;fprintf (output," # %8.0f cycles / transaction " , ratio); - }else if (transaction_run &&perf_evsel__is (evsel,ELISION_START ) && + }else if (perf_evsel__is (evsel,ELISION_START ) && avg >0 && runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) { total =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 5/9 perf stat: Introduce reset_shadow_stats function
In reply to Jiri OlsaMove shadow counters reset code into separate function as preparation for moving it into its own object.
--- tools/perf/builtin-stat.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
tools/perf/builtin-stat.c +13 -8
@@ -281,15 +281,8 @@ static int evsel_context(struct perf_evsel *evsel)return ctx; } -static void perf_stat__reset_stats (struct perf_evlist *evlist) +static void reset_shadow_stats (void ) { -struct perf_evsel *evsel; - -evlist__for_each (evlist, evsel) { -perf_evsel__reset_stat_priv (evsel); -perf_evsel__reset_counts (evsel,perf_evsel__nr_cpus (evsel)); - } -memset (runtime_nsecs_stats,0 ,sizeof (runtime_nsecs_stats));memset (runtime_cycles_stats,0 ,sizeof (runtime_cycles_stats));memset (runtime_stalled_cycles_front_stats,0 ,sizeof (runtime_stalled_cycles_front_stats));
@@ -309,6 +302,18 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)memset (&walltime_nsecs_stats,0 ,sizeof (walltime_nsecs_stats)); } +static void perf_stat__reset_stats (struct perf_evlist *evlist) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +perf_evsel__reset_stat_priv (evsel); +perf_evsel__reset_counts (evsel,perf_evsel__nr_cpus (evsel)); + } + +reset_shadow_stats (); +} +static int create_perf_stat_counter (struct perf_evsel *evsel) {struct perf_event_attr *attr = &evsel->attr;
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 6/9 perf stat: Introduce print_shadow_stats function
In reply to Jiri OlsaMove shadow counters display code into separate function as preparation for moving it into its own object.
--- tools/perf/builtin-stat.c | 72 +++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 33 deletions(-)
tools/perf/builtin-stat.c +39 -33
@@ -1061,43 +1061,11 @@ static void print_ll_cache_misses(int cpu,fprintf (output," of all LL-cache hits " ); } -static void abs_printout (int id,int nr,struct perf_evsel *evsel,double avg) +static void print_shadow_stats (struct perf_evsel *evsel,double avg,int cpu) {double total, ratio =0.0 , total2; -double sc = evsel->scale; -const char *fmt; -int cpu =cpu_map__id_to_cpu (id);int ctx =evsel_context (evsel); -if (csv_output) { - fmt = sc !=1.0 ?"%.2f%s" :"%.0f%s" ; - }else { -if (big_num) - fmt = sc !=1.0 ?"%'18.2f%s" :"%'18.0f%s" ; -else - fmt = sc !=1.0 ?"%18.2f%s" :"%18.0f%s" ; - } - -aggr_printout (evsel, id, nr); - -if (aggr_mode ==AGGR_GLOBAL ) - cpu =0 ; - -fprintf (output, fmt, avg, csv_sep); - -if (evsel->unit) -fprintf (output,"%-*s%s" , - csv_output ?0 : unit_width, - evsel->unit, csv_sep); - -fprintf (output,"%-*s" , csv_output ?0 :25 ,perf_evsel__name (evsel)); - -if (evsel->cgrp) -fprintf (output,"%s%s" , csv_sep, evsel->cgrp->name); - -if (csv_output || interval) -return ; -if (perf_evsel__match (evsel,HARDWARE ,HW_INSTRUCTIONS )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]);if (total) {
@@ -1230,6 +1198,44 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) } } +static void abs_printout (int id,int nr,struct perf_evsel *evsel,double avg) +{ +double sc = evsel->scale; +const char *fmt; +int cpu =cpu_map__id_to_cpu (id); + +if (csv_output) { + fmt = sc !=1.0 ?"%.2f%s" :"%.0f%s" ; + }else { +if (big_num) + fmt = sc !=1.0 ?"%'18.2f%s" :"%'18.0f%s" ; +else + fmt = sc !=1.0 ?"%18.2f%s" :"%18.0f%s" ; + } + +aggr_printout (evsel, id, nr); + +if (aggr_mode ==AGGR_GLOBAL ) + cpu =0 ; + +fprintf (output, fmt, avg, csv_sep); + +if (evsel->unit) +fprintf (output,"%-*s%s" , + csv_output ?0 : unit_width, + evsel->unit, csv_sep); + +fprintf (output,"%-*s" , csv_output ?0 :25 ,perf_evsel__name (evsel)); + +if (evsel->cgrp) +fprintf (output,"%s%s" , csv_sep, evsel->cgrp->name); + +if (csv_output || interval) +return ; + +print_shadow_stats (evsel, avg, cpu); +} +static void print_aggr (char *prefix) {struct perf_evsel *counter;
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 7/9 perf stat: Add output file argument to print_shadow_stats function
In reply to Jiri OlsaAs preparation for moving shadow counters code into its own object.
--- tools/perf/builtin-stat.c | 112 +++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 56 deletions(-)
tools/perf/builtin-stat.c +56 -56
@@ -901,7 +901,7 @@ static const char *get_ratio_color(enum grc_type type, double ratio)return color; } -static void print_stalled_cycles_frontend (int cpu, +static void print_stalled_cycles_frontend (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -916,12 +916,12 @@ static void print_stalled_cycles_frontend(int cpu, color =get_ratio_color (GRC_STALLED_CYCLES_FE , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," frontend cycles idle " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," frontend cycles idle " ); } -static void print_stalled_cycles_backend (int cpu, +static void print_stalled_cycles_backend (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -936,12 +936,12 @@ static void print_stalled_cycles_backend(int cpu, color =get_ratio_color (GRC_STALLED_CYCLES_BE , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," backend cycles idle " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," backend cycles idle " ); } -static void print_branch_misses (int cpu, +static void print_branch_misses (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -956,12 +956,12 @@ static void print_branch_misses(int cpu, color =get_ratio_color (GRC_CACHE_MISSES , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," of all branches " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," of all branches " ); } -static void print_l1_dcache_misses (int cpu, +static void print_l1_dcache_misses (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -976,12 +976,12 @@ static void print_l1_dcache_misses(int cpu, color =get_ratio_color (GRC_CACHE_MISSES , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," of all L1-dcache hits " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," of all L1-dcache hits " ); } -static void print_l1_icache_misses (int cpu, +static void print_l1_icache_misses (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -996,12 +996,12 @@ static void print_l1_icache_misses(int cpu, color =get_ratio_color (GRC_CACHE_MISSES , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," of all L1-icache hits " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," of all L1-icache hits " ); } -static void print_dtlb_cache_misses (int cpu, +static void print_dtlb_cache_misses (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -1016,12 +1016,12 @@ static void print_dtlb_cache_misses(int cpu, color =get_ratio_color (GRC_CACHE_MISSES , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," of all dTLB cache hits " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," of all dTLB cache hits " ); } -static void print_itlb_cache_misses (int cpu, +static void print_itlb_cache_misses (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -1036,12 +1036,12 @@ static void print_itlb_cache_misses(int cpu, color =get_ratio_color (GRC_CACHE_MISSES , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," of all iTLB cache hits " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," of all iTLB cache hits " ); } -static void print_ll_cache_misses (int cpu, +static void print_ll_cache_misses (FILE *out,int cpu,struct perf_evsel *evsel__maybe_unused ,double avg) {
@@ -1056,12 +1056,12 @@ static void print_ll_cache_misses(int cpu, color =get_ratio_color (GRC_CACHE_MISSES , ratio); -fprintf (output," # " ); -color_fprintf (output, color,"%6.2f%%" , ratio); -fprintf (output," of all LL-cache hits " ); +fprintf (out," # " ); +color_fprintf (out, color,"%6.2f%%" , ratio); +fprintf (out," of all LL-cache hits " ); } -static void print_shadow_stats (struct perf_evsel *evsel,double avg,int cpu) +static void print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu) {double total, ratio =0.0 , total2;int ctx =evsel_context (evsel);
@@ -1070,59 +1070,59 @@ static void print_shadow_stats(struct perf_evsel *evsel, double avg, int cpu) total =avg_stats (&runtime_cycles_stats[ctx][cpu]);if (total) { ratio = avg / total; -fprintf (output," # %5.2f insns per cycle " , ratio); +fprintf (out," # %5.2f insns per cycle " , ratio); }else { -fprintf (output," " ); +fprintf (out," " ); } total =avg_stats (&runtime_stalled_cycles_front_stats[ctx][cpu]); total =max (total,avg_stats (&runtime_stalled_cycles_back_stats[ctx][cpu]));if (total && avg) { ratio = total / avg; -fprintf (output,"\n" ); +fprintf (out,"\n" );if (aggr_mode ==AGGR_NONE ) -fprintf (output," " ); -fprintf (output," # %5.2f stalled cycles per insn" , ratio); +fprintf (out," " ); +fprintf (out," # %5.2f stalled cycles per insn" , ratio); } }else if (perf_evsel__match (evsel,HARDWARE ,HW_BRANCH_MISSES ) && runtime_branches_stats[ctx][cpu].n !=0 ) { -print_branch_misses (cpu, evsel, avg); +print_branch_misses (out, cpu, evsel, avg); }else if ( evsel->attr.type ==PERF_TYPE_HW_CACHE && evsel->attr.config == (PERF_COUNT_HW_CACHE_L1D | ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && runtime_l1_dcache_stats[ctx][cpu].n !=0 ) { -print_l1_dcache_misses (cpu, evsel, avg); +print_l1_dcache_misses (out, cpu, evsel, avg); }else if ( evsel->attr.type ==PERF_TYPE_HW_CACHE && evsel->attr.config == (PERF_COUNT_HW_CACHE_L1I | ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && runtime_l1_icache_stats[ctx][cpu].n !=0 ) { -print_l1_icache_misses (cpu, evsel, avg); +print_l1_icache_misses (out, cpu, evsel, avg); }else if ( evsel->attr.type ==PERF_TYPE_HW_CACHE && evsel->attr.config == (PERF_COUNT_HW_CACHE_DTLB | ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && runtime_dtlb_cache_stats[ctx][cpu].n !=0 ) { -print_dtlb_cache_misses (cpu, evsel, avg); +print_dtlb_cache_misses (out, cpu, evsel, avg); }else if ( evsel->attr.type ==PERF_TYPE_HW_CACHE && evsel->attr.config == (PERF_COUNT_HW_CACHE_ITLB | ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && runtime_itlb_cache_stats[ctx][cpu].n !=0 ) { -print_itlb_cache_misses (cpu, evsel, avg); +print_itlb_cache_misses (out, cpu, evsel, avg); }else if ( evsel->attr.type ==PERF_TYPE_HW_CACHE && evsel->attr.config == (PERF_COUNT_HW_CACHE_LL | ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && runtime_ll_cache_stats[ctx][cpu].n !=0 ) { -print_ll_cache_misses (cpu, evsel, avg); +print_ll_cache_misses (out, cpu, evsel, avg); }else if (perf_evsel__match (evsel,HARDWARE ,HW_CACHE_MISSES ) && runtime_cacherefs_stats[ctx][cpu].n !=0 ) { total =avg_stats (&runtime_cacherefs_stats[ctx][cpu]);
@@ -1130,25 +1130,25 @@ static void print_shadow_stats(struct perf_evsel *evsel, double avg, int cpu)if (total) ratio = avg *100 / total; -fprintf (output," # %8.3f %% of all cache refs " , ratio); +fprintf (out," # %8.3f %% of all cache refs " , ratio); }else if (perf_evsel__match (evsel,HARDWARE ,HW_STALLED_CYCLES_FRONTEND )) { -print_stalled_cycles_frontend (cpu, evsel, avg); +print_stalled_cycles_frontend (out, cpu, evsel, avg); }else if (perf_evsel__match (evsel,HARDWARE ,HW_STALLED_CYCLES_BACKEND )) { -print_stalled_cycles_backend (cpu, evsel, avg); +print_stalled_cycles_backend (out, cpu, evsel, avg); }else if (perf_evsel__match (evsel,HARDWARE ,HW_CPU_CYCLES )) { total =avg_stats (&runtime_nsecs_stats[cpu]);if (total) { ratio = avg / total; -fprintf (output," # %8.3f GHz " , ratio); +fprintf (out," # %8.3f GHz " , ratio); }else { -fprintf (output," " ); +fprintf (out," " ); } }else if (perf_evsel__is (evsel,CYCLES_IN_TX )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]);if (total) { -fprintf (output, +fprintf (out," # %5.2f%% transactional cycles " ,100.0 * (avg / total)); }
@@ -1158,7 +1158,7 @@ static void print_shadow_stats(struct perf_evsel *evsel, double avg, int cpu)if (total2 < avg) total2 = avg;if (total) { -fprintf (output, +fprintf (out," # %5.2f%% aborted cycles " ,100.0 * ((total2-avg) / total)); }
@@ -1170,7 +1170,7 @@ static void print_shadow_stats(struct perf_evsel *evsel, double avg, int cpu)if (total) ratio = total / avg; -fprintf (output," # %8.0f cycles / transaction " , ratio); +fprintf (out," # %8.0f cycles / transaction " , ratio); }else if (perf_evsel__is (evsel,ELISION_START ) && avg >0 && runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) {
@@ -1179,7 +1179,7 @@ static void print_shadow_stats(struct perf_evsel *evsel, double avg, int cpu)if (total) ratio = total / avg; -fprintf (output," # %8.0f cycles / elision " , ratio); +fprintf (out," # %8.0f cycles / elision " , ratio); }else if (runtime_nsecs_stats[cpu].n !=0 ) {char unit ='M' ;
@@ -1192,9 +1192,9 @@ static void print_shadow_stats(struct perf_evsel *evsel, double avg, int cpu) unit ='K' ; } -fprintf (output," # %8.3f %c/sec " , ratio, unit); +fprintf (out," # %8.3f %c/sec " , ratio, unit); }else { -fprintf (output," " ); +fprintf (out," " ); } }
@@ -1233,7 +1233,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (csv_output || interval)return ; -print_shadow_stats (evsel, avg, cpu); +print_shadow_stats (output, evsel, avg, cpu); }static void print_aggr (char *prefix)
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 8/9 perf stat: Add aggr_mode argument to print_shadow_stats function
In reply to Jiri OlsaAs preparation for moving shadow counters code into its own object.
--- tools/perf/builtin-stat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
tools/perf/builtin-stat.c +4 -3
@@ -1061,7 +1061,8 @@ static void print_ll_cache_misses(FILE *out, int cpu,fprintf (out," of all LL-cache hits " ); } -static void print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu) +static void print_shadow_stats (FILE *out,struct perf_evsel *evsel, +double avg,int cpu,enum aggr_mode aggr) {double total, ratio =0.0 , total2;int ctx =evsel_context (evsel);
@@ -1080,7 +1081,7 @@ static void print_shadow_stats(FILE *out, struct perf_evsel *evsel, double avg,if (total && avg) { ratio = total / avg;fprintf (out,"\n" ); -if (aggr_mode ==AGGR_NONE ) +if (aggr ==AGGR_NONE )fprintf (out," " );fprintf (out," # %5.2f stalled cycles per insn" , ratio); }
@@ -1233,7 +1234,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (csv_output || interval)return ; -print_shadow_stats (output, evsel, avg, cpu); +print_shadow_stats (output, evsel, avg, cpu, aggr_mode); }static void print_aggr (char *prefix)
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 9/9 perf stat: Move shadow stat counters into separate object
In reply to Jiri OlsaSeparating shadow counters code into separate object as a cleanup, but mainly for upcomming changes, so could use it from script command context.
--- tools/perf/builtin-stat.c | 446 +----------------------------------------- tools/perf/util/Build | 1 + tools/perf/util/stat-shadow.c | 436 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 18 ++ 4 files changed, 459 insertions(+), 442 deletions(-) create mode 100644 tools/perf/util/stat-shadow.c
tools/perf/builtin-stat.c +4 -442
@@ -102,13 +102,6 @@ static struct target target = { .uid = UINT_MAX, }; -enum aggr_mode { -AGGR_NONE , -AGGR_GLOBAL , -AGGR_SOCKET , -AGGR_CORE , -}; -static int run_count =1 ;static bool no_inherit = false;static bool scale = true;
@@ -236,72 +229,6 @@ out_free:return -1 ; } -enum { -CTX_BIT_USER =1 <<0 , -CTX_BIT_KERNEL =1 <<1 , -CTX_BIT_HV =1 <<2 , -CTX_BIT_HOST =1 <<3 , -CTX_BIT_IDLE =1 <<4 , -CTX_BIT_MAX =1 <<5 , -}; - -#define NUM_CTX CTX_BIT_MAX - -static struct stats runtime_nsecs_stats[MAX_NR_CPUS ]; -static struct stats runtime_cycles_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_stalled_cycles_front_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_stalled_cycles_back_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_branches_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_cacherefs_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_l1_dcache_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_l1_icache_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_ll_cache_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_itlb_cache_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_dtlb_cache_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_cycles_in_tx_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats walltime_nsecs_stats; -static struct stats runtime_transaction_stats[NUM_CTX ][MAX_NR_CPUS ]; -static struct stats runtime_elision_stats[NUM_CTX ][MAX_NR_CPUS ]; - -static int evsel_context (struct perf_evsel *evsel) -{ -int ctx =0 ; - -if (evsel->attr.exclude_kernel) - ctx |=CTX_BIT_KERNEL ; -if (evsel->attr.exclude_user) - ctx |=CTX_BIT_USER ; -if (evsel->attr.exclude_hv) - ctx |=CTX_BIT_HV ; -if (evsel->attr.exclude_host) - ctx |=CTX_BIT_HOST ; -if (evsel->attr.exclude_idle) - ctx |=CTX_BIT_IDLE ; - -return ctx; -} - -static void reset_shadow_stats (void ) -{ -memset (runtime_nsecs_stats,0 ,sizeof (runtime_nsecs_stats)); -memset (runtime_cycles_stats,0 ,sizeof (runtime_cycles_stats)); -memset (runtime_stalled_cycles_front_stats,0 ,sizeof (runtime_stalled_cycles_front_stats)); -memset (runtime_stalled_cycles_back_stats,0 ,sizeof (runtime_stalled_cycles_back_stats)); -memset (runtime_branches_stats,0 ,sizeof (runtime_branches_stats)); -memset (runtime_cacherefs_stats,0 ,sizeof (runtime_cacherefs_stats)); -memset (runtime_l1_dcache_stats,0 ,sizeof (runtime_l1_dcache_stats)); -memset (runtime_l1_icache_stats,0 ,sizeof (runtime_l1_icache_stats)); -memset (runtime_ll_cache_stats,0 ,sizeof (runtime_ll_cache_stats)); -memset (runtime_itlb_cache_stats,0 ,sizeof (runtime_itlb_cache_stats)); -memset (runtime_dtlb_cache_stats,0 ,sizeof (runtime_dtlb_cache_stats)); -memset (runtime_cycles_in_tx_stats,0 , -sizeof (runtime_cycles_in_tx_stats)); -memset (runtime_transaction_stats,0 , -sizeof (runtime_transaction_stats)); -memset (runtime_elision_stats,0 ,sizeof (runtime_elision_stats)); -memset (&walltime_nsecs_stats,0 ,sizeof (walltime_nsecs_stats)); -} -static void perf_stat__reset_stats (struct perf_evlist *evlist) {struct perf_evsel *evsel;
@@ -311,7 +238,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)perf_evsel__reset_counts (evsel,perf_evsel__nr_cpus (evsel)); } -reset_shadow_stats (); +perf_stat__reset_shadow_stats (); }static int create_perf_stat_counter (struct perf_evsel *evsel)
@@ -348,46 +275,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)return 0 ; } -/* -* Update various tracking values we maintain to print -* more semantic information such as miss/hit ratios, -* instruction rates, etc: -*/ -static void update_shadow_stats (struct perf_evsel *counter,u64 *count, -int cpu) -{ -int ctx =evsel_context (counter); - -if (perf_evsel__match (counter,SOFTWARE ,SW_TASK_CLOCK )) -update_stats (&runtime_nsecs_stats[cpu], count[0 ]); -else if (perf_evsel__match (counter,HARDWARE ,HW_CPU_CYCLES )) -update_stats (&runtime_cycles_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__is (counter,CYCLES_IN_TX )) -update_stats (&runtime_transaction_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__is (counter,TRANSACTION_START )) -update_stats (&runtime_transaction_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__is (counter,ELISION_START )) -update_stats (&runtime_elision_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HARDWARE ,HW_STALLED_CYCLES_FRONTEND )) -update_stats (&runtime_stalled_cycles_front_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HARDWARE ,HW_STALLED_CYCLES_BACKEND )) -update_stats (&runtime_stalled_cycles_back_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HARDWARE ,HW_BRANCH_INSTRUCTIONS )) -update_stats (&runtime_branches_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HARDWARE ,HW_CACHE_REFERENCES )) -update_stats (&runtime_cacherefs_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HW_CACHE ,HW_CACHE_L1D )) -update_stats (&runtime_l1_dcache_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HW_CACHE ,HW_CACHE_L1I )) -update_stats (&runtime_ll_cache_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HW_CACHE ,HW_CACHE_LL )) -update_stats (&runtime_ll_cache_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HW_CACHE ,HW_CACHE_DTLB )) -update_stats (&runtime_dtlb_cache_stats[ctx][cpu], count[0 ]); -else if (perf_evsel__match (counter,HW_CACHE ,HW_CACHE_ITLB )) -update_stats (&runtime_itlb_cache_stats[ctx][cpu], count[0 ]); -} -static void zero_per_pkg (struct perf_evsel *counter) {if (counter->per_pkg_mask)
@@ -448,7 +335,7 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,perf_counts_values__scale (count, scale,NULL ); evsel->counts->cpu[cpu] = *count;if (aggr_mode ==AGGR_NONE ) -update_shadow_stats (evsel, count->values, cpu); +perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL : aggr->val += count->val;
@@ -496,7 +383,7 @@ static int read_counter_aggr(struct perf_evsel *counter)/* * Save the full runtime - to allow normalization during printout: */ -update_shadow_stats (counter, count,0 ); +perf_stat__update_shadow_stats (counter, count,0 );return 0 ; }
@@ -874,331 +761,6 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)fprintf (output," " ); } -/* used for get_ratio_color() */ -enum grc_type { -GRC_STALLED_CYCLES_FE , -GRC_STALLED_CYCLES_BE , -GRC_CACHE_MISSES , -GRC_MAX_NR -}; - -static const char *get_ratio_color (enum grc_type type,double ratio) -{ -static const double grc_table[GRC_MAX_NR ][3 ] = { - [GRC_STALLED_CYCLES_FE ] = {50.0 ,30.0 ,10.0 }, - [GRC_STALLED_CYCLES_BE ] = {75.0 ,50.0 ,20.0 }, - [GRC_CACHE_MISSES ] = {20.0 ,10.0 ,5.0 }, - }; -const char *color =PERF_COLOR_NORMAL ; - -if (ratio > grc_table[type][0 ]) - color =PERF_COLOR_RED ; -else if (ratio > grc_table[type][1 ]) - color =PERF_COLOR_MAGENTA ; -else if (ratio > grc_table[type][2 ]) - color =PERF_COLOR_YELLOW ; - -return color; -} - -static void print_stalled_cycles_frontend (FILE *out,int cpu, -struct perf_evsel *evsel -__maybe_unused ,double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_cycles_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_STALLED_CYCLES_FE , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," frontend cycles idle " ); -} - -static void print_stalled_cycles_backend (FILE *out,int cpu, -struct perf_evsel *evsel -__maybe_unused ,double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_cycles_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_STALLED_CYCLES_BE , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," backend cycles idle " ); -} - -static void print_branch_misses (FILE *out,int cpu, -struct perf_evsel *evsel__maybe_unused , -double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_branches_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_CACHE_MISSES , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," of all branches " ); -} - -static void print_l1_dcache_misses (FILE *out,int cpu, -struct perf_evsel *evsel__maybe_unused , -double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_l1_dcache_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_CACHE_MISSES , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," of all L1-dcache hits " ); -} - -static void print_l1_icache_misses (FILE *out,int cpu, -struct perf_evsel *evsel__maybe_unused , -double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_l1_icache_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_CACHE_MISSES , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," of all L1-icache hits " ); -} - -static void print_dtlb_cache_misses (FILE *out,int cpu, -struct perf_evsel *evsel__maybe_unused , -double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_dtlb_cache_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_CACHE_MISSES , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," of all dTLB cache hits " ); -} - -static void print_itlb_cache_misses (FILE *out,int cpu, -struct perf_evsel *evsel__maybe_unused , -double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_itlb_cache_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_CACHE_MISSES , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," of all iTLB cache hits " ); -} - -static void print_ll_cache_misses (FILE *out,int cpu, -struct perf_evsel *evsel__maybe_unused , -double avg) -{ -double total, ratio =0.0 ; -const char *color; -int ctx =evsel_context (evsel); - - total =avg_stats (&runtime_ll_cache_stats[ctx][cpu]); - -if (total) - ratio = avg / total *100.0 ; - - color =get_ratio_color (GRC_CACHE_MISSES , ratio); - -fprintf (out," # " ); -color_fprintf (out, color,"%6.2f%%" , ratio); -fprintf (out," of all LL-cache hits " ); -} - -static void print_shadow_stats (FILE *out,struct perf_evsel *evsel, -double avg,int cpu,enum aggr_mode aggr) -{ -double total, ratio =0.0 , total2; -int ctx =evsel_context (evsel); - -if (perf_evsel__match (evsel,HARDWARE ,HW_INSTRUCTIONS )) { - total =avg_stats (&runtime_cycles_stats[ctx][cpu]); -if (total) { - ratio = avg / total; -fprintf (out," # %5.2f insns per cycle " , ratio); - }else { -fprintf (out," " ); - } - total =avg_stats (&runtime_stalled_cycles_front_stats[ctx][cpu]); - total =max (total,avg_stats (&runtime_stalled_cycles_back_stats[ctx][cpu])); - -if (total && avg) { - ratio = total / avg; -fprintf (out,"\n" ); -if (aggr ==AGGR_NONE ) -fprintf (out," " ); -fprintf (out," # %5.2f stalled cycles per insn" , ratio); - } - - }else if (perf_evsel__match (evsel,HARDWARE ,HW_BRANCH_MISSES ) && - runtime_branches_stats[ctx][cpu].n !=0 ) { -print_branch_misses (out, cpu, evsel, avg); - }else if ( - evsel->attr.type ==PERF_TYPE_HW_CACHE && - evsel->attr.config == (PERF_COUNT_HW_CACHE_L1D | - ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && - runtime_l1_dcache_stats[ctx][cpu].n !=0 ) { -print_l1_dcache_misses (out, cpu, evsel, avg); - }else if ( - evsel->attr.type ==PERF_TYPE_HW_CACHE && - evsel->attr.config == (PERF_COUNT_HW_CACHE_L1I | - ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && - runtime_l1_icache_stats[ctx][cpu].n !=0 ) { -print_l1_icache_misses (out, cpu, evsel, avg); - }else if ( - evsel->attr.type ==PERF_TYPE_HW_CACHE && - evsel->attr.config == (PERF_COUNT_HW_CACHE_DTLB | - ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && - runtime_dtlb_cache_stats[ctx][cpu].n !=0 ) { -print_dtlb_cache_misses (out, cpu, evsel, avg); - }else if ( - evsel->attr.type ==PERF_TYPE_HW_CACHE && - evsel->attr.config == (PERF_COUNT_HW_CACHE_ITLB | - ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && - runtime_itlb_cache_stats[ctx][cpu].n !=0 ) { -print_itlb_cache_misses (out, cpu, evsel, avg); - }else if ( - evsel->attr.type ==PERF_TYPE_HW_CACHE && - evsel->attr.config == (PERF_COUNT_HW_CACHE_LL | - ((PERF_COUNT_HW_CACHE_OP_READ ) <<8 ) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS ) <<16 )) && - runtime_ll_cache_stats[ctx][cpu].n !=0 ) { -print_ll_cache_misses (out, cpu, evsel, avg); - }else if (perf_evsel__match (evsel,HARDWARE ,HW_CACHE_MISSES ) && - runtime_cacherefs_stats[ctx][cpu].n !=0 ) { - total =avg_stats (&runtime_cacherefs_stats[ctx][cpu]); - -if (total) - ratio = avg *100 / total; - -fprintf (out," # %8.3f %% of all cache refs " , ratio); - - }else if (perf_evsel__match (evsel,HARDWARE ,HW_STALLED_CYCLES_FRONTEND )) { -print_stalled_cycles_frontend (out, cpu, evsel, avg); - }else if (perf_evsel__match (evsel,HARDWARE ,HW_STALLED_CYCLES_BACKEND )) { -print_stalled_cycles_backend (out, cpu, evsel, avg); - }else if (perf_evsel__match (evsel,HARDWARE ,HW_CPU_CYCLES )) { - total =avg_stats (&runtime_nsecs_stats[cpu]); - -if (total) { - ratio = avg / total; -fprintf (out," # %8.3f GHz " , ratio); - }else { -fprintf (out," " ); - } - }else if (perf_evsel__is (evsel,CYCLES_IN_TX )) { - total =avg_stats (&runtime_cycles_stats[ctx][cpu]); -if (total) { -fprintf (out, -" # %5.2f%% transactional cycles " , -100.0 * (avg / total)); - } - }else if (perf_evsel__is (evsel,CYCLES_IN_TX_CP )) { - total =avg_stats (&runtime_cycles_stats[ctx][cpu]); - total2 =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]); -if (total2 < avg) - total2 = avg; -if (total) { -fprintf (out, -" # %5.2f%% aborted cycles " , -100.0 * ((total2-avg) / total)); - } - }else if (perf_evsel__is (evsel,TRANSACTION_START ) && - avg >0 && - runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) { - total =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]); - -if (total) - ratio = total / avg; - -fprintf (out," # %8.0f cycles / transaction " , ratio); - }else if (perf_evsel__is (evsel,ELISION_START ) && - avg >0 && - runtime_cycles_in_tx_stats[ctx][cpu].n !=0 ) { - total =avg_stats (&runtime_cycles_in_tx_stats[ctx][cpu]); - -if (total) - ratio = total / avg; - -fprintf (out," # %8.0f cycles / elision " , ratio); - }else if (runtime_nsecs_stats[cpu].n !=0 ) { -char unit ='M' ; - - total =avg_stats (&runtime_nsecs_stats[cpu]); - -if (total) - ratio =1000.0 * avg / total; -if (ratio <0.001 ) { - ratio *=1000 ; - unit ='K' ; - } - -fprintf (out," # %8.3f %c/sec " , ratio, unit); - }else { -fprintf (out," " ); - } -} -static void abs_printout (int id,int nr,struct perf_evsel *evsel,double avg) {double sc = evsel->scale;
@@ -1234,7 +796,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (csv_output || interval)return ; -print_shadow_stats (output, evsel, avg, cpu, aggr_mode); +perf_stat__print_shadow_stats (output, evsel, avg, cpu, aggr_mode); }static void print_aggr (char *prefix)
tools/perf/util/Build +1 -0
@@ -68,6 +68,7 @@ libperf-y += rblist.o libperf-y += intlist.o libperf-y += vdso.o libperf-y += stat.o +libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o
tools/perf/util/stat-shadow.c new file +436 -0
436 lines not on this page · raw message
tools/perf/util/stat.h +18 -0
@@ -2,6 +2,7 @@#define __PERF_STATS_H#include <linux/types.h> +#include <stdio.h> struct stats {
@@ -22,4 +23,21 @@ static inline void init_stats(struct stats *stats) stats->min = (u64) -1 ; stats->max = 0; } + +enum aggr_mode { +AGGR_NONE , +AGGR_GLOBAL , +AGGR_SOCKET , +AGGR_CORE , +}; + +extern struct stats walltime_nsecs_stats; +struct perf_evsel ; + +void perf_stat__reset_shadow_stats (void ); +void perf_stat__update_shadow_stats (struct perf_evsel *counter,u64 *count, +int cpu); +void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel, +double avg,int cpu,enum aggr_mode aggr); +#endif
Signature · 1 line
1.9.3