Skip to content

Commit fbe51fb

Browse files
Andi Kleenacmel
authored andcommitted
perf stat: Factor out callback for collecting event values
To be used in next patch to support automatic summing of alias events. v2: Move check for bad results to next patch v3: Remove trivial addition. v4: Use perf_evsel__cpus instead of evsel->cpus Signed-off-by: Andi Kleen <[email protected]> Acked-by: Jiri Olsa <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent ed7b339 commit fbe51fb

File tree

1 file changed

+80
-23
lines changed

1 file changed

+80
-23
lines changed

tools/perf/builtin-stat.c

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,11 +1182,46 @@ static void aggr_update_shadow(void)
11821182
}
11831183
}
11841184

1185+
static void collect_data(struct perf_evsel *counter,
1186+
void (*cb)(struct perf_evsel *counter, void *data,
1187+
bool first),
1188+
void *data)
1189+
{
1190+
cb(counter, data, true);
1191+
}
1192+
1193+
struct aggr_data {
1194+
u64 ena, run, val;
1195+
int id;
1196+
int nr;
1197+
int cpu;
1198+
};
1199+
1200+
static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
1201+
{
1202+
struct aggr_data *ad = data;
1203+
int cpu, s2;
1204+
1205+
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1206+
struct perf_counts_values *counts;
1207+
1208+
s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
1209+
if (s2 != ad->id)
1210+
continue;
1211+
if (first)
1212+
ad->nr++;
1213+
counts = perf_counts(counter->counts, cpu, 0);
1214+
ad->val += counts->val;
1215+
ad->ena += counts->ena;
1216+
ad->run += counts->run;
1217+
}
1218+
}
1219+
11851220
static void print_aggr(char *prefix)
11861221
{
11871222
FILE *output = stat_config.output;
11881223
struct perf_evsel *counter;
1189-
int cpu, s, s2, id, nr;
1224+
int s, id, nr;
11901225
double uval;
11911226
u64 ena, run, val;
11921227
bool first;
@@ -1201,23 +1236,20 @@ static void print_aggr(char *prefix)
12011236
* Without each counter has its own line.
12021237
*/
12031238
for (s = 0; s < aggr_map->nr; s++) {
1239+
struct aggr_data ad;
12041240
if (prefix && metric_only)
12051241
fprintf(output, "%s", prefix);
12061242

1207-
id = aggr_map->map[s];
1243+
ad.id = id = aggr_map->map[s];
12081244
first = true;
12091245
evlist__for_each_entry(evsel_list, counter) {
1210-
val = ena = run = 0;
1211-
nr = 0;
1212-
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1213-
s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
1214-
if (s2 != id)
1215-
continue;
1216-
val += perf_counts(counter->counts, cpu, 0)->val;
1217-
ena += perf_counts(counter->counts, cpu, 0)->ena;
1218-
run += perf_counts(counter->counts, cpu, 0)->run;
1219-
nr++;
1220-
}
1246+
ad.val = ad.ena = ad.run = 0;
1247+
ad.nr = 0;
1248+
collect_data(counter, aggr_cb, &ad);
1249+
nr = ad.nr;
1250+
ena = ad.ena;
1251+
run = ad.run;
1252+
val = ad.val;
12211253
if (first && metric_only) {
12221254
first = false;
12231255
aggr_printout(counter, id, nr);
@@ -1261,30 +1293,52 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
12611293
}
12621294
}
12631295

1296+
struct caggr_data {
1297+
double avg, avg_enabled, avg_running;
1298+
};
1299+
1300+
static void counter_aggr_cb(struct perf_evsel *counter, void *data,
1301+
bool first __maybe_unused)
1302+
{
1303+
struct caggr_data *cd = data;
1304+
struct perf_stat_evsel *ps = counter->priv;
1305+
1306+
cd->avg += avg_stats(&ps->res_stats[0]);
1307+
cd->avg_enabled += avg_stats(&ps->res_stats[1]);
1308+
cd->avg_running += avg_stats(&ps->res_stats[2]);
1309+
}
1310+
12641311
/*
12651312
* Print out the results of a single counter:
12661313
* aggregated counts in system-wide mode
12671314
*/
12681315
static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
12691316
{
12701317
FILE *output = stat_config.output;
1271-
struct perf_stat_evsel *ps = counter->priv;
1272-
double avg = avg_stats(&ps->res_stats[0]);
12731318
double uval;
1274-
double avg_enabled, avg_running;
1319+
struct caggr_data cd = { .avg = 0.0 };
12751320

1276-
avg_enabled = avg_stats(&ps->res_stats[1]);
1277-
avg_running = avg_stats(&ps->res_stats[2]);
1321+
collect_data(counter, counter_aggr_cb, &cd);
12781322

12791323
if (prefix && !metric_only)
12801324
fprintf(output, "%s", prefix);
12811325

1282-
uval = avg * counter->scale;
1283-
printout(-1, 0, counter, uval, prefix, avg_running, avg_enabled, avg);
1326+
uval = cd.avg * counter->scale;
1327+
printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, cd.avg);
12841328
if (!metric_only)
12851329
fprintf(output, "\n");
12861330
}
12871331

1332+
static void counter_cb(struct perf_evsel *counter, void *data,
1333+
bool first __maybe_unused)
1334+
{
1335+
struct aggr_data *ad = data;
1336+
1337+
ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
1338+
ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
1339+
ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
1340+
}
1341+
12881342
/*
12891343
* Print out the results of a single counter:
12901344
* does not use aggregated count in system-wide
@@ -1297,9 +1351,12 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
12971351
int cpu;
12981352

12991353
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1300-
val = perf_counts(counter->counts, cpu, 0)->val;
1301-
ena = perf_counts(counter->counts, cpu, 0)->ena;
1302-
run = perf_counts(counter->counts, cpu, 0)->run;
1354+
struct aggr_data ad = { .cpu = cpu };
1355+
1356+
collect_data(counter, counter_cb, &ad);
1357+
val = ad.val;
1358+
ena = ad.ena;
1359+
run = ad.run;
13031360

13041361
if (prefix)
13051362
fprintf(output, "%s", prefix);

0 commit comments

Comments
 (0)