Skip to contentSkip to conversation

perf stat: Separate shadow counters code

PATCH Superseded Jiri Olsa 3 participants 13 messages Jun 1, 2015 – Jun 2, 2015 perf events

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Jiri Olsa

author reviewer
#0 lore raw

cover 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
author reviewer
#1 lore raw

PATCH 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
index a3e36fc634dc..9e057319933d 100644
@@ -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
index 21ec08247d47..f89f34f1a7a1 100644
@@ -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
index 2a4d1ec02846..abf0ff07b9cf 100644
@@ -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
#2 lore raw

Re: [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.

---
 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
index a3e36fc634dc..9e057319933d 100644
@@ -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
index 21ec08247d47..f89f34f1a7a1 100644
@@ -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
index 2a4d1ec02846..abf0ff07b9cf 100644
@@ -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
#3 lore raw

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

#4 lore raw

Re: [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

author reviewer
#5 lore raw

PATCH 2/9 perf stat: Replace transaction event check with nameid

In reply to Jiri Olsa

Using 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
index fd577f725d23..1f9269419b01 100644
@@ -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
index 9e057319933d..13a033f5e99e 100644
@@ -82,7 +82,11 @@ set_methods:
 
 #define ID(id, name) [PERF_EVSEL_NAMEID__##id] = #name
 static 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
index f89f34f1a7a1..3110bc34790e 100644
@@ -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
author reviewer
#6 lore raw

PATCH 3/9 perf stat: Remove setup_events function

In reply to Jiri Olsa

We 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
index 1f9269419b01..902d4a270021 100644
@@ -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
author reviewer
#7 lore raw

PATCH 4/9 perf stat: Remove transaction_run from shadow update/print code

In reply to Jiri Olsa

It'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
index 902d4a270021..793344620fcf 100644
@@ -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
author reviewer
#8 lore raw

PATCH 5/9 perf stat: Introduce reset_shadow_stats function

In reply to Jiri Olsa

Move 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
index 793344620fcf..72adb3813f77 100644
@@ -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
author reviewer
#9 lore raw

PATCH 6/9 perf stat: Introduce print_shadow_stats function

In reply to Jiri Olsa

Move 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
index 72adb3813f77..bdcfb29715bb 100644
@@ -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
author reviewer
#10 lore raw

PATCH 7/9 perf stat: Add output file argument to print_shadow_stats function

In reply to Jiri Olsa

As 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
index bdcfb29715bb..2e8f24ebc776 100644
@@ -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
author reviewer
#11 lore raw

PATCH 8/9 perf stat: Add aggr_mode argument to print_shadow_stats function

In reply to Jiri Olsa

As 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
index 2e8f24ebc776..697cec32aa9e 100644
@@ -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
author reviewer
#12 lore raw

PATCH 9/9 perf stat: Move shadow stat counters into separate object

In reply to Jiri Olsa

Separating 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
index 697cec32aa9e..c09e9f8ff5e9 100644
@@ -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
index e4b676de2f64..586a59d46022 100644
@@ -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
index 5667fc3e39cf..e5c3b4d19e2d 100644
@@ -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