From d53e57d039c323fe3a43630e9f729df48134e2c9 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 25 Oct 2013 20:25:49 -0400 Subject: perf ui tui progress: Don't force a refresh during progress update Each call to tui_progress__update() would forcibly refresh the entire screen. This is somewhat inefficient and causes noticable flickering during the startup of perf-report, especially on large/slow terminals. It looks like the force-refresh in tui_progress__update() serves no purpose other than to clear the screen so that the progress bar of a previous operation does not subsume that of a subsequent operation. But we can do just that in a much more efficient manner by clearing only the region that a previous progress bar may have occupied before repainting the new progress bar. Then the force-refresh could be removed with no change in visuals. This patch disables the slow force-refresh in tui_progress__update() and instead calls SLsmg_fill_region() on the entire area that the progress bar may occupy before repainting it. This change makes the startup of perf-report much faster and appear much "smoother". It turns out that this was a big bottleneck in the startup speed of perf-report -- with this patch, perf-report starts up ~2x faster (1.1s vs 0.55s) on my machines. (These numbers were measured by running "time perf report" on an 8MB perf.data and pressing 'q' immediately.) Signed-off-by: Patrick Palka Acked-by: Ingo Molnar Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1382747149-9716-1-git-send-email-patrick@parcs.ath.cx Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/tui/progress.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c index 3e2d936d744..c61d14b101e 100644 --- a/tools/perf/ui/tui/progress.c +++ b/tools/perf/ui/tui/progress.c @@ -18,13 +18,14 @@ static void tui_progress__update(struct ui_progress *p) if (p->total == 0) return; - ui__refresh_dimensions(true); + ui__refresh_dimensions(false); pthread_mutex_lock(&ui__lock); y = SLtt_Screen_Rows / 2 - 2; SLsmg_set_color(0); SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols); SLsmg_gotorc(y++, 1); SLsmg_write_string((char *)p->title); + SLsmg_fill_region(y, 1, 1, SLtt_Screen_Cols - 2, ' '); SLsmg_set_color(HE_COLORSET_SELECTED); bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total; SLsmg_fill_region(y, 1, 1, bar, ' '); -- cgit v1.2.3-18-g5258 From ef503831d8d64e12c6dad5547875cfcd4c5d043c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 7 Nov 2013 16:41:19 -0300 Subject: perf evsel: Remove idx parm from constructor Most uses of the evsel constructor are followed by a call to perf_evlist__add with an idex of evlist->nr_entries, so make rename the current constructor to perf_evsel__new_idx and remove the need for passing the constructor for the common case. We still need the new_idx variant because the way groups are handled, with evsel->nr_members holding the number of entries in an evlist, partitioning the evlist into sublists inside a single linked list. This asks for a clarifying refactoring, but for now simplify the non parser cases, so that tool writers don't have to bother with evsel idx setting. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-zy9tskx6jqm2rmw7468zze2a@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 13 +++++-------- tools/perf/tests/evsel-tp-sched.c | 4 ++-- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/open-syscall-all-cpus.c | 2 +- tools/perf/tests/open-syscall-tp-fields.c | 2 +- tools/perf/tests/open-syscall.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/util/evlist.c | 9 +++++---- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 15 +++++++++++++-- tools/perf/util/header.c | 4 ++-- tools/perf/util/parse-events.c | 6 +++--- 12 files changed, 37 insertions(+), 28 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 329b7832b5d..68943cad70d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -149,10 +149,9 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel) perf_evsel__delete(evsel); } -static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, - void *handler, int idx) +static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler) { - struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction, idx); + struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); if (evsel) { evsel->priv = malloc(sizeof(struct syscall_tp)); @@ -186,17 +185,16 @@ static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist, void *sys_exit_handler) { int ret = -1; - int idx = evlist->nr_entries; struct perf_evsel *sys_enter, *sys_exit; - sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler, idx++); + sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler); if (sys_enter == NULL) goto out; if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args)) goto out_delete_sys_enter; - sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler, idx++); + sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler); if (sys_exit == NULL) goto out_delete_sys_enter; @@ -1824,8 +1822,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname", - evlist->nr_entries); + struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); if (evsel == NULL) return; diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 9b98c155483..4774f7fbb75 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -32,7 +32,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, int test__perf_evsel__tp_sched_test(void) { - struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); + struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); int ret = 0; if (evsel == NULL) { @@ -63,7 +63,7 @@ int test__perf_evsel__tp_sched_test(void) perf_evsel__delete(evsel); - evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); + evsel = perf_evsel__newtp("sched", "sched_wakeup"); if (perf_evsel__test_field(evsel, "comm", 16, true)) ret = -1; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index a7232c204eb..d64ab79c6d3 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -65,7 +65,7 @@ int test__basic_mmap(void) char name[64]; snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); - evsels[i] = perf_evsel__newtp("syscalls", name, i); + evsels[i] = perf_evsel__newtp("syscalls", name); if (evsels[i] == NULL) { pr_debug("perf_evsel__new\n"); goto out_free_evlist; diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c index b0657a9ccda..5fecdbd2f5f 100644 --- a/tools/perf/tests/open-syscall-all-cpus.c +++ b/tools/perf/tests/open-syscall-all-cpus.c @@ -26,7 +26,7 @@ int test__open_syscall_event_on_all_cpus(void) CPU_ZERO(&cpu_set); - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); if (evsel == NULL) { pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); goto out_thread_map_delete; diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index 524b221b829..41cc0badb74 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c @@ -27,7 +27,7 @@ int test__syscall_open_tp_fields(void) goto out; } - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); if (evsel == NULL) { pr_debug("%s: perf_evsel__newtp\n", __func__); goto out_delete_evlist; diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c index befc0671f95..c1dc7d25f38 100644 --- a/tools/perf/tests/open-syscall.c +++ b/tools/perf/tests/open-syscall.c @@ -15,7 +15,7 @@ int test__open_syscall_event(void) return -1; } - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); if (evsel == NULL) { pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); goto out_thread_map_delete; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 6e2b44ec074..73c5c37cb27 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -42,7 +42,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) return -1; } - evsel = perf_evsel__new(&attr, 0); + evsel = perf_evsel__new(&attr); if (evsel == NULL) { pr_debug("perf_evsel__new\n"); goto out_free_evlist; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b939221efd8..99dc58e5dcc 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -117,6 +117,8 @@ void perf_evlist__delete(struct perf_evlist *evlist) void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) { list_add_tail(&entry->node, &evlist->entries); + entry->idx = evlist->nr_entries; + if (!evlist->nr_entries++) perf_evlist__set_id_pos(evlist); } @@ -165,7 +167,7 @@ int perf_evlist__add_default(struct perf_evlist *evlist) event_attr_init(&attr); - evsel = perf_evsel__new(&attr, 0); + evsel = perf_evsel__new(&attr); if (evsel == NULL) goto error; @@ -190,7 +192,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, size_t i; for (i = 0; i < nr_attrs; i++) { - evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i); + evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); if (evsel == NULL) goto out_delete_partial_list; list_add_tail(&evsel->node, &head); @@ -249,9 +251,8 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler) { - struct perf_evsel *evsel; + struct perf_evsel *evsel = perf_evsel__newtp(sys, name); - evsel = perf_evsel__newtp(sys, name, evlist->nr_entries); if (evsel == NULL) return -1; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 5280820ed38..f95653a639a 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -168,7 +168,7 @@ void perf_evsel__init(struct perf_evsel *evsel, perf_evsel__calc_id_pos(evsel); } -struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) +struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); @@ -219,7 +219,7 @@ out: return format; } -struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) +struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 64ec8e1a7a2..0178233abd6 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -96,8 +96,19 @@ struct thread_map; struct perf_evlist; struct perf_record_opts; -struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); -struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); +struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); + +static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) +{ + return perf_evsel__new_idx(attr, 0); +} + +struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); + +static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) +{ + return perf_evsel__newtp_idx(sys, name, 0); +} struct event_format *event_format__new(const char *sys, const char *name); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 26d9520a0c1..369c03648f8 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2797,7 +2797,7 @@ int perf_session__read_header(struct perf_session *session) perf_event__attr_swap(&f_attr.attr); tmp = lseek(fd, 0, SEEK_CUR); - evsel = perf_evsel__new(&f_attr.attr, i); + evsel = perf_evsel__new(&f_attr.attr); if (evsel == NULL) goto out_delete_evlist; @@ -2916,7 +2916,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, return -ENOMEM; } - evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries); + evsel = perf_evsel__new(&event->attr.attr); if (evsel == NULL) return -ENOMEM; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index c90e55cf7e8..6de6f89c2a6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -277,7 +277,7 @@ static int __add_event(struct list_head *list, int *idx, event_attr_init(attr); - evsel = perf_evsel__new(attr, (*idx)++); + evsel = perf_evsel__new_idx(attr, (*idx)++); if (!evsel) return -ENOMEM; @@ -378,7 +378,7 @@ static int add_tracepoint(struct list_head *list, int *idx, { struct perf_evsel *evsel; - evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); + evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); if (!evsel) return -ENOMEM; @@ -1097,7 +1097,7 @@ static bool is_event_supported(u8 type, unsigned config) .threads = { 0 }, }; - evsel = perf_evsel__new(&attr, 0); + evsel = perf_evsel__new(&attr); if (evsel) { ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; perf_evsel__delete(evsel); -- cgit v1.2.3-18-g5258 From 62605dc50c27bf0e4ff69b7b3166f226586aff02 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 09:44:09 -0300 Subject: perf record: Synthesize non-exec MMAP records when --data used When perf_event_attr.mmap_data is set the kernel will generate PERF_RECORD_MMAP events when non-exec (data, SysV mem) mmaps are created, so we need to synthesize from /proc/pid/maps for existing threads, as we do for exec mmaps. Right now just 'perf record' does it, but any other tool that uses perf_event__synthesize_thread(s|map) can request it. Reported-by: Don Zickus Tested-by: Don Zickus Cc: Adrian Hunter Cc: Bill Gray Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Joe Mario Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Richard Fowles Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ihwzraikx23ian9txinogvv2@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 4 ++-- tools/perf/builtin-record.c | 6 ++--- tools/perf/builtin-top.c | 4 ++-- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/event.c | 50 ++++++++++++++++++++++++----------------- tools/perf/util/event.h | 4 ++-- 7 files changed, 42 insertions(+), 32 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index cd9f92078ab..f36e8209c30 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1550,10 +1550,10 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, perf_event__synthesize_thread_map(&kvm->tool, kvm->evlist->threads, perf_event__process, - &kvm->session->machines.host); + &kvm->session->machines.host, false); else perf_event__synthesize_threads(&kvm->tool, perf_event__process, - &kvm->session->machines.host); + &kvm->session->machines.host, false); err = kvm_live_open_events(kvm); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 15280b5e557..afb252cf6ec 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -482,11 +482,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (perf_target__has_task(&opts->target)) err = perf_event__synthesize_thread_map(tool, evsel_list->threads, - process_synthesized_event, - machine); + process_synthesized_event, + machine, opts->sample_address); else if (perf_target__has_cpu(&opts->target)) err = perf_event__synthesize_threads(tool, process_synthesized_event, - machine); + machine, opts->sample_address); else /* command specified */ err = 0; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 9acca8856cc..cc96d753db9 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -953,10 +953,10 @@ static int __cmd_top(struct perf_top *top) if (perf_target__has_task(&opts->target)) perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, perf_event__process, - &top->session->machines.host); + &top->session->machines.host, false); else perf_event__synthesize_threads(&top->tool, perf_event__process, - &top->session->machines.host); + &top->session->machines.host, false); ret = perf_top__start_counters(top); if (ret) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 68943cad70d..277c2367e0c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1343,10 +1343,10 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) if (perf_target__has_task(&trace->opts.target)) { err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, trace__tool_process, - trace->host); + trace->host, false); } else { err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, - trace->host); + trace->host, false); } if (err) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 49ccc3b2995..6d9dc198a20 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -441,7 +441,7 @@ static int do_test_code_reading(bool try_kcore) } ret = perf_event__synthesize_thread_map(NULL, threads, - perf_event__process, machine); + perf_event__process, machine, false); if (ret < 0) { pr_debug("perf_event__synthesize_thread_map failed\n"); goto out_err; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index ec9ae1114ed..6e3a846aed0 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -170,7 +170,8 @@ static 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) + struct machine *machine, + bool mmap_data) { char filename[PATH_MAX]; FILE *fp; @@ -188,10 +189,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, } event->header.type = PERF_RECORD_MMAP; - /* - * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c - */ - event->header.misc = PERF_RECORD_MISC_USER; while (1) { char bf[BUFSIZ]; @@ -215,9 +212,17 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, if (n != 5) continue; + /* + * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c + */ + event->header.misc = PERF_RECORD_MISC_USER; - if (prot[2] != 'x') - continue; + if (prot[2] != 'x') { + if (!mmap_data || prot[0] != 'r') + continue; + + event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; + } if (!strcmp(execname, "")) strcpy(execname, anonstr); @@ -304,20 +309,21 @@ 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) + struct machine *machine, bool mmap_data) { pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, process, machine); if (tgid == -1) return -1; return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, - process, machine); + process, machine, mmap_data); } int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, - struct machine *machine) + struct machine *machine, + bool mmap_data) { union perf_event *comm_event, *mmap_event; int err = -1, thread, j; @@ -334,7 +340,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, for (thread = 0; thread < threads->nr; ++thread) { if (__event__synthesize_thread(comm_event, mmap_event, threads->map[thread], 0, - process, tool, machine)) { + process, tool, machine, + mmap_data)) { err = -1; break; } @@ -356,10 +363,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, /* if not, generate events for it */ if (need_leader && - __event__synthesize_thread(comm_event, - mmap_event, - comm_event->comm.pid, 0, - process, tool, machine)) { + __event__synthesize_thread(comm_event, mmap_event, + comm_event->comm.pid, 0, + process, tool, machine, + mmap_data)) { err = -1; break; } @@ -374,7 +381,7 @@ out: int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, - struct machine *machine) + struct machine *machine, bool mmap_data) { DIR *proc; struct dirent dirent, *next; @@ -404,7 +411,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, * one thread couldn't be synthesized. */ __event__synthesize_thread(comm_event, mmap_event, pid, 1, - process, tool, machine); + process, tool, machine, mmap_data); } err = 0; @@ -528,19 +535,22 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused, size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) { - return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", + return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", event->mmap.pid, event->mmap.tid, event->mmap.start, - event->mmap.len, event->mmap.pgoff, event->mmap.filename); + event->mmap.len, event->mmap.pgoff, + (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', + event->mmap.filename); } size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) { return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 - " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n", + " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n", event->mmap2.pid, event->mmap2.tid, event->mmap2.start, event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, event->mmap2.min, event->mmap2.ino, event->mmap2.ino_generation, + (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', event->mmap2.filename); } diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index f8d70f3003a..30fec9901e4 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -208,10 +208,10 @@ 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); + struct machine *machine, bool mmap_data); int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, - struct machine *machine); + struct machine *machine, bool mmap_data); int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine, -- cgit v1.2.3-18-g5258 From 58d925dcede9e8765876707a33a3406011fe1c11 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 11:28:02 -0300 Subject: perf machine: Introduce synthesize_threads method out of open coded equivalent Further simplifications to be done on following patch, as most tools don't use the callback, using instead just the canned machine__process_event one. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-r1m0vuuj3cat4bampno9yc8d@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 15 +++------------ tools/perf/builtin-record.c | 12 ++---------- tools/perf/builtin-top.c | 11 +++-------- tools/perf/builtin-trace.c | 11 ++--------- tools/perf/util/machine.c | 12 ++++++++++++ tools/perf/util/machine.h | 4 ++++ 6 files changed, 26 insertions(+), 39 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index f36e8209c30..f5d2c4bccbe 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1544,18 +1544,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, } kvm->session->evlist = kvm->evlist; perf_session__set_id_hdr_size(kvm->session); - - - if (perf_target__has_task(&kvm->opts.target)) - perf_event__synthesize_thread_map(&kvm->tool, - kvm->evlist->threads, - perf_event__process, - &kvm->session->machines.host, false); - else - perf_event__synthesize_threads(&kvm->tool, perf_event__process, - &kvm->session->machines.host, false); - - + machine__synthesize_threads(&kvm->session->machines.host, &kvm->tool, + &kvm->opts.target, kvm->evlist->threads, + perf_event__process, false); err = kvm_live_open_events(kvm); if (err) goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index afb252cf6ec..41d1f37f534 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -480,16 +480,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_event__synthesize_guest_os, tool); } - if (perf_target__has_task(&opts->target)) - err = perf_event__synthesize_thread_map(tool, evsel_list->threads, - process_synthesized_event, - machine, opts->sample_address); - else if (perf_target__has_cpu(&opts->target)) - err = perf_event__synthesize_threads(tool, process_synthesized_event, - machine, opts->sample_address); - else /* command specified */ - err = 0; - + err = machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, + process_synthesized_event, opts->sample_address); if (err != 0) goto out_delete_session; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index cc96d753db9..c3a936ef768 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -950,14 +950,9 @@ static int __cmd_top(struct perf_top *top) if (ret) goto out_delete; - if (perf_target__has_task(&opts->target)) - perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, - perf_event__process, - &top->session->machines.host, false); - else - perf_event__synthesize_threads(&top->tool, perf_event__process, - &top->session->machines.host, false); - + machine__synthesize_threads(&top->session->machines.host, &top->tool, + &opts->target, top->evlist->threads, + perf_event__process, false); ret = perf_top__start_counters(top); if (ret) goto out_delete; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 277c2367e0c..7690324824d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1340,15 +1340,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) if (trace->host == NULL) return -ENOMEM; - if (perf_target__has_task(&trace->opts.target)) { - err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, - trace__tool_process, - trace->host, false); - } else { - err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, - trace->host, false); - } - + err = machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, + evlist->threads, trace__tool_process, false); if (err) symbol__exit(); diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index ce034c183a7..9f2c61d5a9e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1394,3 +1394,15 @@ int machine__for_each_thread(struct machine *machine, } return rc; } + +int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap) +{ + if (perf_target__has_task(target)) + return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); + else if (perf_target__has_cpu(target)) + return perf_event__synthesize_threads(tool, process, machine, data_mmap); + /* command specified */ + return 0; +} diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 2389ba81faf..14a89d2aeca 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -4,6 +4,7 @@ #include #include #include "map.h" +#include "event.h" struct addr_location; struct branch_stack; @@ -178,4 +179,7 @@ int machine__for_each_thread(struct machine *machine, int (*fn)(struct thread *thread, void *p), void *priv); +int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap); #endif /* __PERF_MACHINE_H */ -- cgit v1.2.3-18-g5258 From a33fbd56ec83b5421090b4d8f2032f635e6a9488 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 11:36:12 -0300 Subject: perf machine: Simplify synthesize_threads method Several tools (top, kvm) don't need to be called back to process each of the syntheiszed records, instead relying on the machine__process_event function to change the per machine data structures that represent threads and mmaps, so provide a way to ask for this common idiom. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-pusqibp8n3c4ynegd1frn4zd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 5 ++--- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-top.c | 5 ++--- tools/perf/builtin-trace.c | 4 ++-- tools/perf/util/machine.c | 6 +++--- tools/perf/util/machine.h | 14 +++++++++++--- 6 files changed, 22 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index f5d2c4bccbe..346bb5909e3 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1544,9 +1544,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, } kvm->session->evlist = kvm->evlist; perf_session__set_id_hdr_size(kvm->session); - machine__synthesize_threads(&kvm->session->machines.host, &kvm->tool, - &kvm->opts.target, kvm->evlist->threads, - perf_event__process, false); + machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, + kvm->evlist->threads, false); err = kvm_live_open_events(kvm); if (err) goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 41d1f37f534..fc68b26d58f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -480,8 +480,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_event__synthesize_guest_os, tool); } - err = machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, - process_synthesized_event, opts->sample_address); + err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, + process_synthesized_event, opts->sample_address); if (err != 0) goto out_delete_session; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c3a936ef768..8c520d9fecf 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -950,9 +950,8 @@ static int __cmd_top(struct perf_top *top) if (ret) goto out_delete; - machine__synthesize_threads(&top->session->machines.host, &top->tool, - &opts->target, top->evlist->threads, - perf_event__process, false); + machine__synthesize_threads(&top->session->machines.host, &opts->target, + top->evlist->threads, false); ret = perf_top__start_counters(top); if (ret) goto out_delete; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 7690324824d..c3008b1c369 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1340,8 +1340,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) if (trace->host == NULL) return -ENOMEM; - err = machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, - evlist->threads, trace__tool_process, false); + err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, + evlist->threads, trace__tool_process, false); if (err) symbol__exit(); diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 9f2c61d5a9e..680700b6d77 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1395,9 +1395,9 @@ int machine__for_each_thread(struct machine *machine, return rc; } -int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct perf_target *target, struct thread_map *threads, - perf_event__handler_t process, bool data_mmap) +int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap) { if (perf_target__has_task(target)) return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 14a89d2aeca..fedd1dfaf71 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -179,7 +179,15 @@ int machine__for_each_thread(struct machine *machine, int (*fn)(struct thread *thread, void *p), void *priv); -int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct perf_target *target, struct thread_map *threads, - perf_event__handler_t process, bool data_mmap); +int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap); +static inline +int machine__synthesize_threads(struct machine *machine, struct perf_target *target, + struct thread_map *threads, bool data_mmap) +{ + return __machine__synthesize_threads(machine, NULL, target, threads, + perf_event__process, data_mmap); +} + #endif /* __PERF_MACHINE_H */ -- cgit v1.2.3-18-g5258 From 7524f63b997cc02a80aa073558728ae3ee242cf8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 8 Nov 2013 17:53:42 +0900 Subject: perf tools: Prevent condition that all sort keys are elided If given sort keys are all elided there'll be no output except for the overhead column - actually the TUI shows a noisy output. In this case it'd be better to show up the sort keys rather than elide. Before: $ perf report -s comm -c perf (...) # Overhead # ........ # 100.00% After: $ perf report -s comm -c perf (...) # Overhead Command # ........ ....... # 100.00% perf Signed-off-by: Namhyung Kim Acked-by: Ingo Molnar Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1383900822-14609-1-git-send-email-namhyung@kernel.org [ Us curly braces around multi-line statements, as requested by Ingo Molnar ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 3c1b75c8b9a..8b0bb1f4494 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1137,6 +1137,8 @@ static void sort_entry__setup_elide(struct sort_entry *se, void sort__setup_elide(FILE *output) { + struct sort_entry *se; + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", output); sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, @@ -1172,4 +1174,15 @@ void sort__setup_elide(FILE *output) "snoop", output); } + /* + * It makes no sense to elide all of sort entries. + * Just revert them to show up again. + */ + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (!se->elide) + return; + } + + list_for_each_entry(se, &hist_entry__sort_list, list) + se->elide = false; } -- cgit v1.2.3-18-g5258 From 410f17860318f36b999a90138f50350e3dc49933 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 8 Nov 2013 12:27:50 +0200 Subject: perf record: Use correct return type for write() write() returns a 'ssize_t' not an 'int'. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1383906470-21002-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index fc68b26d58f..8f5af32d645 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -81,7 +81,7 @@ static int write_output(struct perf_record *rec, void *buf, size_t size) struct perf_data_file *file = &rec->file; while (size) { - int ret = write(file->fd, buf, size); + ssize_t ret = write(file->fd, buf, size); if (ret < 0) { pr_err("failed to write perf data, error: %m\n"); -- cgit v1.2.3-18-g5258 From a9986fad6645b98d5bb3c2f83c22efb0761ca272 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 7 Nov 2013 21:23:24 -0700 Subject: perf record: Move existing write_output into helper function Code move only; no logic changes. In preparation for the mmap based output option in the next patch. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1383884605-30968-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8f5af32d645..880227eae20 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -76,7 +76,7 @@ struct perf_record { long samples; }; -static int write_output(struct perf_record *rec, void *buf, size_t size) +static int do_write_output(struct perf_record *rec, void *buf, size_t size) { struct perf_data_file *file = &rec->file; @@ -97,6 +97,11 @@ static int write_output(struct perf_record *rec, void *buf, size_t size) return 0; } +static int write_output(struct perf_record *rec, void *buf, size_t size) +{ + return do_write_output(rec, buf, size); +} + static int process_synthesized_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, -- cgit v1.2.3-18-g5258 From d0b849e9bced36cf279881294c07c43b0b9dce86 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 16:28:42 -0300 Subject: perf tests: Check return of perf_evlist__open sw clock event period test We were not checking if we successfully opened the counters, i.e. if sys_perf_event_open worked, when it doesn't in this test, we were continuing anyway and then segfaulting when trying to access the file descriptor array, that at that point had been freed in perf_evlist__open error path: [root@ssdandy ~]# perf test -v 19 19: Test software clock events have valid period values : --- start --- Segmentation fault (core dumped) [root@ssdandy ~]# Do the check and bail out instead. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-6qy8ljkn0e9hm7bh7keo5z68@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sw-clock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 73c5c37cb27..ed777728dfe 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -57,7 +57,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) goto out_delete_maps; } - perf_evlist__open(evlist); + if (perf_evlist__open(evlist)) { + err = -errno; + pr_debug("Couldn't open evlist: %s\n", strerror(errno)); + goto out_delete_maps; + } err = perf_evlist__mmap(evlist, 128, true); if (err < 0) { -- cgit v1.2.3-18-g5258 From 67c1e4a53b17894e6a24f95057cc374c4be051cb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 16:33:18 -0300 Subject: perf tests: Use lower sample_freq in sw clock event period test We were using it at 10 kHz, which doesn't work in machines where somehow the max freq was auto reduced by the kernel: [root@ssdandy ~]# perf test 19 19: Test software clock events have valid period values : FAILED! [root@ssdandy ~]# perf test -v 19 19: Test software clock events have valid period values : --- start --- Couldn't open evlist: Invalid argument ---- end ---- Test software clock events have valid period values: FAILED! [root@ssdandy ~]# [root@ssdandy ~]# cat /proc/sys/kernel/perf_event_max_sample_rate 7000 Reducing it to 500 Hz should be good enough for this test and also shouldn't affect what it is testing. But warn the user if it fails, informing the knob and the freq tried. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-548rhj1uo6xbwnxa95kw3hqe@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sw-clock.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index ed777728dfe..93a7139ff5f 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -34,7 +34,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) .freq = 1, }; - attr.sample_freq = 10000; + attr.sample_freq = 500; evlist = perf_evlist__new(); if (evlist == NULL) { @@ -58,8 +58,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) } if (perf_evlist__open(evlist)) { + const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate"; + err = -errno; - pr_debug("Couldn't open evlist: %s\n", strerror(errno)); + pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", + strerror(errno), knob, (u64)attr.sample_freq); goto out_delete_maps; } -- cgit v1.2.3-18-g5258 From 73faab3a421351c342b10b0177fec9eea1a1d809 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 12 Nov 2013 15:24:59 +0900 Subject: perf trace: Beautify fifth argument of mmap() as fd The fifth argument of mmap syscall is fd and it often contains -1 as a value for anon mappings. Without this patch it doesn't show the file name as well as it shows -1 as 4294967295. Signed-off-by: Namhyung Kim Acked-by: David Ahern Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1384237500-22991-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c3008b1c369..aeb6296a76b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -951,7 +951,8 @@ static struct syscall_fmt { { .name = "mmap", .hexret = true, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ [2] = SCA_MMAP_PROT, /* prot */ - [3] = SCA_MMAP_FLAGS, /* flags */ }, }, + [3] = SCA_MMAP_FLAGS, /* flags */ + [4] = SCA_FD, /* fd */ }, }, { .name = "mprotect", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* start */ [2] = SCA_MMAP_PROT, /* prot */ }, }, -- cgit v1.2.3-18-g5258 From 96695d440242aca871ef8d797bd98d9cbd7ad8a0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 12 Nov 2013 08:51:45 -0300 Subject: perf trace: Separate tp syscall field caching into init routine to be reused We need to set this in evsels coming out of a perf.data file header, not just for new ones created for live sessions. So separate the code that caches the syscall entry/exit tracepoint format fields into a new function that will be used in the next changeset. Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20131112115700.GC4053@ghostprotocols.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index aeb6296a76b..3fa1dce6d43 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -149,20 +149,32 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel) perf_evsel__delete(evsel); } +static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler) +{ + evsel->priv = malloc(sizeof(struct syscall_tp)); + if (evsel->priv != NULL) { + if (perf_evsel__init_sc_tp_uint_field(evsel, id)) + goto out_delete; + + evsel->handler = handler; + return 0; + } + + return -ENOMEM; + +out_delete: + free(evsel->priv); + evsel->priv = NULL; + return -ENOENT; +} + static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler) { struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); if (evsel) { - evsel->priv = malloc(sizeof(struct syscall_tp)); - - if (evsel->priv == NULL) + if (perf_evsel__init_syscall_tp(evsel, handler)) goto out_delete; - - if (perf_evsel__init_sc_tp_uint_field(evsel, id)) - goto out_delete; - - evsel->handler = handler; } return evsel; -- cgit v1.2.3-18-g5258 From 003824e8c27eeb8d3eec54cfab5845ec01ab532e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 12 Nov 2013 15:25:00 +0900 Subject: perf trace: Fix segfault on perf trace -i perf.data When replaying a previous record session, it'll get a segfault since it doesn't initialize raw_syscalls enter/exit tracepoint's evsel->priv for caching the format fields. So fix it by properly initializing sys_enter/exit evsels that comes from reading the perf.data file header. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1384237500-22991-2-git-send-email-namhyung@kernel.org [ Split the syscall tp field caching part in the previous patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 3fa1dce6d43..8d6ea8fbf47 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1766,16 +1766,6 @@ static int trace__process_sample(struct perf_tool *tool, return err; } -static bool -perf_session__has_tp(struct perf_session *session, const char *name) -{ - struct perf_evsel *evsel; - - evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name); - - return evsel != NULL; -} - static int parse_target_str(struct trace *trace) { if (trace->opts.target.pid) { @@ -2012,8 +2002,6 @@ out_error: static int trace__replay(struct trace *trace) { const struct perf_evsel_str_handler handlers[] = { - { "raw_syscalls:sys_enter", trace__sys_enter, }, - { "raw_syscalls:sys_exit", trace__sys_exit, }, { "probe:vfs_getname", trace__vfs_getname, }, }; struct perf_data_file file = { @@ -2021,6 +2009,7 @@ static int trace__replay(struct trace *trace) .mode = PERF_DATA_MODE_READ, }; struct perf_session *session; + struct perf_evsel *evsel; int err = -1; trace->tool.sample = trace__process_sample; @@ -2052,13 +2041,29 @@ static int trace__replay(struct trace *trace) if (err) goto out; - if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) { - pr_err("Data file does not have raw_syscalls:sys_enter events\n"); + evsel = perf_evlist__find_tracepoint_by_name(session->evlist, + "raw_syscalls:sys_enter"); + if (evsel == NULL) { + pr_err("Data file does not have raw_syscalls:sys_enter event\n"); + goto out; + } + + if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 || + perf_evsel__init_sc_tp_ptr_field(evsel, args)) { + pr_err("Error during initialize raw_syscalls:sys_enter event\n"); + goto out; + } + + evsel = perf_evlist__find_tracepoint_by_name(session->evlist, + "raw_syscalls:sys_exit"); + if (evsel == NULL) { + pr_err("Data file does not have raw_syscalls:sys_exit event\n"); goto out; } - if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) { - pr_err("Data file does not have raw_syscalls:sys_exit events\n"); + if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 || + perf_evsel__init_sc_tp_uint_field(evsel, ret)) { + pr_err("Error during initialize raw_syscalls:sys_exit event\n"); goto out; } -- cgit v1.2.3-18-g5258 From 3fe2130523b2e098085eb4d38cd5b737a97cbee6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 12 Nov 2013 11:45:21 -0300 Subject: perf tests: Compensate lower sample freq with longer test loop Doesn't work for me: ./perf test -v 19 19: Test software clock events have valid period values : --- start --- mmap size 528384B mmap size 528384B All (0) samples have period value of 1! ---- end ---- Test software clock events have valid period values: FAILED! Compensate the lower freq introduced in 67c1e4a53b17 with a longer loop, Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/5281D3B8.2030104@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sw-clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 93a7139ff5f..6664a7cd828 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -9,7 +9,7 @@ #include "util/cpumap.h" #include "util/thread_map.h" -#define NR_LOOPS 1000000 +#define NR_LOOPS 10000000 /* * This test will open software clock events (cpu-clock, task-clock) -- cgit v1.2.3-18-g5258 From 7f7a4138c66e857cc5bbf6e248a47379765349b5 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 12 Nov 2013 16:10:10 +0200 Subject: perf trace: Change syscall summary duration order Switch duration order to minimum, average, maximum for the '--summary' command line option because it's more natural to read. Signed-off-by: Pekka Enberg Acked-by: David Ahern Cc: David Ahern Cc: Ingo Molnar Link: http://lkml.kernel.org/r/1384265410-12344-1-git-send-email-penberg@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8d6ea8fbf47..8990fbeb8b4 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2093,7 +2093,7 @@ static size_t trace__fprintf_threads_header(FILE *fp) printed = fprintf(fp, "\n _____________________________________________________________________________\n"); printed += fprintf(fp, " __) Summary of events (__\n\n"); printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); - printed += fprintf(fp, " syscall count min max avg stddev\n"); + printed += fprintf(fp, " syscall count min avg max stddev\n"); printed += fprintf(fp, " msec msec msec %%\n"); printed += fprintf(fp, " _____________________________________________________________________________\n\n"); @@ -2129,8 +2129,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, sc = &trace->syscalls.table[inode->i]; printed += fprintf(fp, "%24s %14s : ", "", sc->name); printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f", - n, min, max); - printed += fprintf(fp, " %8.3f %6.2f\n", avg, pct); + n, min, avg); + printed += fprintf(fp, " %8.3f %6.2f\n", max, pct); } inode = intlist__next(inode); -- cgit v1.2.3-18-g5258 From 99ff7150547382ee612c40d8d6a0670ddec7c9fc Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 12 Nov 2013 16:42:14 +0200 Subject: perf trace: Simplify '--summary' output The output of 'perf trace --summary' tries to be too cute with formatting and makes it very hard to read. Simplify it in the spirit of "strace -c": [penberg@localhost libtrading]$ perf trace -a --duration 10000 --summary -- sleep 1 ^C Summary of events: dbus-daemon (555), 10 events, 0.0%, 0.000 msec msec/call syscall calls min avg max stddev --------------- -------- -------- -------- -------- ------ sendmsg 2 0.002 0.005 0.008 55.00 recvmsg 2 0.002 0.003 0.005 44.00 epoll_wait 1 0.000 0.000 0.000 0.00 NetworkManager (667), 56 events, 0.0%, 0.000 msec msec/call syscall calls min avg max stddev --------------- -------- -------- -------- -------- ------ poll 2 0.000 0.002 0.003 100.00 sendmsg 10 0.004 0.007 0.016 15.41 recvmsg 16 0.002 0.003 0.005 8.24 zfs-fuse (669), 4 events, 0.0%, 0.000 msec msec/call syscall calls min avg max stddev --------------- -------- -------- -------- -------- ------ futex 2 0.000 0.001 0.002 100.00 Signed-off-by: Pekka Enberg Cc: David Ahern Cc: Ingo Molnar Link: http://lkml.kernel.org/r/1384267334-18953-1-git-send-email-penberg@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8990fbeb8b4..0964c0cdc98 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2090,12 +2090,7 @@ static size_t trace__fprintf_threads_header(FILE *fp) { size_t printed; - printed = fprintf(fp, "\n _____________________________________________________________________________\n"); - printed += fprintf(fp, " __) Summary of events (__\n\n"); - printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); - printed += fprintf(fp, " syscall count min avg max stddev\n"); - printed += fprintf(fp, " msec msec msec %%\n"); - printed += fprintf(fp, " _____________________________________________________________________________\n\n"); + printed = fprintf(fp, "\n Summary of events:\n\n"); return printed; } @@ -2113,6 +2108,10 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, printed += fprintf(fp, "\n"); + printed += fprintf(fp, " msec/call\n"); + printed += fprintf(fp, " syscall calls min avg max stddev\n"); + printed += fprintf(fp, " --------------- -------- -------- -------- -------- ------\n"); + /* each int_node is a syscall */ while (inode) { stats = inode->priv; @@ -2127,10 +2126,10 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, avg /= NSEC_PER_MSEC; sc = &trace->syscalls.table[inode->i]; - printed += fprintf(fp, "%24s %14s : ", "", sc->name); - printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f", + printed += fprintf(fp, " %-15s", sc->name); + printed += fprintf(fp, " %8" PRIu64 " %8.3f %8.3f", n, min, avg); - printed += fprintf(fp, " %8.3f %6.2f\n", max, pct); + printed += fprintf(fp, " %8.3f %6.2f\n", max, pct); } inode = intlist__next(inode); @@ -2171,10 +2170,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) else if (ratio > 5.0) color = PERF_COLOR_YELLOW; - printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread)); - printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events); - printed += color_fprintf(fp, color, "%5.1f%%", ratio); - printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms); + printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid); + printed += fprintf(fp, "%lu events, ", ttrace->nr_events); + printed += color_fprintf(fp, color, "%.1f%%", ratio); + printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); printed += thread__dump_stats(ttrace, trace, fp); data->printed += printed; -- cgit v1.2.3-18-g5258 From fd2eabaf16984bc75695e43f4b76e6f20ed4ea41 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 12 Nov 2013 09:31:15 -0700 Subject: perf trace: Add summary only option Per request from Pekka make --summary a summary only option meaning do not show the individual system calls. Add another option to see all syscalls along with the summary. In addition use 's' and 'S' as shortcuts for the options. Requested-by: Pekka Enberg Signed-off-by: David Ahern Tested-by: Pekka Enberg Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Pekka Enberg Link: http://lkml.kernel.org/r/1384273875-3751-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 10 ++++++++-- tools/perf/builtin-trace.c | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 7b0497f95a7..fae38d9a44a 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -93,9 +93,15 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. --comm:: Show process COMM right beside its ID, on by default, disable with --no-comm. +-s:: --summary:: - Show a summary of syscalls by thread with min, max, and average times (in - msec) and relative stddev. + Show only a summary of syscalls by thread with min, max, and average times + (in msec) and relative stddev. + +-S:: +--with-summary:: + Show all syscalls followed by a summary by thread with min, max, and + average times (in msec) and relative stddev. --tool_stats:: Show tool stats such as number of times fd->pathname was discovered thru diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0964c0cdc98..aa5702ffa2c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1168,6 +1168,7 @@ struct trace { bool sched; bool multiple_threads; bool summary; + bool summary_only; bool show_comm; bool show_tool_stats; double duration_filter; @@ -1611,7 +1612,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, args, trace, thread); if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { - if (!trace->duration_filter) { + if (!trace->duration_filter && !trace->summary_only) { trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); fprintf(trace->output, "%-70s\n", ttrace->entry_str); } @@ -1664,6 +1665,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, } else if (trace->durat