perf tools: Configurable per thread proc map processing time out

The time out to limit the individual proc map processing was hard code
to 500ms. This patch introduce a new option --proc-map-timeout to make
the time limit configurable.

Signed-off-by: Kan Liang <kan.liang@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ying Huang <ying.huang@intel.com>
Link: http://lkml.kernel.org/r/1434549071-25611-2-git-send-email-kan.liang@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Kan Liang 2015-06-17 09:51:11 -04:00 committed by Arnaldo Carvalho de Melo
parent 930e6fcd2b
commit 9d9cad763c
17 changed files with 87 additions and 31 deletions

View File

@ -151,6 +151,12 @@ STAT LIVE OPTIONS
Show events other than HLT (x86 only) or Wait state (s390 only)
that take longer than duration usecs.
--proc-map-timeout::
When processing pre-existing threads /proc/XXX/mmap, it may take
a long time, because the file may be huge. A time out is needed
in such cases.
This option sets the time out limit. The default value is 500 ms.
SEE ALSO
--------
linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1],

View File

@ -271,6 +271,11 @@ AUX area tracing event. Optionally the number of bytes to capture per
snapshot can be specified. In Snapshot Mode, trace data is captured only when
signal SIGUSR2 is received.
--proc-map-timeout::
When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
because the file may be huge. A time out is needed in such cases.
This option sets the time out limit. The default value is 500 ms.
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-list[1]

View File

@ -201,6 +201,12 @@ Default is to monitor all CPUS.
Force each column width to the provided list, for large terminal
readability. 0 means no limit (default behavior).
--proc-map-timeout::
When processing pre-existing threads /proc/XXX/mmap, it may take
a long time, because the file may be huge. A time out is needed
in such cases.
This option sets the time out limit. The default value is 500 ms.
INTERACTIVE PROMPTING KEYS
--------------------------

View File

@ -121,6 +121,11 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
--event::
Trace other events, see 'perf list' for a complete list.
--proc-map-timeout::
When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
because the file may be huge. A time out is needed in such cases.
This option sets the time out limit. The default value is 500 ms.
PAGEFAULTS
----------

View File

@ -1311,6 +1311,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
"show events other than"
" HLT (x86 only) or Wait state (s390 only)"
" that take longer than duration usecs"),
OPT_UINTEGER(0, "proc-map-timeout", &kvm->opts.proc_map_timeout,
"per thread proc mmap processing timeout in ms"),
OPT_END()
};
const char * const live_usage[] = {
@ -1338,6 +1340,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
kvm->opts.target.uses_mmap = false;
kvm->opts.target.uid_str = NULL;
kvm->opts.target.uid = UINT_MAX;
kvm->opts.proc_map_timeout = 500;
symbol__init(NULL);
disable_buildid_cache();
@ -1393,7 +1396,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
perf_session__set_id_hdr_size(kvm->session);
ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
kvm->evlist->threads, false);
kvm->evlist->threads, false, kvm->opts.proc_map_timeout);
err = kvm_live_open_events(kvm);
if (err)
goto out;

View File

@ -598,7 +598,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
}
err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
process_synthesized_event, opts->sample_address);
process_synthesized_event, opts->sample_address,
opts->proc_map_timeout);
if (err != 0)
goto out_child;
@ -959,6 +960,7 @@ static struct record record = {
.uses_mmap = true,
.default_per_cpu = true,
},
.proc_map_timeout = 500,
},
.tool = {
.sample = process_sample_event,
@ -1066,6 +1068,8 @@ struct option __record_options[] = {
parse_clockid),
OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
"opts", "AUX area tracing Snapshot Mode", ""),
OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
"per thread proc mmap processing timeout in ms"),
OPT_END()
};

View File

@ -977,7 +977,7 @@ static int __cmd_top(struct perf_top *top)
goto out_delete;
machine__synthesize_threads(&top->session->machines.host, &opts->target,
top->evlist->threads, false);
top->evlist->threads, false, opts->proc_map_timeout);
ret = perf_top__start_counters(top);
if (ret)
goto out_delete;
@ -1087,6 +1087,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
.target = {
.uses_mmap = true,
},
.proc_map_timeout = 500,
},
.max_stack = PERF_MAX_STACK_DEPTH,
.sym_pcnt_filter = 5,
@ -1186,6 +1187,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
"width[,width...]",
"don't try to adjust column width, use these fixed values"),
OPT_UINTEGER(0, "proc-map-timeout", &opts->proc_map_timeout,
"per thread proc mmap processing timeout in ms"),
OPT_END()
};
const char * const top_usage[] = {

View File

@ -1518,7 +1518,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
return -ENOMEM;
err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
evlist->threads, trace__tool_process, false);
evlist->threads, trace__tool_process, false,
trace->opts.proc_map_timeout);
if (err)
symbol__exit();
@ -2747,6 +2748,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
.user_interval = ULLONG_MAX,
.no_buffering = true,
.mmap_pages = UINT_MAX,
.proc_map_timeout = 500,
},
.output = stdout,
.show_comm = true,
@ -2796,6 +2798,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
"Trace pagefaults", parse_pagefaults, "maj"),
OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
"per thread proc mmap processing timeout in ms"),
OPT_END()
};
const char * const trace_subcommands[] = { "record", NULL };

View File

@ -69,6 +69,7 @@ struct record_opts {
unsigned initial_delay;
bool use_clockid;
clockid_t clockid;
unsigned int proc_map_timeout;
};
struct option;

View File

@ -451,7 +451,7 @@ static int do_test_code_reading(bool try_kcore)
}
ret = perf_event__synthesize_thread_map(NULL, threads,
perf_event__process, machine, false);
perf_event__process, machine, false, 500);
if (ret < 0) {
pr_debug("perf_event__synthesize_thread_map failed\n");
goto out_err;

View File

@ -28,7 +28,7 @@ static int init_live_machine(struct machine *machine)
pid_t pid = getpid();
return perf_event__synthesize_mmap_events(NULL, &event, pid, pid,
mmap_handler, machine, true);
mmap_handler, machine, true, 500);
}
#define MAX_STACK 8

View File

@ -129,7 +129,7 @@ static int synth_all(struct machine *machine)
{
return perf_event__synthesize_threads(NULL,
perf_event__process,
machine, 0);
machine, 0, 500);
}
static int synth_process(struct machine *machine)
@ -141,7 +141,7 @@ static int synth_process(struct machine *machine)
err = perf_event__synthesize_thread_map(NULL, map,
perf_event__process,
machine, 0);
machine, 0, 500);
thread_map__delete(map);
return err;

View File

@ -213,19 +213,19 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
return 0;
}
#define PROC_MAP_PARSE_TIMEOUT (500 * 1000000ULL)
int perf_event__synthesize_mmap_events(struct perf_tool *tool,
union perf_event *event,
pid_t pid, pid_t tgid,
perf_event__handler_t process,
struct machine *machine,
bool mmap_data)
bool mmap_data,
unsigned int proc_map_timeout)
{
char filename[PATH_MAX];
FILE *fp;
unsigned long long t;
bool truncation = false;
unsigned long long timeout = proc_map_timeout * 1000000ULL;
int rc = 0;
if (machine__is_default_guest(machine))
@ -258,8 +258,11 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
if (fgets(bf, sizeof(bf), fp) == NULL)
break;
if ((rdclock() - t) > PROC_MAP_PARSE_TIMEOUT) {
pr_warning("Reading %s time out.\n", filename);
if ((rdclock() - t) > timeout) {
pr_warning("Reading %s time out. "
"You may want to increase "
"the time limit by --proc-map-timeout\n",
filename);
truncation = true;
goto out;
}
@ -404,7 +407,9 @@ static int __event__synthesize_thread(union perf_event *comm_event,
pid_t pid, int full,
perf_event__handler_t process,
struct perf_tool *tool,
struct machine *machine, bool mmap_data)
struct machine *machine,
bool mmap_data,
unsigned int proc_map_timeout)
{
char filename[PATH_MAX];
DIR *tasks;
@ -421,7 +426,8 @@ static int __event__synthesize_thread(union perf_event *comm_event,
return -1;
return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
process, machine, mmap_data);
process, machine, mmap_data,
proc_map_timeout);
}
if (machine__is_default_guest(machine))
@ -462,7 +468,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
if (_pid == pid) {
/* process the parent's maps too */
rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
process, machine, mmap_data);
process, machine, mmap_data, proc_map_timeout);
if (rc)
break;
}
@ -476,7 +482,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
struct thread_map *threads,
perf_event__handler_t process,
struct machine *machine,
bool mmap_data)
bool mmap_data,
unsigned int proc_map_timeout)
{
union perf_event *comm_event, *mmap_event, *fork_event;
int err = -1, thread, j;
@ -499,7 +506,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
fork_event,
threads->map[thread], 0,
process, tool, machine,
mmap_data)) {
mmap_data, proc_map_timeout)) {
err = -1;
break;
}
@ -525,7 +532,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
fork_event,
comm_event->comm.pid, 0,
process, tool, machine,
mmap_data)) {
mmap_data, proc_map_timeout)) {
err = -1;
break;
}
@ -542,7 +549,9 @@ out:
int perf_event__synthesize_threads(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine, bool mmap_data)
struct machine *machine,
bool mmap_data,
unsigned int proc_map_timeout)
{
DIR *proc;
char proc_path[PATH_MAX];
@ -582,7 +591,8 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
* one thread couldn't be synthesized.
*/
__event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
1, process, tool, machine, mmap_data);
1, process, tool, machine, mmap_data,
proc_map_timeout);
}
err = 0;

View File

@ -384,10 +384,12 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool,
int perf_event__synthesize_thread_map(struct perf_tool *tool,
struct thread_map *threads,
perf_event__handler_t process,
struct machine *machine, bool mmap_data);
struct machine *machine, bool mmap_data,
unsigned int proc_map_timeout);
int perf_event__synthesize_threads(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine, bool mmap_data);
struct machine *machine, bool mmap_data,
unsigned int proc_map_timeout);
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine);
@ -469,7 +471,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
pid_t pid, pid_t tgid,
perf_event__handler_t process,
struct machine *machine,
bool mmap_data);
bool mmap_data,
unsigned int proc_map_timeout);
size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);

View File

@ -1913,12 +1913,13 @@ int machines__for_each_thread(struct machines *machines,
int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
struct target *target, struct thread_map *threads,
perf_event__handler_t process, bool data_mmap)
perf_event__handler_t process, bool data_mmap,
unsigned int proc_map_timeout)
{
if (target__has_task(target))
return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap);
return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap, proc_map_timeout);
else if (target__has_cpu(target))
return perf_event__synthesize_threads(tool, process, machine, data_mmap);
return perf_event__synthesize_threads(tool, process, machine, data_mmap, proc_map_timeout);
/* command specified */
return 0;
}

View File

@ -222,13 +222,16 @@ int machines__for_each_thread(struct machines *machines,
int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
struct target *target, struct thread_map *threads,
perf_event__handler_t process, bool data_mmap);
perf_event__handler_t process, bool data_mmap,
unsigned int proc_map_timeout);
static inline
int machine__synthesize_threads(struct machine *machine, struct target *target,
struct thread_map *threads, bool data_mmap)
struct thread_map *threads, bool data_mmap,
unsigned int proc_map_timeout)
{
return __machine__synthesize_threads(machine, NULL, target, threads,
perf_event__process, data_mmap);
perf_event__process, data_mmap,
proc_map_timeout);
}
pid_t machine__get_current_tid(struct machine *machine, int cpu);

View File

@ -1368,7 +1368,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
"not processed, if there are samples for addresses they\n"
"will not be resolved, you may find out which are these\n"
"threads by running with -v and redirecting the output\n"
"to a file.\n",
"to a file.\n"
"The time limit to process proc map is too short?\n"
"Increase it by --proc-map-timeout\n",
stats->nr_proc_map_timeout);
}
}