mirror of https://gitee.com/openkylin/linux.git
perf tools: Fix FORK after COMM when synthesizing records for pre-existing threads
In this commit:
commit 363b785f38
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>
This commit is contained in:
parent
3b4331d9a4
commit
4aa5f4f7bb
|
@ -95,9 +95,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
|
|||
return tgid;
|
||||
}
|
||||
|
||||
static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
|
||||
union perf_event *event, pid_t pid,
|
||||
perf_event__handler_t process,
|
||||
static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
|
||||
struct machine *machine)
|
||||
{
|
||||
size_t size;
|
||||
|
@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
|
|||
(sizeof(event->comm.comm) - size) +
|
||||
machine->id_hdr_size);
|
||||
event->comm.tid = pid;
|
||||
out:
|
||||
return tgid;
|
||||
}
|
||||
|
||||
static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
|
||||
union perf_event *event, pid_t pid,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
{
|
||||
pid_t tgid = perf_event__prepare_comm(event, pid, machine);
|
||||
|
||||
if (tgid == -1)
|
||||
goto out;
|
||||
|
||||
if (process(tool, event, &synth_sample, machine) != 0)
|
||||
return -1;
|
||||
|
@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
|
|||
{
|
||||
memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
|
||||
|
||||
/* this is really a clone event but we use fork to synthesize it */
|
||||
event->fork.ppid = tgid;
|
||||
event->fork.ptid = tgid;
|
||||
event->fork.pid = tgid;
|
||||
|
@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event,
|
|||
if (*end)
|
||||
continue;
|
||||
|
||||
tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
|
||||
process, machine);
|
||||
tgid = perf_event__prepare_comm(comm_event, _pid, machine);
|
||||
if (tgid == -1)
|
||||
return -1;
|
||||
|
||||
if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
|
||||
process, machine) < 0)
|
||||
return -1;
|
||||
/*
|
||||
* Send the prepared comm event
|
||||
*/
|
||||
if (process(tool, comm_event, &synth_sample, machine) != 0)
|
||||
return -1;
|
||||
|
||||
if (_pid == pid) {
|
||||
/* process the parent's maps too */
|
||||
rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
|
||||
process, machine, mmap_data);
|
||||
} else {
|
||||
/* only fork the tid's map, to save time */
|
||||
rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
|
||||
process, machine);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
|
|
Loading…
Reference in New Issue