summaryrefslogtreecommitdiff
path: root/tools/perf/util/stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/stat.c')
-rw-r--r--tools/perf/util/stat.c200
1 files changed, 31 insertions, 169 deletions
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 534d36d26fc3..976a06e63252 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -77,55 +77,6 @@ double rel_stddev_stats(double stddev, double avg)
return pct;
}
-bool __perf_stat_evsel__is(struct evsel *evsel, enum perf_stat_evsel_id id)
-{
- struct perf_stat_evsel *ps = evsel->stats;
-
- return ps->id == id;
-}
-
-#define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
-static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
- 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/),
- ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
- ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
- ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
- ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
- ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
- ID(TOPDOWN_RETIRING, topdown-retiring),
- ID(TOPDOWN_BAD_SPEC, topdown-bad-spec),
- ID(TOPDOWN_FE_BOUND, topdown-fe-bound),
- ID(TOPDOWN_BE_BOUND, topdown-be-bound),
- ID(TOPDOWN_HEAVY_OPS, topdown-heavy-ops),
- ID(TOPDOWN_BR_MISPREDICT, topdown-br-mispredict),
- ID(TOPDOWN_FETCH_LAT, topdown-fetch-lat),
- ID(TOPDOWN_MEM_BOUND, topdown-mem-bound),
- ID(SMI_NUM, msr/smi/),
- ID(APERF, msr/aperf/),
-};
-#undef ID
-
-static void perf_stat_evsel_id_init(struct evsel *evsel)
-{
- struct perf_stat_evsel *ps = evsel->stats;
- int i;
-
- /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
-
- for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
- if (!strcmp(evsel__name(evsel), id_str[i]) ||
- (strstr(evsel__name(evsel), id_str[i]) && evsel->pmu_name
- && strstr(evsel__name(evsel), evsel->pmu_name))) {
- ps->id = i;
- break;
- }
- }
-}
-
static void evsel__reset_aggr_stats(struct evsel *evsel)
{
struct perf_stat_evsel *ps = evsel->stats;
@@ -185,7 +136,6 @@ static int evsel__alloc_stat_priv(struct evsel *evsel, int nr_aggr)
return -ENOMEM;
}
- perf_stat_evsel_id_init(evsel);
evsel__reset_stat_priv(evsel);
return 0;
}
@@ -314,6 +264,28 @@ void evlist__copy_prev_raw_counts(struct evlist *evlist)
evsel__copy_prev_raw_counts(evsel);
}
+static void evsel__copy_res_stats(struct evsel *evsel)
+{
+ struct perf_stat_evsel *ps = evsel->stats;
+
+ /*
+ * For GLOBAL aggregation mode, it updates the counts for each run
+ * in the evsel->stats.res_stats. See perf_stat_process_counter().
+ */
+ *ps->aggr[0].counts.values = avg_stats(&ps->res_stats);
+}
+
+void evlist__copy_res_stats(struct perf_stat_config *config, struct evlist *evlist)
+{
+ struct evsel *evsel;
+
+ if (config->aggr_mode != AGGR_GLOBAL)
+ return;
+
+ evlist__for_each_entry(evlist, evsel)
+ evsel__copy_res_stats(evsel);
+}
+
static size_t pkg_id_hash(long __key, void *ctx __maybe_unused)
{
uint64_t *key = (uint64_t *) __key;
@@ -343,7 +315,7 @@ static int check_per_pkg(struct evsel *counter, struct perf_counts_values *vals,
if (!counter->per_pkg)
return 0;
- if (perf_cpu_map__empty(cpus))
+ if (perf_cpu_map__is_any_cpu_or_is_empty(cpus))
return 0;
if (!mask) {
@@ -554,7 +526,7 @@ static int evsel__merge_aggr_counters(struct evsel *evsel, struct evsel *alias)
struct perf_counts_values *aggr_counts_a = &ps_a->aggr[i].counts;
struct perf_counts_values *aggr_counts_b = &ps_b->aggr[i].counts;
- /* NB: don't increase aggr.nr for aliases */
+ ps_a->aggr[i].nr += ps_b->aggr[i].nr;
aggr_counts_a->val += aggr_counts_b->val;
aggr_counts_a->ena += aggr_counts_b->ena;
@@ -563,26 +535,6 @@ static int evsel__merge_aggr_counters(struct evsel *evsel, struct evsel *alias)
return 0;
}
-/* events should have the same name, scale, unit, cgroup but on different PMUs */
-static bool evsel__is_alias(struct evsel *evsel_a, struct evsel *evsel_b)
-{
- if (strcmp(evsel__name(evsel_a), evsel__name(evsel_b)))
- return false;
-
- if (evsel_a->scale != evsel_b->scale)
- return false;
-
- if (evsel_a->cgrp != evsel_b->cgrp)
- return false;
-
- if (strcmp(evsel_a->unit, evsel_b->unit))
- return false;
-
- if (evsel__is_clock(evsel_a) != evsel__is_clock(evsel_b))
- return false;
-
- return !!strcmp(evsel_a->pmu_name, evsel_b->pmu_name);
-}
static void evsel__merge_aliases(struct evsel *evsel)
{
@@ -591,10 +543,9 @@ static void evsel__merge_aliases(struct evsel *evsel)
alias = list_prepare_entry(evsel, &(evlist->core.entries), core.node);
list_for_each_entry_continue(alias, &evlist->core.entries, core.node) {
- /* Merge the same events on different PMUs. */
- if (evsel__is_alias(evsel, alias)) {
+ if (alias->first_wildcard_match == evsel) {
+ /* Merge the same events on different PMUs. */
evsel__merge_aggr_counters(evsel, alias);
- alias->merged_stat = true;
}
}
}
@@ -607,11 +558,7 @@ static bool evsel__should_merge_hybrid(const struct evsel *evsel,
static void evsel__merge_stats(struct evsel *evsel, struct perf_stat_config *config)
{
- /* this evsel is already merged */
- if (evsel->merged_stat)
- return;
-
- if (evsel->auto_merge_stats || evsel__should_merge_hybrid(evsel, config))
+ if (!evsel->pmu || !evsel->pmu->is_core || evsel__should_merge_hybrid(evsel, config))
evsel__merge_aliases(evsel);
}
@@ -620,7 +567,7 @@ void perf_stat_merge_counters(struct perf_stat_config *config, struct evlist *ev
{
struct evsel *evsel;
- if (config->no_merge)
+ if (config->aggr_mode == AGGR_NONE)
return;
evlist__for_each_entry(evlist, evsel)
@@ -698,31 +645,8 @@ void perf_stat_process_percore(struct perf_stat_config *config, struct evlist *e
evsel__process_percore(evsel);
}
-static void evsel__update_shadow_stats(struct evsel *evsel)
-{
- struct perf_stat_evsel *ps = evsel->stats;
- int i;
-
- if (ps->aggr == NULL)
- return;
-
- for (i = 0; i < ps->nr_aggr; i++) {
- struct perf_counts_values *aggr_counts = &ps->aggr[i].counts;
-
- perf_stat__update_shadow_stats(evsel, aggr_counts->val, i, &rt_stat);
- }
-}
-
-void perf_stat_process_shadow_stats(struct perf_stat_config *config __maybe_unused,
- struct evlist *evlist)
-{
- struct evsel *evsel;
-
- evlist__for_each_entry(evlist, evsel)
- evsel__update_shadow_stats(evsel);
-}
-
-int perf_event__process_stat_event(struct perf_session *session,
+int perf_event__process_stat_event(const struct perf_tool *tool __maybe_unused,
+ struct perf_session *session,
union perf_event *event)
{
struct perf_counts_values count, *ptr;
@@ -781,7 +705,7 @@ size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
{
- struct perf_stat_config sc;
+ struct perf_stat_config sc = {};
size_t ret;
perf_event__read_stat_config(&sc, &event->stat_config);
@@ -793,65 +717,3 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
return ret;
}
-
-int create_perf_stat_counter(struct evsel *evsel,
- struct perf_stat_config *config,
- struct target *target,
- int cpu_map_idx)
-{
- struct perf_event_attr *attr = &evsel->core.attr;
- struct evsel *leader = evsel__leader(evsel);
-
- attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
- PERF_FORMAT_TOTAL_TIME_RUNNING;
-
- /*
- * The event is part of non trivial group, let's enable
- * the group read (for leader) and ID retrieval for all
- * members.
- */
- if (leader->core.nr_members > 1)
- attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
-
- attr->inherit = !config->no_inherit && list_empty(&evsel->bpf_counter_list);
-
- /*
- * Some events get initialized with sample_(period/type) set,
- * like tracepoints. Clear it up for counting.
- */
- attr->sample_period = 0;
-
- if (config->identifier)
- attr->sample_type = PERF_SAMPLE_IDENTIFIER;
-
- if (config->all_user) {
- attr->exclude_kernel = 1;
- attr->exclude_user = 0;
- }
-
- if (config->all_kernel) {
- attr->exclude_kernel = 0;
- attr->exclude_user = 1;
- }
-
- /*
- * Disabling all counters initially, they will be enabled
- * either manually by us or by kernel via enable_on_exec
- * set later.
- */
- if (evsel__is_group_leader(evsel)) {
- attr->disabled = 1;
-
- /*
- * In case of initial_delay we enable tracee
- * events manually.
- */
- if (target__none(target) && !config->initial_delay)
- attr->enable_on_exec = 1;
- }
-
- if (target__has_cpu(target) && !target__has_per_thread(target))
- return evsel__open_per_cpu(evsel, evsel__cpus(evsel), cpu_map_idx);
-
- return evsel__open_per_thread(evsel, evsel->core.threads);
-}