/* Check that leader matches cpus with each member. */ if (leader == evsel) continue; if (perf_cpu_map__equal(leader->core.cpus, evsel->core.cpus)) continue;
/* If there's mismatch disable the group and warn user. */ if (warned_leader != leader) { char buf[200];
pr_warning("WARNING: grouped events cpus do not match.\n" "Events with CPUs not matching the leader will " "be removed from the group.\n");
evsel__group_desc(leader, buf, sizeof(buf));
pr_warning(" %s\n", buf);
warned_leader = leader;
} if (verbose > 0) { char buf[200];
if (evlist__ctlfd_process(evlist, &cmd) > 0) { switch (cmd) { case EVLIST_CTL_CMD_ENABLE:
fallthrough; case EVLIST_CTL_CMD_DISABLE: if (interval)
process_interval(); break; case EVLIST_CTL_CMD_SNAPSHOT: case EVLIST_CTL_CMD_ACK: case EVLIST_CTL_CMD_UNSUPPORTED: case EVLIST_CTL_CMD_EVLIST: case EVLIST_CTL_CMD_STOP: case EVLIST_CTL_CMD_PING: default: break;
}
}
}
staticvoid compute_tts(struct timespec *time_start, struct timespec *time_stop, int *time_to_sleep)
{ int tts = *time_to_sleep; struct timespec time_diff;
staticint dispatch_events(bool forks, int timeout, int interval, int *times)
{ int child_exited = 0, status = 0; int time_to_sleep, sleep_time; struct timespec time_start, time_stop;
if (errno == EOPNOTSUPP) { if (verbose > 0) {
ui__warning("%s event is not supported by the kernel.\n",
evsel__name(counter));
}
counter->supported = false;
counter->errored = true;
if (evlist__apply_filters(evsel_list, &counter, &target)) {
pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
counter->filter, evsel__name(counter), errno,
str_error_r(errno, msg, sizeof(msg))); return -1;
}
if (STAT_RECORD) { int fd = perf_data__fd(&perf_stat.data);
/* *Weneedtokeepevsel_listalive,becauseit'sprocessed *latertheevsel_listwillbeclosedafter.
*/ if (!STAT_RECORD)
evlist__close(evsel_list);
return WEXITSTATUS(status);
err_out: if (forks)
evlist__cancel_workload(evsel_list);
affinity__cleanup(affinity); return err;
}
/* *Returns-1forfatalerrorswhichsignifiestonotcontinue *wheninrepeatmode. * *Returns<-1errorcodeswhenstatrecordisused.These *resultinthestatinformationbeingdisplayed,butwriting *tothefilefailsandisnonfatal.
*/ staticint run_perf_stat(int argc, constchar **argv, int run_idx)
{ int ret;
if (pre_cmd) {
ret = system(pre_cmd); if (ret) return ret;
}
if (sync_run)
sync();
ret = __run_perf_stat(argc, argv, run_idx); if (ret) return ret;
if (post_cmd) {
ret = system(post_cmd); if (ret) return ret;
}
return ret;
}
staticvoid print_counters(struct timespec *ts, int argc, constchar **argv)
{ /* Do not print anything if we record to the pipe. */ if (STAT_RECORD && perf_stat.data.is_pipe) return; if (quiet) return;
staticint parse_stat_cgroups(conststruct option *opt, constchar *str, int unset)
{ if (stat_config.cgroup_list) {
pr_err("--cgroup and --for-each-cgroup cannot be used together\n"); return -1;
}
/* *IfthemapcontainsnoCPU,considerthecurrentCPUto *bethefirstonlineCPUinthecachedomainelseusethe *firstonlineCPUofthecachedomainastheID.
*/
id = perf_cpu_map__min(cpu_map).cpu; if (id == -1)
id = cpu.cpu;
/* Free the perf_cpu_map used to find the cache ID */
perf_cpu_map__put(cpu_map);
static aggr_cpu_id_get_t aggr_mode__get_aggr(enum aggr_mode aggr_mode)
{ switch (aggr_mode) { case AGGR_SOCKET: return aggr_cpu_id__socket; case AGGR_DIE: return aggr_cpu_id__die; case AGGR_CLUSTER: return aggr_cpu_id__cluster; case AGGR_CACHE: return aggr_cpu_id__cache; case AGGR_CORE: return aggr_cpu_id__core; case AGGR_NODE: return aggr_cpu_id__node; case AGGR_NONE: return aggr_cpu_id__cpu; case AGGR_GLOBAL: return aggr_cpu_id__global; case AGGR_THREAD: case AGGR_UNSET: case AGGR_MAX: default: return NULL;
}
}
static aggr_get_id_t aggr_mode__get_id(enum aggr_mode aggr_mode)
{ switch (aggr_mode) { case AGGR_SOCKET: return perf_stat__get_socket_cached; case AGGR_DIE: return perf_stat__get_die_cached; case AGGR_CLUSTER: return perf_stat__get_cluster_cached; case AGGR_CACHE: return perf_stat__get_cache_id_cached; case AGGR_CORE: return perf_stat__get_core_cached; case AGGR_NODE: return perf_stat__get_node_cached; case AGGR_NONE: return perf_stat__get_cpu_cached; case AGGR_GLOBAL: return perf_stat__get_global_cached; case AGGR_THREAD: case AGGR_UNSET: case AGGR_MAX: default: return NULL;
}
}
staticint perf_stat_init_aggr_mode(void)
{ int nr;
aggr_cpu_id_get_t get_id = aggr_mode__get_aggr(stat_config.aggr_mode);
static aggr_cpu_id_get_t aggr_mode__get_aggr_file(enum aggr_mode aggr_mode)
{ switch (aggr_mode) { case AGGR_SOCKET: return perf_env__get_socket_aggr_by_cpu; case AGGR_DIE: return perf_env__get_die_aggr_by_cpu; case AGGR_CLUSTER: return perf_env__get_cluster_aggr_by_cpu; case AGGR_CACHE: return perf_env__get_cache_aggr_by_cpu; case AGGR_CORE: return perf_env__get_core_aggr_by_cpu; case AGGR_NODE: return perf_env__get_node_aggr_by_cpu; case AGGR_GLOBAL: return perf_env__get_global_aggr_by_cpu; case AGGR_NONE: return perf_env__get_cpu_aggr_by_cpu; case AGGR_THREAD: case AGGR_UNSET: case AGGR_MAX: default: return NULL;
}
}
static aggr_get_id_t aggr_mode__get_id_file(enum aggr_mode aggr_mode)
{ switch (aggr_mode) { case AGGR_SOCKET: return perf_stat__get_socket_file; case AGGR_DIE: return perf_stat__get_die_file; case AGGR_CLUSTER: return perf_stat__get_cluster_file; case AGGR_CACHE: return perf_stat__get_cache_file; case AGGR_CORE: return perf_stat__get_core_file; case AGGR_NODE: return perf_stat__get_node_file; case AGGR_GLOBAL: return perf_stat__get_global_file; case AGGR_NONE: return perf_stat__get_cpu_file; case AGGR_THREAD: case AGGR_UNSET: case AGGR_MAX: default: return NULL;
}
}
if (!force_metric_only)
stat_config.metric_only = true;
if (!max_level) {
pr_err("Topdown requested but the topdown metric groups aren't present.\n" "(See perf list the metric groups have names like TopdownL1)\n");
ret = -1; goto out;
} if (stat_config.topdown_level > max_level) {
pr_err("Invalid top-down metrics level. The max level is %u.\n", max_level);
ret = -1; goto out;
} elseif (!stat_config.topdown_level) {
stat_config.topdown_level = 1;
} if (!stat_config.interval && !stat_config.metric_only) {
fprintf(stat_config.output, "Topdown accuracy may decrease when measuring long periods.\n" "Please print the result regularly, e.g. -I1000\n");
}
str[8] = stat_config.topdown_level + '0'; if (metricgroup__parse_groups(evlist,
pmu, str, /*metric_no_group=*/false, /*metric_no_merge=*/false, /*metric_no_threshold=*/true,
stat_config.user_requested_cpu_list,
stat_config.system_wide,
stat_config.hardware_aware_grouping) < 0) {
ret = -1; goto out;
}
}
if (!stat_config.topdown_level)
stat_config.topdown_level = 1;
if (!evlist->core.nr_entries && !evsel_list->core.nr_entries) { /* No events so add defaults. */ if (target__has_cpu(&target))
ret = parse_events(evlist, "cpu-clock", &err); else
ret = parse_events(evlist, "task-clock", &err); if (ret) goto out;
ret = parse_events(evlist, "context-switches," "cpu-migrations," "page-faults," "instructions," "cycles," "stalled-cycles-frontend," "stalled-cycles-backend," "branches," "branch-misses",
&err); if (ret) goto out;
int cmd_stat(int argc, constchar **argv)
{ struct opt_aggr_mode opt_mode = {}; struct option stat_options[] = {
OPT_BOOLEAN('T', "transaction", &transaction_run, "hardware transaction statistics"),
OPT_CALLBACK('e', "event", &parse_events_option_args, "event", "event selector. use 'perf list' to list available events",
parse_events_option),
OPT_CALLBACK(0, "filter", &evsel_list, "filter", "event filter", parse_filter),
OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit, "child tasks do not inherit counters"),
OPT_STRING('p', "pid", &target.pid, "pid", "stat events on existing process id"),
OPT_STRING('t', "tid", &target.tid, "tid", "stat events on existing thread id"), #ifdef HAVE_BPF_SKEL
OPT_STRING('b', "bpf-prog", &target.bpf_str, "bpf-prog-id", "stat events on existing bpf program id"),
OPT_BOOLEAN(0, "bpf-counters", &target.use_bpf, "use bpf program to count events"),
OPT_STRING(0, "bpf-attr-map", &target.attr_map, "attr-map-path", "path to perf_event_attr map"), #endif
OPT_BOOLEAN('a', "all-cpus", &target.system_wide, "system-wide collection from all CPUs"),
OPT_BOOLEAN(0, "scale", &stat_config.scale, "Use --no-scale to disable counter scaling for multiplexing"),
OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
OPT_INTEGER('r', "repeat", &stat_config.run_count, "repeat command and print average + stddev (max: 100, forever: 0)"),
OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table, "display details about each run (only with -r option)"),
OPT_BOOLEAN('n', "null", &stat_config.null_run, "null run - dont start any counters"),
OPT_INCR('d', "detailed", &detailed_run, "detailed run - start a lot of events"),
OPT_BOOLEAN('S', "sync", &sync_run, "call sync() before starting a run"),
OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, "print large numbers with thousands\' separators",
stat__set_big_num),
OPT_STRING('C', "cpu", &target.cpu_list, "cpu", "list of cpus to monitor in system-wide"),
OPT_BOOLEAN('A', "no-aggr", &opt_mode.no_aggr, "disable aggregation across CPUs or PMUs"),
OPT_BOOLEAN(0, "no-merge", &opt_mode.no_aggr, "disable aggregation the same as -A or -no-aggr"),
OPT_BOOLEAN(0, "hybrid-merge", &stat_config.hybrid_merge, "Merge identical named hybrid events"),
OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator", "print counts with custom separator"),
OPT_BOOLEAN('j', "json-output", &stat_config.json_output, "print counts in JSON format"),
OPT_CALLBACK('G', "cgroup", &evsel_list, "name", "monitor event in cgroup name only", parse_stat_cgroups),
OPT_STRING(0, "for-each-cgroup", &stat_config.cgroup_list, "name", "expand events for each cgroup"),
OPT_STRING('o', "output", &output_name, "file", "output file name"),
OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
OPT_INTEGER(0, "log-fd", &output_fd, "log output to fd, instead of stderr"),
OPT_STRING(0, "pre", &pre_cmd, "command", "command to run prior to the measured command"),
OPT_STRING(0, "post", &post_cmd, "command", "command to run after to the measured command"),
OPT_UINTEGER('I', "interval-print", &stat_config.interval, "print counts at regular interval in ms " "(overhead is possible for values <= 100ms)"),
OPT_INTEGER(0, "interval-count", &stat_config.times, "print counts for fixed number of times"),
OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear, "clear screen in between new interval"),
OPT_UINTEGER(0, "timeout", &stat_config.timeout, "stop workload and print counts after a timeout period in ms (>= 10ms)"),
OPT_BOOLEAN(0, "per-socket", &opt_mode.socket, "aggregate counts per processor socket"),
OPT_BOOLEAN(0, "per-die", &opt_mode.die, "aggregate counts per processor die"),
OPT_BOOLEAN(0, "per-cluster", &opt_mode.cluster, "aggregate counts per processor cluster"),
OPT_CALLBACK_OPTARG(0, "per-cache", &opt_mode, &stat_config.aggr_level, "cache level", "aggregate count at this cache level (Default: LLC)",
parse_cache_level),
OPT_BOOLEAN(0, "per-core", &opt_mode.core, "aggregate counts per physical processor core"),
OPT_BOOLEAN(0, "per-thread", &opt_mode.thread, "aggregate counts per thread"),
OPT_BOOLEAN(0, "per-node", &opt_mode.node, "aggregate counts per numa node"),
OPT_INTEGER('D', "delay", &target.initial_delay, "ms to wait before starting measurement after program start (-1: start with events disabled)"),
OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL, "Only print computed metrics. No raw values", enable_metric_only),
OPT_BOOLEAN(0, "metric-no-group", &stat_config.metric_no_group, "don't group metric events, impacts multiplexing"),
OPT_BOOLEAN(0, "metric-no-merge", &stat_config.metric_no_merge, "don't try to share events between metrics in a group"),
OPT_BOOLEAN(0, "metric-no-threshold", &stat_config.metric_no_threshold, "disable adding events for the metric threshold calculation"),
OPT_BOOLEAN(0, "topdown", &topdown_run, "measure top-down statistics"), #ifdef HAVE_ARCH_X86_64_SUPPORT
OPT_BOOLEAN(0, "record-tpebs", &tpebs_recording, "enable recording for tpebs when retire_latency required"),
OPT_CALLBACK(0, "tpebs-mode", &tpebs_mode, "tpebs-mode", "Mode of TPEBS recording: mean, min or max",
parse_tpebs_mode), #endif
OPT_UINTEGER(0, "td-level", &stat_config.topdown_level, "Set the metrics level for the top-down statistics (0: max level)"),
OPT_BOOLEAN(0, "smi-cost", &smi_cost, "measure SMI cost"),
OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list", "monitor specified metrics or metric groups (separated by ,)",
append_metric_groups),
OPT_BOOLEAN_FLAG(0, "all-kernel", &stat_config.all_kernel, "Configure all used events to run in kernel space.",
PARSE_OPT_EXCLUSIVE),
OPT_BOOLEAN_FLAG(0, "all-user", &stat_config.all_user, "Configure all used events to run in user space.",
PARSE_OPT_EXCLUSIVE),
OPT_BOOLEAN(0, "percore-show-thread", &stat_config.percore_show_thread, "Use with 'percore' event qualifier to show the event " "counts of one hardware thread by sum up total hardware " "threads of same physical core"),
OPT_BOOLEAN(0, "summary", &stat_config.summary, "print summary for interval mode"),
OPT_BOOLEAN(0, "no-csv-summary", &stat_config.no_csv_summary, "don't print 'summary' for CSV summary output"),
OPT_BOOLEAN(0, "quiet", &quiet, "don't print any output, messages or warnings (useful with record)"),
OPT_CALLBACK(0, "cputype", &evsel_list, "hybrid cpu type", "Only enable events on applying cpu with this type " "for hybrid platform (e.g. core or atom)",
parse_cputype), #ifdef HAVE_LIBPFM
OPT_CALLBACK(0, "pfm-events", &evsel_list, "event", "libpfm4 event selector. use 'perf list' to list available events",
parse_libpfm_events_option), #endif
OPT_CALLBACK(0, "control", &stat_config, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]", "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n" "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n" "\t\t\t Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.",
parse_control_option),
OPT_CALLBACK_OPTARG(0, "iostat", &evsel_list, &stat_config, "default", "measure I/O performance metrics provided by arch/platform",
iostat_parse),
OPT_END()
}; constchar * const stat_usage[] = { "perf stat [<options>] [<command>]",
NULL
}; int status = -EINVAL, run_idx, err; constchar *mode;
FILE *output = stderr; unsignedint interval, timeout; constchar * const stat_subcommands[] = { "record", "report" }; char errbuf[BUFSIZ];
setlocale(LC_ALL, "");
evsel_list = evlist__new(); if (evsel_list == NULL) return -ENOMEM;
if (output_name && output_fd) {
fprintf(stderr, "cannot use both --output and --log-fd\n");
parse_options_usage(stat_usage, stat_options, "o", 1);
parse_options_usage(NULL, stat_options, "log-fd", 0); goto out;
}
if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
fprintf(stderr, "--metric-only is not supported with --per-thread\n"); goto out;
}
if (stat_config.metric_only && stat_config.run_count > 1) {
fprintf(stderr, "--metric-only is not supported with -r\n"); goto out;
}
if (stat_config.run_count < 0) {
pr_err("Run count must be a positive number\n");
parse_options_usage(stat_usage, stat_options, "r", 1); goto out;
} elseif (stat_config.run_count == 0) {
forever = true;
stat_config.run_count = 1;
}
if (stat_config.walltime_run_table) {
stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0])); if (!stat_config.walltime_run) {
pr_err("failed to setup -r option"); goto out;
}
}
if ((stat_config.aggr_mode == AGGR_THREAD) &&
!target__has_task(&target)) { if (!target.system_wide || target.cpu_list) {
fprintf(stderr, "The --per-thread option is only " "available when monitoring via -p -t -a " "options or only --per-thread.\n");
parse_options_usage(NULL, stat_options, "p", 1);
parse_options_usage(NULL, stat_options, "t", 1); goto out;
}
}
/* *no_aggr,cgroupareforsystem-wideonly *--per-threadisaggregatedperthread,wedontmixitwithcpumode
*/ if (((stat_config.aggr_mode != AGGR_GLOBAL &&
stat_config.aggr_mode != AGGR_THREAD) ||
(nr_cgroups || stat_config.cgroup_list)) &&
!target__has_cpu(&target)) {
fprintf(stderr, "both cgroup and no-aggregation " "modes only available in system-wide mode\n");
if (stat_config.aggr_mode == AGGR_NODE)
cpu__setup_cpunode_map();
if (stat_config.times && interval)
interval_count = true; elseif (stat_config.times && !interval) {
pr_err("interval-count option should be used together with " "interval-print.\n");
parse_options_usage(stat_usage, stat_options, "interval-count", 0);
parse_options_usage(stat_usage, stat_options, "I", 1); goto out;
}
if (timeout && timeout < 100) { if (timeout < 10) {
pr_err("timeout must be >= 10ms.\n");
parse_options_usage(stat_usage, stat_options, "timeout", 0); goto out;
} else
pr_warning("timeout < 100ms. " "The overhead percentage could be high in some cases. " "Please proceed with caution.\n");
} if (timeout && interval) {
pr_err("timeout option is not supported with interval-print.\n");
parse_options_usage(stat_usage, stat_options, "timeout", 0);
parse_options_usage(stat_usage, stat_options, "I", 1); goto out;
}
if (perf_stat_init_aggr_mode()) goto out;
if (evlist__alloc_stats(&stat_config, evsel_list, interval)) goto out;
if (!forever && status != -1 && (!interval || stat_config.summary)) { if (stat_config.run_count > 1)
evlist__copy_res_stats(&stat_config, evsel_list);
print_counters(NULL, argc, argv);
}
evlist__finalize_ctlfd(evsel_list);
if (STAT_RECORD) { /* *Wesynthesizethekernelmmaprecordjustsothatoldertools *don'temitwarningsaboutnotbeingabletoresolvesymbols *dueto/proc/sys/kernel/kptr_restrictsettingsandinsteadprovide *asanermessageaboutnosamplesbeingintheperf.datafile. * *Thisalsoservestosuppressawarningaboutf_header.data.size==0 *inheader.catthemoment'perfstatrecord'getsintroduced,which *isnotreallyneededoncewestartaddingthestatspecificPERF_RECORD_ *records,buttheneedtosuppressthekptr_restrictmessagesinolder *toolsremain-acme
*/ int fd = perf_data__fd(&perf_stat.data);
err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
process_synthesized_event,
&perf_stat.session->machines.host); if (err) {
pr_warning("Couldn't synthesize the kernel mmap record, harmless, " "older tools may produce warnings about this file\n.");
}
if (!interval) { if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
pr_err("failed to write stat round event\n");
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.54Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-11)
¤
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.