staticint evsel_context(conststruct evsel *evsel)
{ int ctx = 0;
if (evsel->core.attr.exclude_kernel)
ctx |= CTX_BIT_KERNEL; if (evsel->core.attr.exclude_user)
ctx |= CTX_BIT_USER; if (evsel->core.attr.exclude_hv)
ctx |= CTX_BIT_HV; if (evsel->core.attr.exclude_host)
ctx |= CTX_BIT_HOST; if (evsel->core.attr.exclude_idle)
ctx |= CTX_BIT_IDLE;
/* Ignore the evsel that is being searched from. */ if (evsel == cur) continue;
/* Ignore evsels that are part of different groups. */ if (evsel->core.leader->nr_members > 1 &&
evsel->core.leader != cur->core.leader) continue; /* Ignore evsels with mismatched modifiers. */ if (evsel_ctx != evsel_context(cur)) continue; /* Ignore if not the cgroup we're looking for. */ if (evsel->cgrp != cur->cgrp) continue; /* Ignore if not the stat we're looking for. */ if (type != evsel__stat_type(cur)) continue;
/* * Except the SW CLOCK events, * ignore if not the PMU we're looking for.
*/ if ((type != STAT_NSECS) && (evsel_pmu != evsel__find_pmu(cur))) continue;
for (i = 0; metric_events[i]; i++) { char *n; double val; int source_count = 0;
if (evsel__is_tool(metric_events[i])) { struct stats *stats; double scale;
switch (evsel__tool_event(metric_events[i])) { case TOOL_PMU__EVENT_DURATION_TIME:
stats = &walltime_nsecs_stats;
scale = 1e-9; break; case TOOL_PMU__EVENT_USER_TIME:
stats = &ru_stats.ru_utime_usec_stat;
scale = 1e-6; break; case TOOL_PMU__EVENT_SYSTEM_TIME:
stats = &ru_stats.ru_stime_usec_stat;
scale = 1e-6; break; case TOOL_PMU__EVENT_NONE:
pr_err("Invalid tool event 'none'");
abort(); case TOOL_PMU__EVENT_MAX:
pr_err("Invalid tool event 'max'");
abort(); case TOOL_PMU__EVENT_HAS_PMEM: case TOOL_PMU__EVENT_NUM_CORES: case TOOL_PMU__EVENT_NUM_CPUS: case TOOL_PMU__EVENT_NUM_CPUS_ONLINE: case TOOL_PMU__EVENT_NUM_DIES: case TOOL_PMU__EVENT_NUM_PACKAGES: case TOOL_PMU__EVENT_SLOTS: case TOOL_PMU__EVENT_SMT_ON: case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: default:
pr_err("Unexpected tool event '%s'", evsel__name(metric_events[i]));
abort();
}
val = avg_stats(stats) * scale;
source_count = 1;
} else { struct perf_stat_evsel *ps = metric_events[i]->stats; struct perf_stat_aggr *aggr;
/* * If there are multiple uncore PMUs and we're not * reading the leader's stats, determine the stats for * the appropriate uncore PMU.
*/ if (evsel && evsel->metric_leader &&
evsel->pmu != evsel->metric_leader->pmu &&
mexp->metric_events[i]->pmu == evsel->metric_leader->pmu) { struct evsel *pos;
evlist__for_each_entry(evsel->evlist, pos) { if (pos->pmu != evsel->pmu) continue; if (pos->metric_leader != mexp->metric_events[i]) continue;
ps = pos->stats;
source_count = 1; break;
}
}
aggr = &ps->aggr[aggr_idx]; if (!aggr) break;
if (!metric_events[i]->supported) { /* * Not supported events will have a count of 0, * which can be confusing in a * metric. Explicitly set the value to NAN. Not * counted events (enable time of 0) are read as * 0.
*/
val = NAN;
source_count = 0;
} else {
val = aggr->counts.val; if (!source_count)
source_count = evsel__source_count(metric_events[i]);
}
}
n = strdup(evsel__metric_id(metric_events[i])); if (!n) return -ENOMEM;
expr__add_id_val_source_count(pctx, n, val, source_count);
}
for (int j = 0; metric_refs && metric_refs[j].metric_name; j++) { int ret = expr__add_ref(pctx, &metric_refs[j]);
/* * A metricgroup may have several metric events, * e.g.,TopdownL1 on e-core of ADL. * The name has been output by the first metric * event. Only align with other metics from * different metric events.
*/ if (last_name && !strcmp(last_name, name)) { if (!need_full_name || last_pmu != evsel->pmu) {
out->print_metricgroup_header(config, ctxp, NULL); return;
}
}
/** * perf_stat__print_shadow_stats_metricgroup - Print out metrics associated with the evsel * For the non-default, all metrics associated * with the evsel are printed. * For the default mode, only the metrics from * the same metricgroup and the name of the * metricgroup are printed. To print the metrics * from the next metricgroup (if available), * invoke the function with correspoinding * metric_expr.
*/ void *perf_stat__print_shadow_stats_metricgroup(struct perf_stat_config *config, struct evsel *evsel, int aggr_idx, int *num, void *from, struct perf_stat_output_ctx *out)
{ struct metric_event *me; struct metric_expr *mexp = from; void *ctxp = out->ctx; bool header_printed = false; constchar *name = NULL; struct rblist *metric_events = &evsel->evlist->metric_events;
me = metricgroup__lookup(metric_events, evsel, false); if (me == NULL) return NULL;
if (!mexp)
mexp = list_first_entry(&me->head, typeof(*mexp), nd);
list_for_each_entry_from(mexp, &me->head, nd) { /* Print the display name of the Default metricgroup */ if (!config->metric_only && me->is_default) { if (!name)
name = mexp->default_metricgroup_name; /* * Two or more metricgroup may share the same metric * event, e.g., TopdownL1 and TopdownL2 on SPR. * Return and print the prefix, e.g., noise, running * for the next metricgroup.
*/ if (strcmp(name, mexp->default_metricgroup_name)) return (void *)mexp; /* Only print the name of the metricgroup once */ if (!header_printed) {
header_printed = true;
perf_stat__print_metricgroup_header(config, evsel, ctxp,
name, out);
}
}
/** * perf_stat__skip_metric_event - Skip the evsel in the Default metricgroup, * if it's not running or not the metric event.
*/ bool perf_stat__skip_metric_event(struct evsel *evsel,
u64 ena, u64 run)
{ if (!evsel->default_metricgroup) returnfalse;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.