diff options
Diffstat (limited to 'tools/perf/util/stat-shadow.c')
| -rw-r--r-- | tools/perf/util/stat-shadow.c | 135 | 
1 files changed, 85 insertions, 50 deletions
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index accb1bf1cfd8..70c87fdb2a43 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -25,12 +25,14 @@ struct stats walltime_nsecs_stats;  struct saved_value {  	struct rb_node rb_node; -	struct perf_evsel *evsel; +	struct evsel *evsel;  	enum stat_type type;  	int ctx;  	int cpu;  	struct runtime_stat *stat;  	struct stats stats; +	u64 metric_total; +	int metric_other;  };  static int saved_value_cmp(struct rb_node *rb_node, const void *entry) @@ -94,7 +96,7 @@ static void saved_value_delete(struct rblist *rblist __maybe_unused,  	free(v);  } -static struct saved_value *saved_value_lookup(struct perf_evsel *evsel, +static struct saved_value *saved_value_lookup(struct evsel *evsel,  					      int cpu,  					      bool create,  					      enum stat_type type, @@ -146,19 +148,19 @@ void perf_stat__init_shadow_stats(void)  	runtime_stat__init(&rt_stat);  } -static int evsel_context(struct perf_evsel *evsel) +static int evsel_context(struct evsel *evsel)  {  	int ctx = 0; -	if (evsel->attr.exclude_kernel) +	if (evsel->core.attr.exclude_kernel)  		ctx |= CTX_BIT_KERNEL; -	if (evsel->attr.exclude_user) +	if (evsel->core.attr.exclude_user)  		ctx |= CTX_BIT_USER; -	if (evsel->attr.exclude_hv) +	if (evsel->core.attr.exclude_hv)  		ctx |= CTX_BIT_HV; -	if (evsel->attr.exclude_host) +	if (evsel->core.attr.exclude_host)  		ctx |= CTX_BIT_HOST; -	if (evsel->attr.exclude_idle) +	if (evsel->core.attr.exclude_idle)  		ctx |= CTX_BIT_IDLE;  	return ctx; @@ -207,11 +209,12 @@ static void update_runtime_stat(struct runtime_stat *st,   * more semantic information such as miss/hit ratios,   * instruction rates, etc:   */ -void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, +void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,  				    int cpu, struct runtime_stat *st)  {  	int ctx = evsel_context(counter);  	u64 count_ns = count; +	struct saved_value *v;  	count *= counter->scale; @@ -266,9 +269,15 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,  		update_runtime_stat(st, STAT_APERF, ctx, cpu, count);  	if (counter->collect_stat) { -		struct saved_value *v = saved_value_lookup(counter, cpu, true, -							   STAT_NONE, 0, st); +		v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st);  		update_stats(&v->stats, count); +		if (counter->metric_leader) +			v->metric_total += count; +	} else if (counter->metric_leader) { +		v = saved_value_lookup(counter->metric_leader, +				       cpu, true, STAT_NONE, 0, st); +		v->metric_total += count; +		v->metric_other++;  	}  } @@ -299,10 +308,10 @@ static const char *get_ratio_color(enum grc_type type, double ratio)  	return color;  } -static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list, +static struct evsel *perf_stat__find_event(struct evlist *evsel_list,  						const char *name)  { -	struct perf_evsel *c2; +	struct evsel *c2;  	evlist__for_each_entry (evsel_list, c2) {  		if (!strcasecmp(c2->name, name) && !c2->collect_stat) @@ -312,9 +321,9 @@ static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list,  }  /* Mark MetricExpr target events and link events using them to them. */ -void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) +void perf_stat__collect_metric_expr(struct evlist *evsel_list)  { -	struct perf_evsel *counter, *leader, **metric_events, *oc; +	struct evsel *counter, *leader, **metric_events, *oc;  	bool found;  	const char **metric_names;  	int i; @@ -332,7 +341,7 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list)  						&metric_names, &num_metric_names) < 0)  				continue; -			metric_events = calloc(sizeof(struct perf_evsel *), +			metric_events = calloc(sizeof(struct evsel *),  					       num_metric_names + 1);  			if (!metric_events)  				return; @@ -415,7 +424,7 @@ static double runtime_stat_n(struct runtime_stat *st,  static void print_stalled_cycles_frontend(struct perf_stat_config *config,  					  int cpu, -					  struct perf_evsel *evsel, double avg, +					  struct evsel *evsel, double avg,  					  struct perf_stat_output_ctx *out,  					  struct runtime_stat *st)  { @@ -439,7 +448,7 @@ static void print_stalled_cycles_frontend(struct perf_stat_config *config,  static void print_stalled_cycles_backend(struct perf_stat_config *config,  					 int cpu, -					 struct perf_evsel *evsel, double avg, +					 struct evsel *evsel, double avg,  					 struct perf_stat_output_ctx *out,  					 struct runtime_stat *st)  { @@ -459,7 +468,7 @@ static void print_stalled_cycles_backend(struct perf_stat_config *config,  static void print_branch_misses(struct perf_stat_config *config,  				int cpu, -				struct perf_evsel *evsel, +				struct evsel *evsel,  				double avg,  				struct perf_stat_output_ctx *out,  				struct runtime_stat *st) @@ -480,7 +489,7 @@ static void print_branch_misses(struct perf_stat_config *config,  static void print_l1_dcache_misses(struct perf_stat_config *config,  				   int cpu, -				   struct perf_evsel *evsel, +				   struct evsel *evsel,  				   double avg,  				   struct perf_stat_output_ctx *out,  				   struct runtime_stat *st) @@ -502,7 +511,7 @@ static void print_l1_dcache_misses(struct perf_stat_config *config,  static void print_l1_icache_misses(struct perf_stat_config *config,  				   int cpu, -				   struct perf_evsel *evsel, +				   struct evsel *evsel,  				   double avg,  				   struct perf_stat_output_ctx *out,  				   struct runtime_stat *st) @@ -523,7 +532,7 @@ static void print_l1_icache_misses(struct perf_stat_config *config,  static void print_dtlb_cache_misses(struct perf_stat_config *config,  				    int cpu, -				    struct perf_evsel *evsel, +				    struct evsel *evsel,  				    double avg,  				    struct perf_stat_output_ctx *out,  				    struct runtime_stat *st) @@ -543,7 +552,7 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config,  static void print_itlb_cache_misses(struct perf_stat_config *config,  				    int cpu, -				    struct perf_evsel *evsel, +				    struct evsel *evsel,  				    double avg,  				    struct perf_stat_output_ctx *out,  				    struct runtime_stat *st) @@ -563,7 +572,7 @@ static void print_itlb_cache_misses(struct perf_stat_config *config,  static void print_ll_cache_misses(struct perf_stat_config *config,  				  int cpu, -				  struct perf_evsel *evsel, +				  struct evsel *evsel,  				  double avg,  				  struct perf_stat_output_ctx *out,  				  struct runtime_stat *st) @@ -686,7 +695,7 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)  }  static void print_smi_cost(struct perf_stat_config *config, -			   int cpu, struct perf_evsel *evsel, +			   int cpu, struct evsel *evsel,  			   struct perf_stat_output_ctx *out,  			   struct runtime_stat *st)  { @@ -712,9 +721,10 @@ static void print_smi_cost(struct perf_stat_config *config,  static void generic_metric(struct perf_stat_config *config,  			   const char *metric_expr, -			   struct perf_evsel **metric_events, +			   struct evsel **metric_events,  			   char *name,  			   const char *metric_name, +			   const char *metric_unit,  			   double avg,  			   int cpu,  			   struct perf_stat_output_ctx *out, @@ -722,17 +732,16 @@ static void generic_metric(struct perf_stat_config *config,  {  	print_metric_t print_metric = out->print_metric;  	struct parse_ctx pctx; -	double ratio; +	double ratio, scale;  	int i;  	void *ctxp = out->ctx;  	char *n, *pn;  	expr__ctx_init(&pctx); -	expr__add_id(&pctx, name, avg);  	for (i = 0; metric_events[i]; i++) {  		struct saved_value *v;  		struct stats *stats; -		double scale; +		u64 metric_total = 0;  		if (!strcmp(metric_events[i]->name, "duration_time")) {  			stats = &walltime_nsecs_stats; @@ -744,6 +753,9 @@ static void generic_metric(struct perf_stat_config *config,  				break;  			stats = &v->stats;  			scale = 1.0; + +			if (v->metric_other) +				metric_total = v->metric_total;  		}  		n = strdup(metric_events[i]->name); @@ -757,21 +769,44 @@ static void generic_metric(struct perf_stat_config *config,  		pn = strchr(n, ' ');  		if (pn)  			*pn = 0; -		expr__add_id(&pctx, n, avg_stats(stats)*scale); + +		if (metric_total) +			expr__add_id(&pctx, n, metric_total); +		else +			expr__add_id(&pctx, n, avg_stats(stats)*scale);  	} + +	expr__add_id(&pctx, name, avg); +  	if (!metric_events[i]) {  		const char *p = metric_expr; -		if (expr__parse(&ratio, &pctx, &p) == 0) -			print_metric(config, ctxp, NULL, "%8.1f", -				metric_name ? -				metric_name : -				out->force_header ?  name : "", -				ratio); -		else +		if (expr__parse(&ratio, &pctx, &p) == 0) { +			char *unit; +			char metric_bf[64]; + +			if (metric_unit && metric_name) { +				if (perf_pmu__convert_scale(metric_unit, +					&unit, &scale) >= 0) { +					ratio *= scale; +				} + +				scnprintf(metric_bf, sizeof(metric_bf), +					  "%s  %s", unit, metric_name); +				print_metric(config, ctxp, NULL, "%8.1f", +					     metric_bf, ratio); +			} else { +				print_metric(config, ctxp, NULL, "%8.1f", +					metric_name ? +					metric_name : +					out->force_header ?  name : "", +					ratio); +			} +		} else {  			print_metric(config, ctxp, NULL, NULL,  				     out->force_header ?  				     (metric_name ? metric_name : name) : "", 0); +		}  	} else  		print_metric(config, ctxp, NULL, NULL, "", 0); @@ -780,7 +815,7 @@ static void generic_metric(struct perf_stat_config *config,  }  void perf_stat__print_shadow_stats(struct perf_stat_config *config, -				   struct perf_evsel *evsel, +				   struct evsel *evsel,  				   double avg, int cpu,  				   struct perf_stat_output_ctx *out,  				   struct rblist *metric_events, @@ -829,8 +864,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  		else  			print_metric(config, ctxp, NULL, NULL, "of all branches", 0);  	} else if ( -		evsel->attr.type == PERF_TYPE_HW_CACHE && -		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D | +		evsel->core.attr.type == PERF_TYPE_HW_CACHE && +		evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |  					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |  					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -839,8 +874,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  		else  			print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);  	} else if ( -		evsel->attr.type == PERF_TYPE_HW_CACHE && -		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I | +		evsel->core.attr.type == PERF_TYPE_HW_CACHE && +		evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |  					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |  					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -849,8 +884,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  		else  			print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);  	} else if ( -		evsel->attr.type == PERF_TYPE_HW_CACHE && -		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB | +		evsel->core.attr.type == PERF_TYPE_HW_CACHE && +		evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |  					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |  					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -859,8 +894,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  		else  			print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);  	} else if ( -		evsel->attr.type == PERF_TYPE_HW_CACHE && -		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB | +		evsel->core.attr.type == PERF_TYPE_HW_CACHE && +		evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |  					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |  					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -869,8 +904,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  		else  			print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);  	} else if ( -		evsel->attr.type == PERF_TYPE_HW_CACHE && -		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL | +		evsel->core.attr.type == PERF_TYPE_HW_CACHE && +		evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_LL |  					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |  					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -992,7 +1027,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  			print_metric(config, ctxp, NULL, NULL, name, 0);  	} else if (evsel->metric_expr) {  		generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, -				evsel->metric_name, avg, cpu, out, st); +				evsel->metric_name, NULL, avg, cpu, out, st);  	} else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {  		char unit = 'M';  		char unit_buf[10]; @@ -1021,7 +1056,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,  				out->new_line(config, ctxp);  			generic_metric(config, mexp->metric_expr, mexp->metric_events,  					evsel->name, mexp->metric_name, -					avg, cpu, out, st); +					mexp->metric_unit, avg, cpu, out, st);  		}  	}  	if (num == 0)  |