|
@@ -140,6 +140,7 @@ static unsigned int unit_width = 4; /* strlen("unit") */
|
|
|
static bool forever = false;
|
|
|
static bool metric_only = false;
|
|
|
static bool force_metric_only = false;
|
|
|
+static bool no_merge = false;
|
|
|
static struct timespec ref_time;
|
|
|
static struct cpu_map *aggr_map;
|
|
|
static aggr_get_id_t aggr_get_id;
|
|
@@ -1182,12 +1183,37 @@ static void aggr_update_shadow(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void collect_data(struct perf_evsel *counter,
|
|
|
+static void collect_all_aliases(struct perf_evsel *counter,
|
|
|
void (*cb)(struct perf_evsel *counter, void *data,
|
|
|
bool first),
|
|
|
void *data)
|
|
|
{
|
|
|
+ struct perf_evsel *alias;
|
|
|
+
|
|
|
+ alias = list_prepare_entry(counter, &(evsel_list->entries), node);
|
|
|
+ list_for_each_entry_continue (alias, &evsel_list->entries, node) {
|
|
|
+ if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
|
|
|
+ alias->scale != counter->scale ||
|
|
|
+ alias->cgrp != counter->cgrp ||
|
|
|
+ strcmp(alias->unit, counter->unit) ||
|
|
|
+ nsec_counter(alias) != nsec_counter(counter))
|
|
|
+ break;
|
|
|
+ alias->merged_stat = true;
|
|
|
+ cb(alias, data, false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static bool collect_data(struct perf_evsel *counter,
|
|
|
+ void (*cb)(struct perf_evsel *counter, void *data,
|
|
|
+ bool first),
|
|
|
+ void *data)
|
|
|
+{
|
|
|
+ if (counter->merged_stat)
|
|
|
+ return false;
|
|
|
cb(counter, data, true);
|
|
|
+ if (!no_merge)
|
|
|
+ collect_all_aliases(counter, cb, data);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
struct aggr_data {
|
|
@@ -1245,7 +1271,8 @@ static void print_aggr(char *prefix)
|
|
|
evlist__for_each_entry(evsel_list, counter) {
|
|
|
ad.val = ad.ena = ad.run = 0;
|
|
|
ad.nr = 0;
|
|
|
- collect_data(counter, aggr_cb, &ad);
|
|
|
+ if (!collect_data(counter, aggr_cb, &ad))
|
|
|
+ continue;
|
|
|
nr = ad.nr;
|
|
|
ena = ad.ena;
|
|
|
run = ad.run;
|
|
@@ -1318,7 +1345,8 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
|
|
|
double uval;
|
|
|
struct caggr_data cd = { .avg = 0.0 };
|
|
|
|
|
|
- collect_data(counter, counter_aggr_cb, &cd);
|
|
|
+ if (!collect_data(counter, counter_aggr_cb, &cd))
|
|
|
+ return;
|
|
|
|
|
|
if (prefix && !metric_only)
|
|
|
fprintf(output, "%s", prefix);
|
|
@@ -1353,7 +1381,8 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
|
|
|
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
|
|
|
struct aggr_data ad = { .cpu = cpu };
|
|
|
|
|
|
- collect_data(counter, counter_cb, &ad);
|
|
|
+ if (!collect_data(counter, counter_cb, &ad))
|
|
|
+ return;
|
|
|
val = ad.val;
|
|
|
ena = ad.ena;
|
|
|
run = ad.run;
|
|
@@ -1701,6 +1730,7 @@ static const struct option stat_options[] = {
|
|
|
"list of cpus to monitor in system-wide"),
|
|
|
OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
|
|
|
"disable CPU count aggregation", AGGR_NONE),
|
|
|
+ OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
|
|
|
OPT_STRING('x', "field-separator", &csv_sep, "separator",
|
|
|
"print counts with custom separator"),
|
|
|
OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
|