Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c45c6ea2 authored by Stephane Eranian's avatar Stephane Eranian Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Add the ability to specify list of cpus to monitor



This patch adds a -C option to stat, record, top to designate a list of CPUs to
monitor. CPUs can be specified as a comma-separated list or ranges, no space
allowed.

Examples:
$ perf record -a -C0-1,4-7 sleep 1
$ perf top -C0-4
$ perf stat -a -C1,2,3,4 sleep 1

With perf record in per-thread mode with inherit mode on, samples are collected
only when the thread runs on the designated CPUs.

The -C option does not turn on system-wide mode automatically.

Cc: David S. Miller <davem@davemloft.net>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <4bff9496.d345d80a.41fe.7b00@mx.google.com>
Signed-off-by: default avatarStephane Eranian <eranian@google.com>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 761844b9
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -103,6 +103,13 @@ OPTIONS
--raw-samples::
--raw-samples::
Collect raw sample records from all opened counters (default for tracepoint counters).
Collect raw sample records from all opened counters (default for tracepoint counters).


-C::
--cpu::
Collect samples only on the list of cpus provided. Multiple CPUs can be provided as a
comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
In per-thread mode with inheritance mode on (default), samples are captured only when
the thread executes on the designated CPUs. Default is to monitor all CPUs.

SEE ALSO
SEE ALSO
--------
--------
linkperf:perf-stat[1], linkperf:perf-list[1]
linkperf:perf-stat[1], linkperf:perf-list[1]
+7 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,13 @@ OPTIONS
-B::
-B::
        print large numbers with thousands' separators according to locale
        print large numbers with thousands' separators according to locale


-C::
--cpu=::
Count only on the list of cpus provided. Multiple CPUs can be provided as a
comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
In per-thread mode, this option is ignored. The -a option is still necessary
to activate system-wide monitoring. Default is to count on all CPUs.

EXAMPLES
EXAMPLES
--------
--------


+5 −3
Original line number Original line Diff line number Diff line
@@ -25,9 +25,11 @@ OPTIONS
--count=<count>::
--count=<count>::
	Event period to sample.
	Event period to sample.


-C <cpu>::
-C <cpu-list>::
--CPU=<cpu>::
--cpu=<cpu>::
	CPU to profile.
Monitor only on the list of cpus provided. Multiple CPUs can be provided as a
comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
Default is to monitor all CPUS.


-d <seconds>::
-d <seconds>::
--delay=<seconds>::
--delay=<seconds>::
+14 −9
Original line number Original line Diff line number Diff line
@@ -49,7 +49,6 @@ static int group = 0;
static int			realtime_prio			=      0;
static int			realtime_prio			=      0;
static bool			raw_samples			=  false;
static bool			raw_samples			=  false;
static bool			system_wide			=  false;
static bool			system_wide			=  false;
static int			profile_cpu			=     -1;
static pid_t			target_pid			=     -1;
static pid_t			target_pid			=     -1;
static pid_t			target_tid			=     -1;
static pid_t			target_tid			=     -1;
static pid_t			*all_tids			=      NULL;
static pid_t			*all_tids			=      NULL;
@@ -74,6 +73,7 @@ static int file_new = 1;
static off_t			post_processing_offset;
static off_t			post_processing_offset;


static struct perf_session	*session;
static struct perf_session	*session;
static const char		*cpu_list;


struct mmap_data {
struct mmap_data {
	int			counter;
	int			counter;
@@ -300,7 +300,7 @@ static void create_counter(int counter, int cpu)
				die("Permission error - are you root?\n"
				die("Permission error - are you root?\n"
					"\t Consider tweaking"
					"\t Consider tweaking"
					" /proc/sys/kernel/perf_event_paranoid.\n");
					" /proc/sys/kernel/perf_event_paranoid.\n");
			else if (err ==  ENODEV && profile_cpu != -1) {
			else if (err ==  ENODEV && cpu_list) {
				die("No such device - did you specify"
				die("No such device - did you specify"
					" an out-of-range profile CPU?\n");
					" an out-of-range profile CPU?\n");
			}
			}
@@ -622,10 +622,15 @@ static int __cmd_record(int argc, const char **argv)
		close(child_ready_pipe[0]);
		close(child_ready_pipe[0]);
	}
	}


	if ((!system_wide && no_inherit) || profile_cpu != -1) {
	nr_cpus = read_cpu_map(cpu_list);
		open_counters(profile_cpu);
	if (nr_cpus < 1) {
		perror("failed to collect number of CPUs\n");
		return -1;
	}

	if (!system_wide && no_inherit && !cpu_list) {
		open_counters(-1);
	} else {
	} else {
		nr_cpus = read_cpu_map();
		for (i = 0; i < nr_cpus; i++)
		for (i = 0; i < nr_cpus; i++)
			open_counters(cpumap[i]);
			open_counters(cpumap[i]);
	}
	}
@@ -704,7 +709,7 @@ static int __cmd_record(int argc, const char **argv)
	if (perf_guest)
	if (perf_guest)
		perf_session__process_machines(session, event__synthesize_guest_os);
		perf_session__process_machines(session, event__synthesize_guest_os);


	if (!system_wide && profile_cpu == -1)
	if (!system_wide && cpu_list)
		event__synthesize_thread(target_tid, process_synthesized_event,
		event__synthesize_thread(target_tid, process_synthesized_event,
					 session);
					 session);
	else
	else
@@ -794,8 +799,8 @@ static const struct option options[] = {
			    "system-wide collection from all CPUs"),
			    "system-wide collection from all CPUs"),
	OPT_BOOLEAN('A', "append", &append_file,
	OPT_BOOLEAN('A', "append", &append_file,
			    "append to the output file to do incremental profiling"),
			    "append to the output file to do incremental profiling"),
	OPT_INTEGER('C', "profile_cpu", &profile_cpu,
	OPT_STRING('C', "cpu", &cpu_list, "cpu",
			    "CPU to profile on"),
		    "list of cpus to monitor"),
	OPT_BOOLEAN('f', "force", &force,
	OPT_BOOLEAN('f', "force", &force,
			"overwrite existing data file (deprecated)"),
			"overwrite existing data file (deprecated)"),
	OPT_U64('c', "count", &user_interval, "event period to sample"),
	OPT_U64('c', "count", &user_interval, "event period to sample"),
@@ -825,7 +830,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
	argc = parse_options(argc, argv, options, record_usage,
	argc = parse_options(argc, argv, options, record_usage,
			    PARSE_OPT_STOP_AT_NON_OPTION);
			    PARSE_OPT_STOP_AT_NON_OPTION);
	if (!argc && target_pid == -1 && target_tid == -1 &&
	if (!argc && target_pid == -1 && target_tid == -1 &&
		!system_wide && profile_cpu == -1)
		!system_wide && !cpu_list)
		usage_with_options(record_usage, options);
		usage_with_options(record_usage, options);


	if (force && append_file) {
	if (force && append_file) {
+10 −4
Original line number Original line Diff line number Diff line
@@ -69,7 +69,7 @@ static struct perf_event_attr default_attrs[] = {
};
};


static bool			system_wide			=  false;
static bool			system_wide			=  false;
static unsigned int		nr_cpus				=  0;
static int			nr_cpus				=  0;
static int			run_idx				=  0;
static int			run_idx				=  0;


static int			run_count			=  1;
static int			run_count			=  1;
@@ -82,6 +82,7 @@ static int thread_num = 0;
static pid_t			child_pid			= -1;
static pid_t			child_pid			= -1;
static bool			null_run			=  false;
static bool			null_run			=  false;
static bool			big_num				=  false;
static bool			big_num				=  false;
static const char		*cpu_list;




static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
@@ -158,7 +159,7 @@ static int create_perf_stat_counter(int counter)
				    PERF_FORMAT_TOTAL_TIME_RUNNING;
				    PERF_FORMAT_TOTAL_TIME_RUNNING;


	if (system_wide) {
	if (system_wide) {
		unsigned int cpu;
		int cpu;


		for (cpu = 0; cpu < nr_cpus; cpu++) {
		for (cpu = 0; cpu < nr_cpus; cpu++) {
			fd[cpu][counter][0] = sys_perf_event_open(attr,
			fd[cpu][counter][0] = sys_perf_event_open(attr,
@@ -208,7 +209,7 @@ static inline int nsec_counter(int counter)
static void read_counter(int counter)
static void read_counter(int counter)
{
{
	u64 count[3], single_count[3];
	u64 count[3], single_count[3];
	unsigned int cpu;
	int cpu;
	size_t res, nv;
	size_t res, nv;
	int scaled;
	int scaled;
	int i, thread;
	int i, thread;
@@ -542,6 +543,8 @@ static const struct option options[] = {
		    "null run - dont start any counters"),
		    "null run - dont start any counters"),
	OPT_BOOLEAN('B', "big-num", &big_num,
	OPT_BOOLEAN('B', "big-num", &big_num,
		    "print large numbers with thousands\' separators"),
		    "print large numbers with thousands\' separators"),
	OPT_STRING('C', "cpu", &cpu_list, "cpu",
		    "list of cpus to monitor in system-wide"),
	OPT_END()
	OPT_END()
};
};


@@ -566,10 +569,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
	}
	}


	if (system_wide)
	if (system_wide)
		nr_cpus = read_cpu_map();
		nr_cpus = read_cpu_map(cpu_list);
	else
	else
		nr_cpus = 1;
		nr_cpus = 1;


	if (nr_cpus < 1)
		usage_with_options(stat_usage, options);

	if (target_pid != -1) {
	if (target_pid != -1) {
		target_tid = target_pid;
		target_tid = target_pid;
		thread_num = find_all_tid(target_pid, &all_tids);
		thread_num = find_all_tid(target_pid, &all_tids);
Loading