* [PATCH 0/3] perf: Teach perf tool to profile sleep times
@ 2012-08-06 10:01 Andrew Vagin
2012-08-06 10:01 ` [PATCH 1/3] perf: teach "perf inject" to work with files Andrew Vagin
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Andrew Vagin @ 2012-08-06 10:01 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo
This functionality helps to analize where a task sleeps or waits locks.
This feature can help to investigate a scalability problems.
The main idea is that we can combine sched_switch and sched_stat_sleep events.
sched_switch contains a callchain, when a task starts sleeping.
sched_stat_sleep contains a time period for which a task slept.
This series teaches "perf inject" to combine this events.
All kernel related patches were committed committed in 3.6-rc1.
Here is an example of a report:
$ cat ~/foo.c
....
for (i = 0; i < 10; i++) {
ts1.tv_sec = 0;
ts1.tv_nsec = 10000000;
nanosleep(&ts1, NULL);
tv1.tv_sec = 0;
tv1.tv_usec = 40000;
select(0, NULL, NULL, NULL,&tv1);
}
...
$ ./perf record -e sched:sched_stat_sleep -e sched:sched_switch \
-e sched:sched_process_exit -gP -o ~/perf.data.raw ~/foo
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.015 MB /root/perf.data.raw (~661 samples) ]
$ ./perf inject -v -s -i ~/perf.data.raw -o ~/perf.data
$ ./perf report -i ~/perf.data
# Samples: 40 of event 'sched:sched_switch'
# Event count (approx.): 1005527702
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. ..............
#
100.00% foo [kernel.kallsyms] [k] __schedule
|
--- __schedule
schedule
|
|--79.81%-- schedule_hrtimeout_range_clock
| schedule_hrtimeout_range
| poll_schedule_timeout
| do_select
| core_sys_select
| sys_select
| system_call_fastpath
| __select
| __libc_start_main
|
--20.19%-- do_nanosleep
hrtimer_nanosleep
sys_nanosleep
system_call_fastpath
__GI___libc_nanosleep
__libc_start_main
Andrew Vagin (3):
perf: teach "perf inject" to work with files
perf: teach perf inject to merge sched_stat_* and sched_switch events
perf: mark a dso if it's used
tools/perf/builtin-inject.c | 139 ++++++++++++++++++++++++++++++++++++++++---
tools/perf/util/build-id.c | 2 +-
tools/perf/util/build-id.h | 5 ++
3 files changed, 137 insertions(+), 9 deletions(-)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/3] perf: teach "perf inject" to work with files
2012-08-06 10:01 [PATCH 0/3] perf: Teach perf tool to profile sleep times Andrew Vagin
@ 2012-08-06 10:01 ` Andrew Vagin
2012-08-06 18:12 ` Arnaldo Carvalho de Melo
2012-08-06 10:01 ` [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events Andrew Vagin
2012-08-06 10:01 ` [PATCH 3/3] perf: mark a dso if it's used Andrew Vagin
2 siblings, 1 reply; 12+ messages in thread
From: Andrew Vagin @ 2012-08-06 10:01 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo
Before this patch "perf inject" can only handle data from pipe.
I want to use "perf inject" for reworking events. Look at my following patch.
Signed-off-by: Andrew Vagin <avagin@openvz.org>
---
tools/perf/builtin-inject.c | 33 +++++++++++++++++++++++++++++++--
1 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 3beab48..d04b7a4 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -14,7 +14,12 @@
#include "util/parse-options.h"
-static char const *input_name = "-";
+static char const *input_name = "-";
+static const char *output_name = "-";
+static int pipe_output;
+static int output;
+static u64 bytes_written;
+
static bool inject_build_ids;
static int perf_event__repipe_synth(struct perf_tool *tool __used,
@@ -27,12 +32,14 @@ static int perf_event__repipe_synth(struct perf_tool *tool __used,
size = event->header.size;
while (size) {
- int ret = write(STDOUT_FILENO, buf, size);
+ int ret = write(output, buf, size);
if (ret < 0)
return -errno;
size -= ret;
buf += ret;
+
+ bytes_written += ret;
}
return 0;
@@ -244,8 +251,14 @@ static int __cmd_inject(void)
if (session == NULL)
return -ENOMEM;
+ if (!pipe_output)
+ lseek(output, session->header.data_offset, SEEK_SET);
ret = perf_session__process_events(session, &perf_inject);
+ if (!pipe_output) {
+ session->header.data_size = bytes_written;
+ perf_session__write_header(session, session->evlist, output, true);
+ }
perf_session__delete(session);
return ret;
@@ -259,6 +272,10 @@ static const char * const report_usage[] = {
static const struct option options[] = {
OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
"Inject build-ids into the output stream"),
+ OPT_STRING('i', "input", &input_name, "file",
+ "input file name"),
+ OPT_STRING('o', "output", &output_name, "file",
+ "output file name"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show build ids, etc)"),
OPT_END()
@@ -274,6 +291,18 @@ int cmd_inject(int argc, const char **argv, const char *prefix __used)
if (argc)
usage_with_options(report_usage, options);
+ if (!strcmp(output_name, "-")) {
+ pipe_output = 1;
+ output = STDOUT_FILENO;
+ } else {
+ output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC,
+ S_IRUSR | S_IWUSR);
+ if (output < 0) {
+ perror("failed to create output file");
+ exit(-1);
+ }
+ }
+
if (symbol__init() < 0)
return -1;
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events
2012-08-06 10:01 [PATCH 0/3] perf: Teach perf tool to profile sleep times Andrew Vagin
2012-08-06 10:01 ` [PATCH 1/3] perf: teach "perf inject" to work with files Andrew Vagin
@ 2012-08-06 10:01 ` Andrew Vagin
2012-08-06 18:19 ` Arnaldo Carvalho de Melo
2012-08-06 10:01 ` [PATCH 3/3] perf: mark a dso if it's used Andrew Vagin
2 siblings, 1 reply; 12+ messages in thread
From: Andrew Vagin @ 2012-08-06 10:01 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo
You may want to know where and how long a task is sleeping. A callchain
may be found in sched_switch and a time slice in stat_iowait, so I add
handler in perf inject for merging this events.
My code saves sched_switch event for each process and when it meets
stat_iowait, it reports the sched_switch event, because this event
contains a correct callchain. By another words it replaces all
stat_iowait events on proper sched_switch events.
Signed-off-by: Andrew Vagin <avagin@openvz.org>
---
tools/perf/builtin-inject.c | 96 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 91 insertions(+), 5 deletions(-)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index d04b7a4..247f41c 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -13,6 +13,8 @@
#include "util/debug.h"
#include "util/parse-options.h"
+#include "util/trace-event.h"
+
static char const *input_name = "-";
static const char *output_name = "-";
@@ -21,6 +23,9 @@ static int output;
static u64 bytes_written;
static bool inject_build_ids;
+static bool inject_sched_stat;
+
+struct perf_session *session;
static int perf_event__repipe_synth(struct perf_tool *tool __used,
union perf_event *event,
@@ -47,7 +52,7 @@ static int perf_event__repipe_synth(struct perf_tool *tool __used,
static int perf_event__repipe_op2_synth(struct perf_tool *tool,
union perf_event *event,
- struct perf_session *session __used)
+ struct perf_session *s __used)
{
return perf_event__repipe_synth(tool, event, NULL);
}
@@ -59,7 +64,7 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
}
static int perf_event__repipe_tracing_data_synth(union perf_event *event,
- struct perf_session *session __used)
+ struct perf_session *s __used)
{
return perf_event__repipe_synth(NULL, event, NULL);
}
@@ -119,12 +124,12 @@ static int perf_event__repipe_task(struct perf_tool *tool,
}
static int perf_event__repipe_tracing_data(union perf_event *event,
- struct perf_session *session)
+ struct perf_session *s)
{
int err;
perf_event__repipe_synth(NULL, event, NULL);
- err = perf_event__process_tracing_data(event, session);
+ err = perf_event__process_tracing_data(event, s);
return err;
}
@@ -210,6 +215,83 @@ repipe:
return 0;
}
+struct event_entry {
+ struct list_head list;
+ u32 pid;
+ union perf_event event[0];
+};
+
+static LIST_HEAD(samples);
+
+static int perf_event__sched_stat(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel __used,
+ struct machine *machine)
+{
+ int type;
+ struct event_format *e;
+ const char *evname = NULL;
+ uint32_t size;
+ struct event_entry *ent;
+ union perf_event *event_sw = NULL;
+ struct perf_sample sample_sw;
+ int sched_process_exit;
+
+ size = event->header.size;
+
+ type = trace_parse_common_type(session->pevent, sample->raw_data);
+ e = pevent_find_event(session->pevent, type);
+ if (e)
+ evname = e->name;
+
+ sched_process_exit = !strcmp(evname, "sched_process_exit");
+
+ if (!strcmp(evname, "sched_switch") || sched_process_exit) {
+ list_for_each_entry(ent, &samples, list)
+ if (sample->pid == ent->pid)
+ break;
+
+ if (&ent->list != &samples) {
+ list_del(&ent->list);
+ free(ent);
+ }
+
+ if (sched_process_exit)
+ return 0;
+
+ ent = malloc(size + sizeof(struct event_entry));
+ ent->pid = sample->pid;
+ memcpy(&ent->event, event, size);
+ list_add(&ent->list, &samples);
+ return 0;
+
+ } else if (!strncmp(evname, "sched_stat_", 11)) {
+ u32 pid;
+
+ pid = raw_field_value(e, "pid", sample->raw_data);
+
+ list_for_each_entry(ent, &samples, list) {
+ if (pid == ent->pid)
+ break;
+ }
+
+ if (&ent->list == &samples)
+ return 0;
+
+ event_sw = &ent->event[0];
+ perf_session__parse_sample(session, event_sw, &sample_sw);
+ sample_sw.period = sample->period;
+ sample_sw.time = sample->time;
+ perf_session__synthesize_sample(session, event_sw, &sample_sw);
+ perf_event__repipe(tool, event_sw, &sample_sw, machine);
+ return 0;
+ }
+
+ perf_event__repipe(tool, event, sample, machine);
+
+ return 0;
+}
struct perf_tool perf_inject = {
.sample = perf_event__repipe_sample,
.mmap = perf_event__repipe,
@@ -235,7 +317,6 @@ static void sig_handler(int sig __attribute__((__unused__)))
static int __cmd_inject(void)
{
- struct perf_session *session;
int ret = -EINVAL;
signal(SIGINT, sig_handler);
@@ -245,6 +326,9 @@ static int __cmd_inject(void)
perf_inject.mmap = perf_event__repipe_mmap;
perf_inject.fork = perf_event__repipe_task;
perf_inject.tracing_data = perf_event__repipe_tracing_data;
+ } else if (inject_sched_stat) {
+ perf_inject.sample = perf_event__sched_stat;
+ perf_inject.ordered_samples = true;
}
session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
@@ -272,6 +356,8 @@ static const char * const report_usage[] = {
static const struct option options[] = {
OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
"Inject build-ids into the output stream"),
+ OPT_BOOLEAN('s', "sched-stat", &inject_sched_stat,
+ "Set source call-chains for sched:shed-stat-*"),
OPT_STRING('i', "input", &input_name, "file",
"input file name"),
OPT_STRING('o', "output", &output_name, "file",
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] perf: mark a dso if it's used
2012-08-06 10:01 [PATCH 0/3] perf: Teach perf tool to profile sleep times Andrew Vagin
2012-08-06 10:01 ` [PATCH 1/3] perf: teach "perf inject" to work with files Andrew Vagin
2012-08-06 10:01 ` [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events Andrew Vagin
@ 2012-08-06 10:01 ` Andrew Vagin
2012-08-06 18:14 ` Arnaldo Carvalho de Melo
2 siblings, 1 reply; 12+ messages in thread
From: Andrew Vagin @ 2012-08-06 10:01 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo
Otherwise they will be not written in an output file.
Signed-off-by: Andrew Vagin <avagin@openvz.org>
---
tools/perf/builtin-inject.c | 11 +++++++++--
tools/perf/util/build-id.c | 2 +-
tools/perf/util/build-id.h | 5 +++++
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 247f41c..cb2fd77 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -14,6 +14,7 @@
#include "util/parse-options.h"
#include "util/trace-event.h"
+#include "util/build-id.h"
static char const *input_name = "-";
@@ -281,13 +282,17 @@ static int perf_event__sched_stat(struct perf_tool *tool,
event_sw = &ent->event[0];
perf_session__parse_sample(session, event_sw, &sample_sw);
+
sample_sw.period = sample->period;
sample_sw.time = sample->time;
perf_session__synthesize_sample(session, event_sw, &sample_sw);
+
+ build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
perf_event__repipe(tool, event_sw, &sample_sw, machine);
return 0;
}
+ build_id__mark_dso_hit(tool, event, sample, evsel, machine);
perf_event__repipe(tool, event, sample, machine);
return 0;
@@ -321,12 +326,14 @@ static int __cmd_inject(void)
signal(SIGINT, sig_handler);
- if (inject_build_ids) {
+ if (inject_build_ids || inject_sched_stat) {
perf_inject.sample = perf_event__inject_buildid;
perf_inject.mmap = perf_event__repipe_mmap;
perf_inject.fork = perf_event__repipe_task;
perf_inject.tracing_data = perf_event__repipe_tracing_data;
- } else if (inject_sched_stat) {
+ }
+
+ if (inject_sched_stat) {
perf_inject.sample = perf_event__sched_stat;
perf_inject.ordered_samples = true;
}
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index fd9a594..9ce0e11 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -16,7 +16,7 @@
#include "session.h"
#include "tool.h"
-static int build_id__mark_dso_hit(struct perf_tool *tool __used,
+int build_id__mark_dso_hit(struct perf_tool *tool __used,
union perf_event *event,
struct perf_sample *sample __used,
struct perf_evsel *evsel __used,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index a993ba8..032a968 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -7,4 +7,9 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
+int build_id__mark_dso_hit(struct perf_tool *tool __used,
+ union perf_event *event,
+ struct perf_sample *sample __used,
+ struct perf_evsel *evsel __used,
+ struct machine *machine);
#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] perf: teach "perf inject" to work with files
2012-08-06 10:01 ` [PATCH 1/3] perf: teach "perf inject" to work with files Andrew Vagin
@ 2012-08-06 18:12 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-06 18:12 UTC (permalink / raw)
To: Andrew Vagin; +Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar
Em Mon, Aug 06, 2012 at 02:01:57PM +0400, Andrew Vagin escreveu:
> Before this patch "perf inject" can only handle data from pipe.
>
> I want to use "perf inject" for reworking events. Look at my following patch.
>
> Signed-off-by: Andrew Vagin <avagin@openvz.org>
Patches that add options to commands should include updates to the docs
(tools/perf/Documentation/).
Also something I saw was the const * char versus const char * stuff for
the foo_file variables, please make them consistent.
- Arnaldo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] perf: mark a dso if it's used
2012-08-06 10:01 ` [PATCH 3/3] perf: mark a dso if it's used Andrew Vagin
@ 2012-08-06 18:14 ` Arnaldo Carvalho de Melo
2012-08-06 19:50 ` Andrey Wagin
0 siblings, 1 reply; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-06 18:14 UTC (permalink / raw)
To: Andrew Vagin; +Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar
Em Mon, Aug 06, 2012 at 02:01:59PM +0400, Andrew Vagin escreveu:
> - if (inject_build_ids) {
> + if (inject_build_ids || inject_sched_stat) {
> perf_inject.sample = perf_event__inject_buildid;
> perf_inject.mmap = perf_event__repipe_mmap;
> perf_inject.fork = perf_event__repipe_task;
> perf_inject.tracing_data = perf_event__repipe_tracing_data;
> - } else if (inject_sched_stat) {
> + }
> +
> + if (inject_sched_stat) {
> perf_inject.sample = perf_event__sched_stat;
> perf_inject.ordered_samples = true;
> }
Huh? so if inject_sched_stat is true we will first set
perf_inject.sample to something, then to another?
- Arnaldo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events
2012-08-06 10:01 ` [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events Andrew Vagin
@ 2012-08-06 18:19 ` Arnaldo Carvalho de Melo
2012-08-06 19:43 ` Andrey Wagin
0 siblings, 1 reply; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-06 18:19 UTC (permalink / raw)
To: Andrew Vagin; +Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar
Em Mon, Aug 06, 2012 at 02:01:58PM +0400, Andrew Vagin escreveu:
> You may want to know where and how long a task is sleeping. A callchain
> may be found in sched_switch and a time slice in stat_iowait, so I add
> handler in perf inject for merging this events.
>
> My code saves sched_switch event for each process and when it meets
> stat_iowait, it reports the sched_switch event, because this event
> contains a correct callchain. By another words it replaces all
> stat_iowait events on proper sched_switch events.
>
> Signed-off-by: Andrew Vagin <avagin@openvz.org>
> ---
> tools/perf/builtin-inject.c | 96 ++++++++++++++++++++++++++++++++++++++++--
> 1 files changed, 91 insertions(+), 5 deletions(-)
>
> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index d04b7a4..247f41c 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -13,6 +13,8 @@
> #include "util/debug.h"
>
> #include "util/parse-options.h"
> +#include "util/trace-event.h"
> +
>
> static char const *input_name = "-";
> static const char *output_name = "-";
> @@ -21,6 +23,9 @@ static int output;
> static u64 bytes_written;
>
> static bool inject_build_ids;
> +static bool inject_sched_stat;
> +
> +struct perf_session *session;
Why do we need to insert even more globals?
> static int perf_event__repipe_synth(struct perf_tool *tool __used,
> union perf_event *event,
> @@ -47,7 +52,7 @@ static int perf_event__repipe_synth(struct perf_tool *tool __used,
>
> static int perf_event__repipe_op2_synth(struct perf_tool *tool,
> union perf_event *event,
> - struct perf_session *session __used)
> + struct perf_session *s __used)
What is the point of the above hunk?
> {
> return perf_event__repipe_synth(tool, event, NULL);
> }
> @@ -59,7 +64,7 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
> }
>
> static int perf_event__repipe_tracing_data_synth(union perf_event *event,
> - struct perf_session *session __used)
> + struct perf_session *s __used)
Ditto
> {
> return perf_event__repipe_synth(NULL, event, NULL);
> }
> @@ -119,12 +124,12 @@ static int perf_event__repipe_task(struct perf_tool *tool,
> }
>
> static int perf_event__repipe_tracing_data(union perf_event *event,
> - struct perf_session *session)
> + struct perf_session *s)
> {
> int err;
>
> perf_event__repipe_synth(NULL, event, NULL);
> - err = perf_event__process_tracing_data(event, session);
> + err = perf_event__process_tracing_data(event, s);
Ditto
>
> return err;
> }
> @@ -210,6 +215,83 @@ repipe:
> return 0;
> }
>
> +struct event_entry {
> + struct list_head list;
Is this really the head of a list? Or is this a node that will allow
event_entry instances to be added to a head of a list? If the former,
please rename this to "node".
> + u32 pid;
> + union perf_event event[0];
> +};
> +
> +static LIST_HEAD(samples);
> +
> +static int perf_event__sched_stat(struct perf_tool *tool,
> + union perf_event *event,
> + struct perf_sample *sample,
> + struct perf_evsel *evsel __used,
> + struct machine *machine)
> +{
> + int type;
> + struct event_format *e;
> + const char *evname = NULL;
> + uint32_t size;
> + struct event_entry *ent;
> + union perf_event *event_sw = NULL;
> + struct perf_sample sample_sw;
> + int sched_process_exit;
> +
> + size = event->header.size;
> +
> + type = trace_parse_common_type(session->pevent, sample->raw_data);
> + e = pevent_find_event(session->pevent, type);
> + if (e)
> + evname = e->name;
> +
> + sched_process_exit = !strcmp(evname, "sched_process_exit");
> +
> + if (!strcmp(evname, "sched_switch") || sched_process_exit) {
extra space
> + list_for_each_entry(ent, &samples, list)
> + if (sample->pid == ent->pid)
> + break;
> +
> + if (&ent->list != &samples) {
> + list_del(&ent->list);
> + free(ent);
> + }
> +
> + if (sched_process_exit)
> + return 0;
> +
> + ent = malloc(size + sizeof(struct event_entry));
Can malloc fail?
> + ent->pid = sample->pid;
> + memcpy(&ent->event, event, size);
> + list_add(&ent->list, &samples);
> + return 0;
> +
> + } else if (!strncmp(evname, "sched_stat_", 11)) {
> + u32 pid;
> +
> + pid = raw_field_value(e, "pid", sample->raw_data);
> +
> + list_for_each_entry(ent, &samples, list) {
> + if (pid == ent->pid)
> + break;
> + }
> +
> + if (&ent->list == &samples)
> + return 0;
> +
> + event_sw = &ent->event[0];
> + perf_session__parse_sample(session, event_sw, &sample_sw);
> + sample_sw.period = sample->period;
> + sample_sw.time = sample->time;
> + perf_session__synthesize_sample(session, event_sw, &sample_sw);
Please use perf_evsel__parse_sample, recently introduced.
> + perf_event__repipe(tool, event_sw, &sample_sw, machine);
> + return 0;
> + }
> +
> + perf_event__repipe(tool, event, sample, machine);
> +
> + return 0;
> +}
> struct perf_tool perf_inject = {
> .sample = perf_event__repipe_sample,
> .mmap = perf_event__repipe,
> @@ -235,7 +317,6 @@ static void sig_handler(int sig __attribute__((__unused__)))
>
> static int __cmd_inject(void)
> {
> - struct perf_session *session;
> int ret = -EINVAL;
>
> signal(SIGINT, sig_handler);
> @@ -245,6 +326,9 @@ static int __cmd_inject(void)
> perf_inject.mmap = perf_event__repipe_mmap;
> perf_inject.fork = perf_event__repipe_task;
> perf_inject.tracing_data = perf_event__repipe_tracing_data;
> + } else if (inject_sched_stat) {
> + perf_inject.sample = perf_event__sched_stat;
> + perf_inject.ordered_samples = true;
> }
>
> session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
> @@ -272,6 +356,8 @@ static const char * const report_usage[] = {
> static const struct option options[] = {
> OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
> "Inject build-ids into the output stream"),
> + OPT_BOOLEAN('s', "sched-stat", &inject_sched_stat,
> + "Set source call-chains for sched:shed-stat-*"),
You're adding an option, needs to be documented on
perf/tools/Documentation/
> OPT_STRING('i', "input", &input_name, "file",
> "input file name"),
> OPT_STRING('o', "output", &output_name, "file",
> --
> 1.7.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events
2012-08-06 18:19 ` Arnaldo Carvalho de Melo
@ 2012-08-06 19:43 ` Andrey Wagin
2012-08-06 22:00 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 12+ messages in thread
From: Andrey Wagin @ 2012-08-06 19:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar
Hello Arnaldo,
Thanks for comments, I will correct them. I need a bit more details
about two of them.
2012/8/6 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>:
>> @@ -21,6 +23,9 @@ static int output;
>> static u64 bytes_written;
>>
>> static bool inject_build_ids;
>> +static bool inject_sched_stat;
>> +
>> +struct perf_session *session;
perf_event__sched_stat (perf_inject.sample) uses "session" for getting
an event name. I don't know how to get it by another way
>
> Why do we need to insert even more globals?
>
>> static int perf_event__repipe_synth(struct perf_tool *tool __used,
>> union perf_event *event,
>> @@ -47,7 +52,7 @@ static int perf_event__repipe_synth(struct perf_tool *tool __used,
>>
>> static int perf_event__repipe_op2_synth(struct perf_tool *tool,
>> union perf_event *event,
>> - struct perf_session *session __used)
>> + struct perf_session *s __used)
>
> What is the point of the above hunk?
"session" is global, for this reason I renamed all arguments.
p.s. Arnaldo, sorry for the personal message with the same content.
It's my mistake.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] perf: mark a dso if it's used
2012-08-06 18:14 ` Arnaldo Carvalho de Melo
@ 2012-08-06 19:50 ` Andrey Wagin
0 siblings, 0 replies; 12+ messages in thread
From: Andrey Wagin @ 2012-08-06 19:50 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar
2012/8/6 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>:
> Em Mon, Aug 06, 2012 at 02:01:59PM +0400, Andrew Vagin escreveu:
>> - if (inject_build_ids) {
>> + if (inject_build_ids || inject_sched_stat) {
>> perf_inject.sample = perf_event__inject_buildid;
>> perf_inject.mmap = perf_event__repipe_mmap;
>> perf_inject.fork = perf_event__repipe_task;
>> perf_inject.tracing_data = perf_event__repipe_tracing_data;
>> - } else if (inject_sched_stat) {
>> + }
>> +
>> + if (inject_sched_stat) {
>> perf_inject.sample = perf_event__sched_stat;
>> perf_inject.ordered_samples = true;
>> }
>
> Huh? so if inject_sched_stat is true we will first set
> perf_inject.sample to something, then to another?
Yes, we will. I though that it will be better then this:
if (inject_build_ids || inject_sched_stat) {
perf_inject.mmap = perf_event__repipe_mmap;
perf_inject.fork = perf_event__repipe_task;
perf_inject.tracing_data = perf_event__repipe_tracing_data;
}
if (inject_build_ids) {
perf_inject.sample = perf_event__inject_buildid;
} else if (inject_sched_stat) {
perf_inject.sample = perf_event__sched_stat;
perf_inject.ordered_samples = true;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events
2012-08-06 19:43 ` Andrey Wagin
@ 2012-08-06 22:00 ` Arnaldo Carvalho de Melo
2012-08-06 23:31 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-06 22:00 UTC (permalink / raw)
To: Andrey Wagin; +Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar
[-- Attachment #1: Type: text/plain, Size: 885 bytes --]
Em Mon, Aug 06, 2012 at 11:43:04PM +0400, Andrey Wagin escreveu:
> 2012/8/6 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>:
> >> +struct perf_session *session;
>
> perf_event__sched_stat (perf_inject.sample) uses "session" for getting
> an event name. I don't know how to get it by another way
Can you try with the attached patch? We already lookup the event_format
entries when we read the perf.data header so that we can cache
evsel->name, we might as well cache the event_format in
evsel->tp_format, so that tools don't have to relookup this for each
sample.
It would look like:
static int perf_event__sched_stat(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel,
struct machine *machine)
{
int type;
struct event_format *e = evsel->tp_format;
const char *evname = e->name;
- Arnaldo
[-- Attachment #2: a.patch --]
[-- Type: text/plain, Size: 660 bytes --]
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b559929..a56c457 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -56,6 +56,7 @@ struct perf_evsel {
int ids;
struct hists hists;
char *name;
+ struct event_format *tp_format;
union {
void *priv;
off_t id_offset;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 24c489b..5b328a4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2126,6 +2126,7 @@ static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
if (event->name == NULL)
return -1;
+ evsel->tp_format = event;
return 0;
}
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events
2012-08-06 22:00 ` Arnaldo Carvalho de Melo
@ 2012-08-06 23:31 ` Arnaldo Carvalho de Melo
2012-08-13 9:17 ` Ingo Molnar
0 siblings, 1 reply; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-06 23:31 UTC (permalink / raw)
To: Andrey Wagin
Cc: linux-kernel, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
David Ahern
[-- Attachment #1: Type: text/plain, Size: 814 bytes --]
Em Mon, Aug 06, 2012 at 07:00:00PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Aug 06, 2012 at 11:43:04PM +0400, Andrey Wagin escreveu:
> > 2012/8/6 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>:
> > >> +struct perf_session *session;
> > perf_event__sched_stat (perf_inject.sample) uses "session" for getting
> > an event name. I don't know how to get it by another way
>
> Can you try with the attached patch? We already lookup the event_format
> entries when we read the perf.data header so that we can cache
> evsel->name, we might as well cache the event_format in
> evsel->tp_format, so that tools don't have to relookup this for each
> sample.
Attached goes a more complete patch that removes the pevent_find_event
calls from several tools, David, could you give it some testing?
- Arnaldo
[-- Attachment #2: perf_evsel_tp_format.patch --]
[-- Type: text/plain, Size: 16372 bytes --]
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index ce35015..ffb93f4 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "perf.h"
+#include "util/evsel.h"
#include "util/util.h"
#include "util/cache.h"
#include "util/symbol.h"
@@ -57,11 +58,6 @@ static unsigned long nr_allocs, nr_cross_allocs;
#define PATH_SYS_NODE "/sys/devices/system/node"
-struct perf_kmem {
- struct perf_tool tool;
- struct perf_session *session;
-};
-
static void init_cpunode_map(void)
{
FILE *fp;
@@ -283,16 +279,10 @@ static void process_free_event(void *data,
s_alloc->alloc_cpu = -1;
}
-static void process_raw_event(struct perf_tool *tool,
- union perf_event *raw_event __used, void *data,
+static void process_raw_event(struct perf_evsel *evsel, void *data,
int cpu, u64 timestamp, struct thread *thread)
{
- struct perf_kmem *kmem = container_of(tool, struct perf_kmem, tool);
- struct event_format *event;
- int type;
-
- type = trace_parse_common_type(kmem->session->pevent, data);
- event = pevent_find_event(kmem->session->pevent, type);
+ struct event_format *event = evsel->tp_format;
if (!strcmp(event->name, "kmalloc") ||
!strcmp(event->name, "kmem_cache_alloc")) {
@@ -313,10 +303,10 @@ static void process_raw_event(struct perf_tool *tool,
}
}
-static int process_sample_event(struct perf_tool *tool,
+static int process_sample_event(struct perf_tool *tool __used,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel __used,
+ struct perf_evsel *evsel,
struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
@@ -329,18 +319,16 @@ static int process_sample_event(struct perf_tool *tool,
dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
- process_raw_event(tool, event, sample->raw_data, sample->cpu,
+ process_raw_event(evsel, sample->raw_data, sample->cpu,
sample->time, thread);
return 0;
}
-static struct perf_kmem perf_kmem = {
- .tool = {
- .sample = process_sample_event,
- .comm = perf_event__process_comm,
- .ordered_samples = true,
- },
+static struct perf_tool perf_kmem = {
+ .sample = process_sample_event,
+ .comm = perf_event__process_comm,
+ .ordered_samples = true,
};
static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -497,13 +485,10 @@ static int __cmd_kmem(void)
int err = -EINVAL;
struct perf_session *session;
- session = perf_session__new(input_name, O_RDONLY, 0, false,
- &perf_kmem.tool);
+ session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem);
if (session == NULL)
return -ENOMEM;
- perf_kmem.session = session;
-
if (perf_session__create_kernel_maps(session) < 0)
goto out_delete;
@@ -511,7 +496,7 @@ static int __cmd_kmem(void)
goto out_delete;
setup_pager();
- err = perf_session__process_events(session, &perf_kmem.tool);
+ err = perf_session__process_events(session, &perf_kmem);
if (err != 0)
goto out_delete;
sort_result();
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index b3c4285..142b303 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "perf.h"
+#include "util/evsel.h"
#include "util/util.h"
#include "util/cache.h"
#include "util/symbol.h"
@@ -718,14 +719,10 @@ process_lock_release_event(void *data,
trace_handler->release_event(&release_event, event, cpu, timestamp, thread);
}
-static void
-process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
+static void process_raw_event(struct perf_evsel *evsel, void *data, int cpu,
+ u64 timestamp, struct thread *thread)
{
- struct event_format *event;
- int type;
-
- type = trace_parse_common_type(session->pevent, data);
- event = pevent_find_event(session->pevent, type);
+ struct event_format *event = evsel->tp_format;
if (!strcmp(event->name, "lock_acquire"))
process_lock_acquire_event(data, event, cpu, timestamp, thread);
@@ -849,7 +846,7 @@ static void dump_info(void)
static int process_sample_event(struct perf_tool *tool __used,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel __used,
+ struct perf_evsel *evsel,
struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, sample->tid);
@@ -860,7 +857,7 @@ static int process_sample_event(struct perf_tool *tool __used,
return -1;
}
- process_raw_event(sample->raw_data, sample->cpu, sample->time, thread);
+ process_raw_event(evsel, sample->raw_data, sample->cpu, sample->time, thread);
return 0;
}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 7a9ad2b..30ef82a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -43,11 +43,6 @@ static u64 sleep_measurement_overhead;
static unsigned long nr_tasks;
-struct perf_sched {
- struct perf_tool tool;
- struct perf_session *session;
-};
-
struct sched_atom;
struct task_desc {
@@ -1596,14 +1591,12 @@ typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event_format *
struct machine *machine,
struct thread *thread);
-static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
+static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __used,
union perf_event *event __used,
struct perf_sample *sample,
struct perf_evsel *evsel,
struct machine *machine)
{
- struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
- struct pevent *pevent = sched->session->pevent;
struct thread *thread = machine__findnew_thread(machine, sample->pid);
if (thread == NULL) {
@@ -1617,25 +1610,18 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
if (evsel->handler.func != NULL) {
tracepoint_handler f = evsel->handler.func;
-
- if (evsel->handler.data == NULL)
- evsel->handler.data = pevent_find_event(pevent,
- evsel->attr.config);
-
- f(tool, evsel->handler.data, sample, machine, thread);
+ f(tool, evsel->tp_format, sample, machine, thread);
}
return 0;
}
-static struct perf_sched perf_sched = {
- .tool = {
- .sample = perf_sched__process_tracepoint_sample,
- .comm = perf_event__process_comm,
- .lost = perf_event__process_lost,
- .fork = perf_event__process_task,
- .ordered_samples = true,
- },
+static struct perf_tool perf_sched = {
+ .sample = perf_sched__process_tracepoint_sample,
+ .comm = perf_event__process_comm,
+ .lost = perf_event__process_lost,
+ .fork = perf_event__process_task,
+ .ordered_samples = true,
};
static void read_events(bool destroy, struct perf_session **psession)
@@ -1652,18 +1638,15 @@ static void read_events(bool destroy, struct perf_session **psession)
};
struct perf_session *session;
- session = perf_session__new(input_name, O_RDONLY, 0, false,
- &perf_sched.tool);
+ session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_sched);
if (session == NULL)
die("No Memory");
- perf_sched.session = session;
-
err = perf_session__set_tracepoints_handlers(session, handlers);
assert(err == 0);
if (perf_session__has_traces(session, "record -R")) {
- err = perf_session__process_events(session, &perf_sched.tool);
+ err = perf_session__process_events(session, &perf_sched);
if (err)
die("Failed to process events, error %d", err);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1e60ab7..8dba470 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -262,14 +262,11 @@ static int perf_session__check_output_opt(struct perf_session *session)
return 0;
}
-static void print_sample_start(struct pevent *pevent,
- struct perf_sample *sample,
+static void print_sample_start(struct perf_sample *sample,
struct thread *thread,
struct perf_evsel *evsel)
{
- int type;
struct perf_event_attr *attr = &evsel->attr;
- struct event_format *event;
const char *evname = NULL;
unsigned long secs;
unsigned long usecs;
@@ -307,20 +304,7 @@ static void print_sample_start(struct pevent *pevent,
}
if (PRINT_FIELD(EVNAME)) {
- if (attr->type == PERF_TYPE_TRACEPOINT) {
- /*
- * XXX Do we really need this here?
- * perf_evlist__set_tracepoint_names should have done
- * this already
- */
- type = trace_parse_common_type(pevent,
- sample->raw_data);
- event = pevent_find_event(pevent, type);
- if (event)
- evname = event->name;
- } else
- evname = perf_evsel__name(evsel);
-
+ evname = perf_evsel__name(evsel);
printf("%s: ", evname ? evname : "[unknown]");
}
}
@@ -416,7 +400,7 @@ static void print_sample_bts(union perf_event *event,
}
static void process_event(union perf_event *event __unused,
- struct pevent *pevent,
+ struct pevent *pevent __unused,
struct perf_sample *sample,
struct perf_evsel *evsel,
struct machine *machine,
@@ -427,7 +411,7 @@ static void process_event(union perf_event *event __unused,
if (output[attr->type].fields == 0)
return;
- print_sample_start(pevent, sample, thread, evsel);
+ print_sample_start(sample, thread, evsel);
if (is_bts_event(attr)) {
print_sample_bts(event, sample, evsel, machine, thread);
@@ -435,9 +419,8 @@ static void process_event(union perf_event *event __unused,
}
if (PRINT_FIELD(TRACE))
- print_trace_event(pevent, sample->cpu, sample->raw_data,
- sample->raw_size);
-
+ event_format__print(evsel->tp_format, sample->cpu,
+ sample->raw_data, sample->raw_size);
if (PRINT_FIELD(ADDR))
print_sample_addr(event, sample, machine, thread, attr);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b559929..a56c457 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -56,6 +56,7 @@ struct perf_evsel {
int ids;
struct hists hists;
char *name;
+ struct event_format *tp_format;
union {
void *priv;
off_t id_offset;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 74ea3c2..7f13ed4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2123,6 +2123,7 @@ static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
if (event->name == NULL)
return -1;
+ evsel->tp_format = event;
return 0;
}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 02dfa19..c266281 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -237,16 +237,16 @@ static void define_event_symbols(struct event_format *event,
define_event_symbols(event, ev_name, args->next);
}
-static inline
-struct event_format *find_cache_event(struct pevent *pevent, int type)
+static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
{
static char ev_name[256];
struct event_format *event;
+ int type = evsel->attr.config;
if (events[type])
return events[type];
- events[type] = event = pevent_find_event(pevent, type);
+ events[type] = event = evsel->tp_format;
if (!event)
return NULL;
@@ -269,7 +269,6 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,
unsigned long long val;
unsigned long s, ns;
struct event_format *event;
- int type;
int pid;
int cpu = sample->cpu;
void *data = sample->raw_data;
@@ -281,11 +280,9 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,
if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
return;
- type = trace_parse_common_type(pevent, data);
-
- event = find_cache_event(pevent, type);
+ event = find_cache_event(evsel);
if (!event)
- die("ug! no event found for type %d", type);
+ die("ug! no event found for type %d", evsel->attr.config);
pid = trace_parse_common_pid(pevent, data);
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ce4d1b0..8006978 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include "../../perf.h"
+#include "../evsel.h"
#include "../util.h"
#include "../event.h"
#include "../thread.h"
@@ -194,16 +195,21 @@ static void define_event_symbols(struct event_format *event,
define_event_symbols(event, ev_name, args->next);
}
-static inline
-struct event_format *find_cache_event(struct pevent *pevent, int type)
+static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
{
static char ev_name[256];
struct event_format *event;
+ int type = evsel->attr.config;
+ /*
+ * XXX: Do we really need to cache this since now we have evsel->tp_format
+ * cached already? Need to re-read this "cache" routine that as well calls
+ * define_event_symbols() :-\
+ */
if (events[type])
return events[type];
- events[type] = event = pevent_find_event(pevent, type);
+ events[type] = event = evsel->tp_format;
if (!event)
return NULL;
@@ -217,7 +223,7 @@ struct event_format *find_cache_event(struct pevent *pevent, int type)
static void python_process_event(union perf_event *perf_event __unused,
struct pevent *pevent,
struct perf_sample *sample,
- struct perf_evsel *evsel __unused,
+ struct perf_evsel *evsel,
struct machine *machine __unused,
struct thread *thread)
{
@@ -228,7 +234,6 @@ static void python_process_event(union perf_event *perf_event __unused,
unsigned long s, ns;
struct event_format *event;
unsigned n = 0;
- int type;
int pid;
int cpu = sample->cpu;
void *data = sample->raw_data;
@@ -239,11 +244,9 @@ static void python_process_event(union perf_event *perf_event __unused,
if (!t)
Py_FatalError("couldn't create Python tuple");
- type = trace_parse_common_type(pevent, data);
-
- event = find_cache_event(pevent, type);
+ event = find_cache_event(evsel);
if (!event)
- die("ug! no event found for type %d", type);
+ die("ug! no event found for type %d", (int)evsel->attr.config);
pid = trace_parse_common_pid(pevent, data);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 0715c84..1208834 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -167,20 +167,11 @@ unsigned long long read_size(struct pevent *pevent, void *ptr, int size)
return pevent_read_number(pevent, ptr, size);
}
-void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
+void event_format__print(struct event_format *event,
+ int cpu, void *data, int size)
{
- struct event_format *event;
struct pevent_record record;
struct trace_seq s;
- int type;
-
- type = trace_parse_common_type(pevent, data);
-
- event = pevent_find_event(pevent, type);
- if (!event) {
- warning("ug! no event found for type %d", type);
- return;
- }
memset(&record, 0, sizeof(record));
record.cpu = cpu;
@@ -192,6 +183,19 @@ void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
trace_seq_do_printf(&s);
}
+void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
+{
+ int type = trace_parse_common_type(pevent, data);
+ struct event_format *event = pevent_find_event(pevent, type);
+
+ if (!event) {
+ warning("ug! no event found for type %d", type);
+ return;
+ }
+
+ event_format__print(event, cpu, data, size);
+}
+
void print_event(struct pevent *pevent, int cpu, void *data, int size,
unsigned long long nsecs, char *comm)
{
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 8fef1d6..069d105 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -32,6 +32,8 @@ int bigendian(void);
struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
void print_trace_event(struct pevent *pevent, int cpu, void *data, int size);
+void event_format__print(struct event_format *event,
+ int cpu, void *data, int size);
void print_event(struct pevent *pevent, int cpu, void *data, int size,
unsigned long long nsecs, char *comm);
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events
2012-08-06 23:31 ` Arnaldo Carvalho de Melo
@ 2012-08-13 9:17 ` Ingo Molnar
0 siblings, 0 replies; 12+ messages in thread
From: Ingo Molnar @ 2012-08-13 9:17 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Andrey Wagin, linux-kernel, Peter Zijlstra, Paul Mackerras,
David Ahern
* Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> static int process_sample_event(struct perf_tool *tool __used,
> union perf_event *event,
> struct perf_sample *sample,
> struct perf_evsel *evsel,
> struct machine *machine)
Just saw this 5-parameter function signature fly by: as a
separate clean-up it would be really neat to stick most of these
into an intuitively named helper structure or so.
struct event_context ectx?
That would make extension of the context easier as well in the
future. Or so.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2012-08-13 9:17 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-06 10:01 [PATCH 0/3] perf: Teach perf tool to profile sleep times Andrew Vagin
2012-08-06 10:01 ` [PATCH 1/3] perf: teach "perf inject" to work with files Andrew Vagin
2012-08-06 18:12 ` Arnaldo Carvalho de Melo
2012-08-06 10:01 ` [PATCH 2/3] perf: teach perf inject to merge sched_stat_* and sched_switch events Andrew Vagin
2012-08-06 18:19 ` Arnaldo Carvalho de Melo
2012-08-06 19:43 ` Andrey Wagin
2012-08-06 22:00 ` Arnaldo Carvalho de Melo
2012-08-06 23:31 ` Arnaldo Carvalho de Melo
2012-08-13 9:17 ` Ingo Molnar
2012-08-06 10:01 ` [PATCH 3/3] perf: mark a dso if it's used Andrew Vagin
2012-08-06 18:14 ` Arnaldo Carvalho de Melo
2012-08-06 19:50 ` Andrey Wagin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).