* [PATCH 0/3] perf per-task-per-cpu support
@ 2009-12-16 16:55 Peter Zijlstra
2009-12-16 16:55 ` [PATCH 1/3] perf: Allow per-task-per-cpu counters Peter Zijlstra
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Peter Zijlstra @ 2009-12-16 16:55 UTC (permalink / raw)
To: Ingo Molnar, Paul Mackerras
Cc: Arnaldo Carvalho de Melo, fweisbec, linux-kernel, Peter Zijlstra
Its not the most elegant solution, but it does seem to work.
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/3] perf: Allow per-task-per-cpu counters 2009-12-16 16:55 [PATCH 0/3] perf per-task-per-cpu support Peter Zijlstra @ 2009-12-16 16:55 ` Peter Zijlstra 2009-12-16 17:34 ` [tip:perf/urgent] perf events: " tip-bot for Peter Zijlstra 2009-12-16 16:55 ` [PATCH 2/3] perf-record: Properly synchronize child creation Peter Zijlstra 2009-12-16 16:55 ` [PATCH 3/3] perf-record: Use per-task-per-cpu events for inherited events Peter Zijlstra 2 siblings, 1 reply; 7+ messages in thread From: Peter Zijlstra @ 2009-12-16 16:55 UTC (permalink / raw) To: Ingo Molnar, Paul Mackerras Cc: Arnaldo Carvalho de Melo, fweisbec, linux-kernel, Peter Zijlstra [-- Attachment #1: perf1.patch --] [-- Type: text/plain, Size: 1755 bytes --] In order to allow for per-task-per-cpu counters, useful for scalability when profiling task hierarchies, we allow installing events with event->cpu != -1 in task contexts. __perf_event_sched_in() already skips events where ->cpu mis-matches the current cpu, fix up __perf_install_in_context() and __perf_event_enable() to also respect this filter. This does lead to vary hard to interpret enabled/running times for such counters, but I don't see a simple solution for that. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> --- kernel/perf_event.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) Index: linux-2.6/kernel/perf_event.c =================================================================== --- linux-2.6.orig/kernel/perf_event.c +++ linux-2.6/kernel/perf_event.c @@ -782,6 +782,9 @@ static void __perf_install_in_context(vo add_event_to_ctx(event, ctx); + if (event->cpu != -1 && event->cpu != smp_processor_id()) + goto unlock; + /* * Don't put the event on if it is disabled or if * it is in a group and the group isn't on. @@ -925,6 +928,9 @@ static void __perf_event_enable(void *in goto unlock; __perf_event_mark_enabled(event, ctx); + if (event->cpu != -1 && event->cpu != smp_processor_id()) + goto unlock; + /* * If the event is in a group and isn't the group leader, * then don't put it on unless the group is on. @@ -1595,10 +1601,7 @@ static struct perf_event_context *find_g unsigned long flags; int err; - /* - * If cpu is not a wildcard then this is a percpu event: - */ - if (cpu != -1) { + if (pid == -1 && cpu != -1) { /* Must be root to operate on a CPU event: */ if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) return ERR_PTR(-EACCES); -- ^ permalink raw reply [flat|nested] 7+ messages in thread
* [tip:perf/urgent] perf events: Allow per-task-per-cpu counters 2009-12-16 16:55 ` [PATCH 1/3] perf: Allow per-task-per-cpu counters Peter Zijlstra @ 2009-12-16 17:34 ` tip-bot for Peter Zijlstra 0 siblings, 0 replies; 7+ messages in thread From: tip-bot for Peter Zijlstra @ 2009-12-16 17:34 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, paulus, acme, hpa, mingo, a.p.zijlstra, tglx, mingo Commit-ID: f4c4176f21533e22bcc292030da72bcfa105f5b8 Gitweb: http://git.kernel.org/tip/f4c4176f21533e22bcc292030da72bcfa105f5b8 Author: Peter Zijlstra <a.p.zijlstra@chello.nl> AuthorDate: Wed, 16 Dec 2009 17:55:54 +0100 Committer: Ingo Molnar <mingo@elte.hu> CommitDate: Wed, 16 Dec 2009 18:30:11 +0100 perf events: Allow per-task-per-cpu counters In order to allow for per-task-per-cpu counters, useful for scalability when profiling task hierarchies, we allow installing events with event->cpu != -1 in task contexts. __perf_event_sched_in() already skips events where ->cpu mis-matches the current cpu, fix up __perf_install_in_context() and __perf_event_enable() to also respect this filter. This does lead to vary hard to interpret enabled/running times for such counters, but I don't see a simple solution for that. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: fweisbec@gmail.com Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <20091216165904.831451147@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/perf_event.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 0dd8e5d..2e0aaa3 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -782,6 +782,9 @@ static void __perf_install_in_context(void *info) add_event_to_ctx(event, ctx); + if (event->cpu != -1 && event->cpu != smp_processor_id()) + goto unlock; + /* * Don't put the event on if it is disabled or if * it is in a group and the group isn't on. @@ -925,6 +928,9 @@ static void __perf_event_enable(void *info) goto unlock; __perf_event_mark_enabled(event, ctx); + if (event->cpu != -1 && event->cpu != smp_processor_id()) + goto unlock; + /* * If the event is in a group and isn't the group leader, * then don't put it on unless the group is on. @@ -1595,10 +1601,7 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu) unsigned long flags; int err; - /* - * If cpu is not a wildcard then this is a percpu event: - */ - if (cpu != -1) { + if (pid == -1 && cpu != -1) { /* Must be root to operate on a CPU event: */ if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) return ERR_PTR(-EACCES); ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] perf-record: Properly synchronize child creation 2009-12-16 16:55 [PATCH 0/3] perf per-task-per-cpu support Peter Zijlstra 2009-12-16 16:55 ` [PATCH 1/3] perf: Allow per-task-per-cpu counters Peter Zijlstra @ 2009-12-16 16:55 ` Peter Zijlstra 2009-12-16 17:34 ` [tip:perf/urgent] perf record: " tip-bot for Peter Zijlstra 2009-12-16 16:55 ` [PATCH 3/3] perf-record: Use per-task-per-cpu events for inherited events Peter Zijlstra 2 siblings, 1 reply; 7+ messages in thread From: Peter Zijlstra @ 2009-12-16 16:55 UTC (permalink / raw) To: Ingo Molnar, Paul Mackerras Cc: Arnaldo Carvalho de Melo, fweisbec, linux-kernel, Peter Zijlstra [-- Attachment #1: perf2.patch --] [-- Type: text/plain, Size: 4136 bytes --] Remove that ugly usleep and provide proper serialization between parent and child just like perf-stat does. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> --- tools/perf/builtin-record.c | 111 ++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 39 deletions(-) Index: linux-2.6/tools/perf/builtin-record.c =================================================================== --- linux-2.6.orig/tools/perf/builtin-record.c +++ linux-2.6/tools/perf/builtin-record.c @@ -402,7 +402,7 @@ static void atexit_header(void) perf_header__write(&session->header, output, true); } -static int __cmd_record(int argc, const char **argv) +static int __cmd_record(int argc __used, const char **argv) { int i, counter; struct stat st; @@ -410,6 +410,8 @@ static int __cmd_record(int argc, const int flags; int err; unsigned long waking = 0; + int child_ready_pipe[2], go_pipe[2]; + char buf; page_size = sysconf(_SC_PAGE_SIZE); nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -420,6 +422,11 @@ static int __cmd_record(int argc, const signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); + if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { + perror("failed to create pipes"); + exit(-1); + } + if (!stat(output_name, &st) && st.st_size) { if (!force) { if (!append_file) { @@ -476,19 +483,65 @@ static int __cmd_record(int argc, const atexit(atexit_header); - if (!system_wide) { - pid = target_pid; - if (pid == -1) - pid = getpid(); + if (target_pid == -1) { + pid = fork(); + if (pid < 0) { + perror("failed to fork"); + exit(-1); + } - open_counters(profile_cpu, pid); - } else { - if (profile_cpu != -1) { - open_counters(profile_cpu, target_pid); - } else { - for (i = 0; i < nr_cpus; i++) - open_counters(i, target_pid); + if (!pid) { + close(child_ready_pipe[0]); + close(go_pipe[1]); + fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); + + /* + * Do a dummy execvp to get the PLT entry resolved, + * so we avoid the resolver overhead on the real + * execvp call. + */ + execvp("", (char **)argv); + + /* + * Tell the parent we're ready to go + */ + close(child_ready_pipe[1]); + + /* + * Wait until the parent tells us to go. + */ + if (read(go_pipe[0], &buf, 1) == -1) + perror("unable to read pipe"); + + execvp(argv[0], (char **)argv); + + perror(argv[0]); + exit(-1); } + + child_pid = pid; + + if (!system_wide) + target_pid = pid; + + close(child_ready_pipe[1]); + close(go_pipe[0]); + /* + * wait for child to settle + */ + if (read(child_ready_pipe[0], &buf, 1) == -1) { + perror("unable to read pipe"); + exit(-1); + } + close(child_ready_pipe[0]); + } + + + if (!system_wide || profile_cpu != -1) { + open_counters(profile_cpu, target_pid); + } else { + for (i = 0; i < nr_cpus; i++) + open_counters(i, target_pid); } if (file_new) { @@ -503,31 +556,6 @@ static int __cmd_record(int argc, const else event__synthesize_threads(process_synthesized_event, session); - if (target_pid == -1 && argc) { - pid = fork(); - if (pid < 0) - die("failed to fork"); - - if (!pid) { - if (execvp(argv[0], (char **)argv)) { - perror(argv[0]); - exit(-1); - } - } else { - /* - * Wait a bit for the execv'ed child to appear - * and be updated in /proc - * FIXME: Do you know a less heuristical solution? - */ - usleep(1000); - event__synthesize_thread(pid, - process_synthesized_event, - session); - } - - child_pid = pid; - } - if (realtime_prio) { struct sched_param param; @@ -538,6 +566,11 @@ static int __cmd_record(int argc, const } } + /* + * Let the child rip + */ + close(go_pipe[1]); + for (;;) { int hits = samples; @@ -634,7 +667,7 @@ int cmd_record(int argc, const char **ar argc = parse_options(argc, argv, options, record_usage, PARSE_OPT_STOP_AT_NON_OPTION); - if (!argc && target_pid == -1 && !system_wide) + if (!argc && target_pid == -1 && (!system_wide || profile_cpu == -1)) usage_with_options(record_usage, options); symbol__init(); -- ^ permalink raw reply [flat|nested] 7+ messages in thread
* [tip:perf/urgent] perf record: Properly synchronize child creation 2009-12-16 16:55 ` [PATCH 2/3] perf-record: Properly synchronize child creation Peter Zijlstra @ 2009-12-16 17:34 ` tip-bot for Peter Zijlstra 0 siblings, 0 replies; 7+ messages in thread From: tip-bot for Peter Zijlstra @ 2009-12-16 17:34 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, paulus, acme, hpa, mingo, a.p.zijlstra, tglx, mingo Commit-ID: 856e96608a72412d319e498a3a7c557571f811bd Gitweb: http://git.kernel.org/tip/856e96608a72412d319e498a3a7c557571f811bd Author: Peter Zijlstra <a.p.zijlstra@chello.nl> AuthorDate: Wed, 16 Dec 2009 17:55:55 +0100 Committer: Ingo Molnar <mingo@elte.hu> CommitDate: Wed, 16 Dec 2009 18:30:12 +0100 perf record: Properly synchronize child creation Remove that ugly usleep and provide proper serialization between parent and child just like perf-stat does. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: fweisbec@gmail.com Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <20091216165904.908184135@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-record.c | 109 ++++++++++++++++++++++++++++--------------- 1 files changed, 71 insertions(+), 38 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 65301c5..9b7c6d8 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -402,7 +402,7 @@ static void atexit_header(void) perf_header__write(&session->header, output, true); } -static int __cmd_record(int argc, const char **argv) +static int __cmd_record(int argc __used, const char **argv) { int i, counter; struct stat st; @@ -410,6 +410,8 @@ static int __cmd_record(int argc, const char **argv) int flags; int err; unsigned long waking = 0; + int child_ready_pipe[2], go_pipe[2]; + char buf; page_size = sysconf(_SC_PAGE_SIZE); nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -420,6 +422,11 @@ static int __cmd_record(int argc, const char **argv) signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); + if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { + perror("failed to create pipes"); + exit(-1); + } + if (!stat(output_name, &st) && st.st_size) { if (!force) { if (!append_file) { @@ -476,19 +483,65 @@ static int __cmd_record(int argc, const char **argv) atexit(atexit_header); - if (!system_wide) { - pid = target_pid; - if (pid == -1) - pid = getpid(); + if (target_pid == -1) { + pid = fork(); + if (pid < 0) { + perror("failed to fork"); + exit(-1); + } - open_counters(profile_cpu, pid); - } else { - if (profile_cpu != -1) { - open_counters(profile_cpu, target_pid); - } else { - for (i = 0; i < nr_cpus; i++) - open_counters(i, target_pid); + if (!pid) { + close(child_ready_pipe[0]); + close(go_pipe[1]); + fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); + + /* + * Do a dummy execvp to get the PLT entry resolved, + * so we avoid the resolver overhead on the real + * execvp call. + */ + execvp("", (char **)argv); + + /* + * Tell the parent we're ready to go + */ + close(child_ready_pipe[1]); + + /* + * Wait until the parent tells us to go. + */ + if (read(go_pipe[0], &buf, 1) == -1) + perror("unable to read pipe"); + + execvp(argv[0], (char **)argv); + + perror(argv[0]); + exit(-1); } + + child_pid = pid; + + if (!system_wide) + target_pid = pid; + + close(child_ready_pipe[1]); + close(go_pipe[0]); + /* + * wait for child to settle + */ + if (read(child_ready_pipe[0], &buf, 1) == -1) { + perror("unable to read pipe"); + exit(-1); + } + close(child_ready_pipe[0]); + } + + + if (!system_wide || profile_cpu != -1) { + open_counters(profile_cpu, target_pid); + } else { + for (i = 0; i < nr_cpus; i++) + open_counters(i, target_pid); } if (file_new) { @@ -503,31 +556,6 @@ static int __cmd_record(int argc, const char **argv) else event__synthesize_threads(process_synthesized_event, session); - if (target_pid == -1 && argc) { - pid = fork(); - if (pid < 0) - die("failed to fork"); - - if (!pid) { - if (execvp(argv[0], (char **)argv)) { - perror(argv[0]); - exit(-1); - } - } else { - /* - * Wait a bit for the execv'ed child to appear - * and be updated in /proc - * FIXME: Do you know a less heuristical solution? - */ - usleep(1000); - event__synthesize_thread(pid, - process_synthesized_event, - session); - } - - child_pid = pid; - } - if (realtime_prio) { struct sched_param param; @@ -538,6 +566,11 @@ static int __cmd_record(int argc, const char **argv) } } + /* + * Let the child rip + */ + close(go_pipe[1]); + for (;;) { int hits = samples; @@ -634,7 +667,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) argc = parse_options(argc, argv, options, record_usage, PARSE_OPT_STOP_AT_NON_OPTION); - if (!argc && target_pid == -1 && !system_wide) + if (!argc && target_pid == -1 && (!system_wide || profile_cpu == -1)) usage_with_options(record_usage, options); symbol__init(); ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] perf-record: Use per-task-per-cpu events for inherited events 2009-12-16 16:55 [PATCH 0/3] perf per-task-per-cpu support Peter Zijlstra 2009-12-16 16:55 ` [PATCH 1/3] perf: Allow per-task-per-cpu counters Peter Zijlstra 2009-12-16 16:55 ` [PATCH 2/3] perf-record: Properly synchronize child creation Peter Zijlstra @ 2009-12-16 16:55 ` Peter Zijlstra 2009-12-16 17:34 ` [tip:perf/urgent] perf record: " tip-bot for Peter Zijlstra 2 siblings, 1 reply; 7+ messages in thread From: Peter Zijlstra @ 2009-12-16 16:55 UTC (permalink / raw) To: Ingo Molnar, Paul Mackerras Cc: Arnaldo Carvalho de Melo, fweisbec, linux-kernel, Peter Zijlstra [-- Attachment #1: perf3.patch --] [-- Type: text/plain, Size: 974 bytes --] Create events with a pid and cpu contraint for inherited events so that we get a stream per cpu, instead of all cpus contending on a single stream. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> --- tools/perf/builtin-record.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: linux-2.6/tools/perf/builtin-record.c =================================================================== --- linux-2.6.orig/tools/perf/builtin-record.c +++ linux-2.6/tools/perf/builtin-record.c @@ -278,7 +278,7 @@ static void create_counter(int counter, attr->mmap = track; attr->comm = track; - attr->inherit = (cpu < 0) && inherit; + attr->inherit = inherit; attr->disabled = 1; try_again: @@ -537,7 +537,7 @@ static int __cmd_record(int argc __used, } - if (!system_wide || profile_cpu != -1) { + if ((!system_wide && !inherit) || profile_cpu != -1) { open_counters(profile_cpu, target_pid); } else { for (i = 0; i < nr_cpus; i++) -- ^ permalink raw reply [flat|nested] 7+ messages in thread
* [tip:perf/urgent] perf record: Use per-task-per-cpu events for inherited events 2009-12-16 16:55 ` [PATCH 3/3] perf-record: Use per-task-per-cpu events for inherited events Peter Zijlstra @ 2009-12-16 17:34 ` tip-bot for Peter Zijlstra 0 siblings, 0 replies; 7+ messages in thread From: tip-bot for Peter Zijlstra @ 2009-12-16 17:34 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, paulus, acme, hpa, mingo, a.p.zijlstra, tglx, mingo Commit-ID: 60ab271617cec607380099f3ed8e84916e48323b Gitweb: http://git.kernel.org/tip/60ab271617cec607380099f3ed8e84916e48323b Author: Peter Zijlstra <a.p.zijlstra@chello.nl> AuthorDate: Wed, 16 Dec 2009 17:55:56 +0100 Committer: Ingo Molnar <mingo@elte.hu> CommitDate: Wed, 16 Dec 2009 18:30:13 +0100 perf record: Use per-task-per-cpu events for inherited events Create events with a pid and cpu contraint for inherited events so that we get a stream per cpu, instead of all cpus contending on a single stream. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: fweisbec@gmail.com Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <20091216165904.987643843@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-record.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 9b7c6d8..63136d0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -278,7 +278,7 @@ static void create_counter(int counter, int cpu, pid_t pid) attr->mmap = track; attr->comm = track; - attr->inherit = (cpu < 0) && inherit; + attr->inherit = inherit; attr->disabled = 1; try_again: @@ -537,7 +537,7 @@ static int __cmd_record(int argc __used, const char **argv) } - if (!system_wide || profile_cpu != -1) { + if ((!system_wide && !inherit) || profile_cpu != -1) { open_counters(profile_cpu, target_pid); } else { for (i = 0; i < nr_cpus; i++) ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-12-16 17:37 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-12-16 16:55 [PATCH 0/3] perf per-task-per-cpu support Peter Zijlstra 2009-12-16 16:55 ` [PATCH 1/3] perf: Allow per-task-per-cpu counters Peter Zijlstra 2009-12-16 17:34 ` [tip:perf/urgent] perf events: " tip-bot for Peter Zijlstra 2009-12-16 16:55 ` [PATCH 2/3] perf-record: Properly synchronize child creation Peter Zijlstra 2009-12-16 17:34 ` [tip:perf/urgent] perf record: " tip-bot for Peter Zijlstra 2009-12-16 16:55 ` [PATCH 3/3] perf-record: Use per-task-per-cpu events for inherited events Peter Zijlstra 2009-12-16 17:34 ` [tip:perf/urgent] perf record: " tip-bot for Peter Zijlstra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®