Commit 0dddd91a authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

perf stat: Make options local



Reduce the scope of stat_options to cmd_stat, and pass as an argument
to __cmd_record. This is done to make more localized changes to the
options in later patches. A side-effect of the change is to reduce the
size of a stripped PIE perf binary by 5952 bytes. The savings come
mainly in the dynamic relocation section.

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Cc: Stephane Eranian <eranian@google.com>
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240605063828.195700-1-irogers@google.com
parent d2307fd4
Loading
Loading
Loading
Loading
+145 −146
Original line number Diff line number Diff line
@@ -1140,150 +1140,6 @@ static int parse_cache_level(const struct option *opt,
	return 0;
}

static 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_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
		    "disable aggregation across CPUs or PMUs", AGGR_NONE),
	OPT_SET_UINT(0, "no-merge", &stat_config.aggr_mode,
		    "disable aggregation the same as -A or -no-aggr", AGGR_NONE),
	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_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
		     "aggregate counts per processor socket", AGGR_SOCKET),
	OPT_SET_UINT(0, "per-die", &stat_config.aggr_mode,
		     "aggregate counts per processor die", AGGR_DIE),
	OPT_SET_UINT(0, "per-cluster", &stat_config.aggr_mode,
		     "aggregate counts per processor cluster", AGGR_CLUSTER),
	OPT_CALLBACK_OPTARG(0, "per-cache", &stat_config.aggr_mode, &stat_config.aggr_level,
			    "cache level", "aggregate count at this cache level (Default: LLC)",
			    parse_cache_level),
	OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
		     "aggregate counts per physical processor core", AGGR_CORE),
	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
		     "aggregate counts per thread", AGGR_THREAD),
	OPT_SET_UINT(0, "per-node", &stat_config.aggr_mode,
		     "aggregate counts per numa node", AGGR_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"),
	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()
};

/**
 * Calculate the cache instance ID from the map in
 * /sys/devices/system/cpu/cpuX/cache/indexY/shared_cpu_list
@@ -2245,7 +2101,7 @@ static void init_features(struct perf_session *session)
	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
}

static int __cmd_record(int argc, const char **argv)
static int __cmd_record(const struct option stat_options[], int argc, const char **argv)
{
	struct perf_session *session;
	struct perf_data *data = &perf_stat.data;
@@ -2494,6 +2350,149 @@ static void setup_system_wide(int forks)

int cmd_stat(int argc, const char **argv)
{
	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_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
			"disable aggregation across CPUs or PMUs", AGGR_NONE),
		OPT_SET_UINT(0, "no-merge", &stat_config.aggr_mode,
			"disable aggregation the same as -A or -no-aggr", AGGR_NONE),
		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_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
			"aggregate counts per processor socket", AGGR_SOCKET),
		OPT_SET_UINT(0, "per-die", &stat_config.aggr_mode,
			"aggregate counts per processor die", AGGR_DIE),
		OPT_SET_UINT(0, "per-cluster", &stat_config.aggr_mode,
			"aggregate counts per processor cluster", AGGR_CLUSTER),
		OPT_CALLBACK_OPTARG(0, "per-cache", &stat_config.aggr_mode, &stat_config.aggr_level,
				"cache level", "aggregate count at this cache level (Default: LLC)",
				parse_cache_level),
		OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
			"aggregate counts per physical processor core", AGGR_CORE),
		OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
			"aggregate counts per thread", AGGR_THREAD),
		OPT_SET_UINT(0, "per-node", &stat_config.aggr_mode,
			"aggregate counts per numa node", AGGR_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"),
		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()
	};
	const char * const stat_usage[] = {
		"perf stat [<options>] [<command>]",
		NULL
@@ -2530,7 +2529,7 @@ int cmd_stat(int argc, const char **argv)
		stat_config.csv_sep = DEFAULT_SEPARATOR;

	if (argc && strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
		argc = __cmd_record(argc, argv);
		argc = __cmd_record(stat_options, argc, argv);
		if (argc < 0)
			return -1;
	} else if (argc && strlen(argv[0]) > 2 && strstarts("report", argv[0]))