diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-02-27 17:52:10 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-03-02 09:51:30 -0500 |
commit | 4aa5f4f7bb8bc41cba15bcd0d80c4fb085027d6b (patch) | |
tree | c9784c07fefab20f57a43201fa758d55ce11c4f9 /tools/perf/util/event.c | |
parent | 3b4331d9a4f2d99603c38bfcac79943b7c6c5439 (diff) |
perf tools: Fix FORK after COMM when synthesizing records for pre-existing threads
In this commit:
commit 363b785f3805a2632eb09a8b430842461c21a640
Author: Don Zickus <dzickus@redhat.com>
Date: Fri Mar 14 10:43:44 2014 -0400
perf tools: Speed up thread map generation
We ended up emitting PERF_RECORD_FORK events after their corresponding
PERF_RECORD_COMM, so the code below will remove the "existing thread"
and then recreates it, unnecessarily:
[root@ssdandy ~]# perf probe -x ~/bin/perf -L machine__process_fork_event
<machine__process_fork_event@/home/acme/git/linux/tools/perf/util/machine.c:0>
0 int machine__process_fork_event(struct machine *machine, union perf_event *event,
struct perf_sample *sample)
2 {
3 struct thread *thread = machine__find_thread(machine,
event->fork.pid,
event->fork.tid);
6 struct thread *parent = machine__findnew_thread(machine,
event->fork.ppid,
event->fork.ptid);
/* if a thread currently exists for the thread id remove it */
if (thread != NULL)
12 machine__remove_thread(machine, thread);
14 thread = machine__findnew_thread(machine, event->fork.pid,
event->fork.tid);
16 if (dump_trace)
17 perf_event__fprintf_task(event, stdout);
19 if (thread == NULL || parent == NULL ||
20 thread__fork(thread, parent, sample->time) < 0) {
21 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
22 return -1;
}
25 return 0;
26 }
[root@ssdandy ~]# perf probe -x ~/bin/perf fork_after_comm=machine__process_fork_event:12
Added new event:
probe_perf:fork_after_comm (on machine__process_fork_event:12 in /home/acme/bin/perf)
You can now use it in all perf tools, such as:
perf record -e probe_perf:fork_after_comm -aR sleep 1
[root@ssdandy ~]#
[root@ssdandy ~]# perf record -g -e probe_perf:* trace -o /tmp/bla
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.021 MB perf.data (30 samples) ]
Terminated
[root@ssdandy ~]#
[root@ssdandy ~]# perf report --no-children --show-total-period --stdio
# To display the perf.data header info, please use --header/--header-only options.
#
# Samples: 30 of event 'probe_perf:fork_after_comm'
# Event count (approx.): 30
#
# Overhead Period Command Shared Object Symbol
# ........ ............ ....... ............. ...............................
#
100.00% 30 trace trace [.] machine__process_fork_event
|
---machine__process_fork_event
__event__synthesize_thread.part.2
perf_event__synthesize_threads
cmd_trace
main
__libc_start_main
[root@ssdandy ~]#
And Looking at 'perf report -D' output we see it:
0 0 0x8698 [0x30]: PERF_RECORD_COMM: auditd:703/707
0 0 0x86c8 [0x38]: PERF_RECORD_FORK(703:707):(703:703)
Fix it by more closely mimicking how the kernel generates those records
when a new fork happens, i.e. first a PERF_RECORD_FORK, then a
PERF_RECORD_COMM.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-h0emvymi2t3mw8dlqd6d6z73@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r-- | tools/perf/util/event.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 9e806d855b04..d5efa5092ce6 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -95,9 +95,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | |||
95 | return tgid; | 95 | return tgid; |
96 | } | 96 | } |
97 | 97 | ||
98 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | 98 | static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, |
99 | union perf_event *event, pid_t pid, | ||
100 | perf_event__handler_t process, | ||
101 | struct machine *machine) | 99 | struct machine *machine) |
102 | { | 100 | { |
103 | size_t size; | 101 | size_t size; |
@@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
124 | (sizeof(event->comm.comm) - size) + | 122 | (sizeof(event->comm.comm) - size) + |
125 | machine->id_hdr_size); | 123 | machine->id_hdr_size); |
126 | event->comm.tid = pid; | 124 | event->comm.tid = pid; |
125 | out: | ||
126 | return tgid; | ||
127 | } | ||
128 | |||
129 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | ||
130 | union perf_event *event, pid_t pid, | ||
131 | perf_event__handler_t process, | ||
132 | struct machine *machine) | ||
133 | { | ||
134 | pid_t tgid = perf_event__prepare_comm(event, pid, machine); | ||
135 | |||
136 | if (tgid == -1) | ||
137 | goto out; | ||
127 | 138 | ||
128 | if (process(tool, event, &synth_sample, machine) != 0) | 139 | if (process(tool, event, &synth_sample, machine) != 0) |
129 | return -1; | 140 | return -1; |
@@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool, | |||
139 | { | 150 | { |
140 | memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); | 151 | memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); |
141 | 152 | ||
142 | /* this is really a clone event but we use fork to synthesize it */ | ||
143 | event->fork.ppid = tgid; | 153 | event->fork.ppid = tgid; |
144 | event->fork.ptid = tgid; | 154 | event->fork.ptid = tgid; |
145 | event->fork.pid = tgid; | 155 | event->fork.pid = tgid; |
@@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event, | |||
368 | if (*end) | 378 | if (*end) |
369 | continue; | 379 | continue; |
370 | 380 | ||
371 | tgid = perf_event__synthesize_comm(tool, comm_event, _pid, | 381 | tgid = perf_event__prepare_comm(comm_event, _pid, machine); |
372 | process, machine); | ||
373 | if (tgid == -1) | 382 | if (tgid == -1) |
374 | return -1; | 383 | return -1; |
375 | 384 | ||
385 | if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, | ||
386 | process, machine) < 0) | ||
387 | return -1; | ||
388 | /* | ||
389 | * Send the prepared comm event | ||
390 | */ | ||
391 | if (process(tool, comm_event, &synth_sample, machine) != 0) | ||
392 | return -1; | ||
393 | |||
376 | if (_pid == pid) { | 394 | if (_pid == pid) { |
377 | /* process the parent's maps too */ | 395 | /* process the parent's maps too */ |
378 | rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, | 396 | rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, |
379 | process, machine, mmap_data); | 397 | process, machine, mmap_data); |
380 | } else { | ||
381 | /* only fork the tid's map, to save time */ | ||
382 | rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid, | ||
383 | process, machine); | ||
384 | } | 398 | } |
385 | 399 | ||
386 | if (rc) | 400 | if (rc) |