* perf: store and retrieve trace event names in the perf.data file
@ 2009-08-09 21:49 Arjan van de Ven
2009-08-09 22:44 ` Frederic Weisbecker
2009-08-10 9:50 ` Peter Zijlstra
0 siblings, 2 replies; 6+ messages in thread
From: Arjan van de Ven @ 2009-08-09 21:49 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Linux Kernel Mailing List
In order to be able to use trace events, a key aspect is the "type" field;
this is the id of the event that you recorded, as stored in the /sys/kernel/debug/events/*/*/id file.
What is currently missing is a way to map the id number (which is not abi stable)
to the event that was recorded.
This patch adds the facility that stores the trace event name and id in the perf.data file,
and then allows users of it to map the ID back to the original string.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index b92a457..73eeefb 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -48,7 +48,7 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
struct perf_header *perf_header__new(void)
{
- struct perf_header *self = malloc(sizeof(*self));
+ struct perf_header *self = malloc(sizeof(struct perf_header));
if (!self)
die("nomem");
@@ -86,6 +86,45 @@ void perf_header__add_attr(struct perf_header *self,
self->attr[pos] = attr;
}
+struct perf_trace_event_type
+{
+ u64 event_id;
+ char name[64];
+};
+
+static int event_count;
+static struct perf_trace_event_type *events;
+
+void perf_header__push_event(u64 id, const char *name)
+{
+ if (strlen(name) > 64) {
+ printf("Event %s will be truncated\n", name);
+ }
+ if (!events) {
+ events = malloc(sizeof(struct perf_trace_event_type));
+ if (!events)
+ die("nomem");
+ } else {
+ events = realloc(events, (event_count + 1) * sizeof(struct perf_trace_event_type));
+ if (!events)
+ die("nomem");
+ }
+ memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
+ events[event_count].event_id = id;
+ strncpy(events[event_count].name, name, 63);
+ event_count++;
+}
+
+char * perf_header__find_event(u64 id)
+{
+ int i;
+ for (i = 0 ; i < event_count; i++) {
+ if (events[i].event_id == id)
+ return events[i].name;
+ }
+ return NULL;
+}
+
static const char *__perf_magic = "PERFFILE";
#define PERF_MAGIC (*(u64 *)__perf_magic)
@@ -106,6 +145,7 @@ struct perf_file_header {
u64 attr_size;
struct perf_file_section attrs;
struct perf_file_section data;
+ struct perf_file_section event_types;
};
static void do_write(int fd, void *buf, size_t size)
@@ -154,6 +194,11 @@ void perf_header__write(struct perf_header *self, int fd)
do_write(fd, &f_attr, sizeof(f_attr));
}
+ self->event_offset = lseek(fd, 0, SEEK_CUR);
+ self->event_size = event_count * sizeof(struct perf_trace_event_type);
+ if (events)
+ do_write(fd, events, self->event_size);
+
self->data_offset = lseek(fd, 0, SEEK_CUR);
@@ -169,6 +214,10 @@ void perf_header__write(struct perf_header *self, int fd)
.offset = self->data_offset,
.size = self->data_size,
},
+ .event_types = {
+ .offset = self->event_offset,
+ .size = self->event_size,
+ },
};
lseek(fd, 0, SEEK_SET);
@@ -237,6 +286,20 @@ struct perf_header *perf_header__read(int fd)
self->data_offset = f_header.data.offset;
self->data_size = f_header.data.size;
+ printf("event_types.size = %i \n", (int)f_header.event_types.size);
+
+ if (f_header.event_types.size) {
+
+ lseek(fd, f_header.event_types.offset, SEEK_SET);
+ events = malloc(f_header.event_types.size);
+ if (!events)
+ die("nomem");
+ do_read(fd, events, f_header.event_types.size);
+ event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
+ }
+ self->event_offset = f_header.event_types.offset;
+ self->event_size = f_header.event_types.size;
+
lseek(fd, self->data_offset + self->data_size, SEEK_SET);
self->frozen = 1;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index bf28044..606a8fb 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -19,6 +19,8 @@ struct perf_header {
s64 attr_offset;
u64 data_offset;
u64 data_size;
+ u64 event_offset;
+ u64 event_size;
};
struct perf_header *perf_header__read(int fd);
@@ -27,6 +29,10 @@ void perf_header__write(struct perf_header *self, int fd);
void perf_header__add_attr(struct perf_header *self,
struct perf_header_attr *attr);
+void perf_header__push_event(u64 id, const char *name);
+char * perf_header__find_event(u64 id);
+
+
struct perf_header_attr *
perf_header_attr__new(struct perf_counter_attr *attr);
void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4858d83..e8c5255 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,6 +6,7 @@
#include "exec_cmd.h"
#include "string.h"
#include "cache.h"
+#include "header.h"
extern char *strcasestr(const char *haystack, const char *needle);
@@ -543,10 +544,32 @@ static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
return 1;
}
+static void store_event_type(const char *orgname)
+{
+ char filename[PATH_MAX], *c;
+ FILE *file;
+ int id;
+
+ sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
+ c = strchr(filename, ':');
+ if (c) *c = '/';
+
+ file = fopen(filename, "r");
+ if (!file)
+ return;
+ fscanf(file, "%i", &id);
+ fclose(file);
+ perf_header__push_event(id, orgname);
+}
+
+
int parse_events(const struct option *opt __used, const char *str, int unset __used)
{
struct perf_counter_attr attr;
+ if (strchr(str, ':'))
+ store_event_type(str);
+
for (;;) {
if (nr_counters == MAX_COUNTERS)
return -1;
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: perf: store and retrieve trace event names in the perf.data file
2009-08-09 21:49 perf: store and retrieve trace event names in the perf.data file Arjan van de Ven
@ 2009-08-09 22:44 ` Frederic Weisbecker
2009-08-09 23:01 ` Arjan van de Ven
2009-08-10 9:50 ` Peter Zijlstra
1 sibling, 1 reply; 6+ messages in thread
From: Frederic Weisbecker @ 2009-08-09 22:44 UTC (permalink / raw)
To: Arjan van de Ven; +Cc: Ingo Molnar, Linux Kernel Mailing List
On Sun, Aug 09, 2009 at 02:49:23PM -0700, Arjan van de Ven wrote:
> In order to be able to use trace events, a key aspect is the "type" field;
> this is the id of the event that you recorded, as stored in the /sys/kernel/debug/events/*/*/id file.
> What is currently missing is a way to map the id number (which is not abi stable)
> to the event that was recorded.
We already have that.
See tools/perf/util/parse-events.c: char *tracepoint_id_to_name(u64 id)
Frederic.
> This patch adds the facility that stores the trace event name and id in the perf.data file,
> and then allows users of it to map the ID back to the original string.
>
> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
>
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index b92a457..73eeefb 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -48,7 +48,7 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
>
> struct perf_header *perf_header__new(void)
> {
> - struct perf_header *self = malloc(sizeof(*self));
> + struct perf_header *self = malloc(sizeof(struct perf_header));
>
> if (!self)
> die("nomem");
> @@ -86,6 +86,45 @@ void perf_header__add_attr(struct perf_header *self,
> self->attr[pos] = attr;
> }
>
> +struct perf_trace_event_type
> +{
> + u64 event_id;
> + char name[64];
> +};
> +
> +static int event_count;
> +static struct perf_trace_event_type *events;
> +
> +void perf_header__push_event(u64 id, const char *name)
> +{
> + if (strlen(name) > 64) {
> + printf("Event %s will be truncated\n", name);
> + }
> + if (!events) {
> + events = malloc(sizeof(struct perf_trace_event_type));
> + if (!events)
> + die("nomem");
> + } else {
> + events = realloc(events, (event_count + 1) * sizeof(struct perf_trace_event_type));
> + if (!events)
> + die("nomem");
> + }
> + memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
> + events[event_count].event_id = id;
> + strncpy(events[event_count].name, name, 63);
> + event_count++;
> +}
> +
> +char * perf_header__find_event(u64 id)
> +{
> + int i;
> + for (i = 0 ; i < event_count; i++) {
> + if (events[i].event_id == id)
> + return events[i].name;
> + }
> + return NULL;
> +}
> +
> static const char *__perf_magic = "PERFFILE";
>
> #define PERF_MAGIC (*(u64 *)__perf_magic)
> @@ -106,6 +145,7 @@ struct perf_file_header {
> u64 attr_size;
> struct perf_file_section attrs;
> struct perf_file_section data;
> + struct perf_file_section event_types;
> };
>
> static void do_write(int fd, void *buf, size_t size)
> @@ -154,6 +194,11 @@ void perf_header__write(struct perf_header *self, int fd)
> do_write(fd, &f_attr, sizeof(f_attr));
> }
>
> + self->event_offset = lseek(fd, 0, SEEK_CUR);
> + self->event_size = event_count * sizeof(struct perf_trace_event_type);
> + if (events)
> + do_write(fd, events, self->event_size);
> +
>
> self->data_offset = lseek(fd, 0, SEEK_CUR);
>
> @@ -169,6 +214,10 @@ void perf_header__write(struct perf_header *self, int fd)
> .offset = self->data_offset,
> .size = self->data_size,
> },
> + .event_types = {
> + .offset = self->event_offset,
> + .size = self->event_size,
> + },
> };
>
> lseek(fd, 0, SEEK_SET);
> @@ -237,6 +286,20 @@ struct perf_header *perf_header__read(int fd)
> self->data_offset = f_header.data.offset;
> self->data_size = f_header.data.size;
>
> + printf("event_types.size = %i \n", (int)f_header.event_types.size);
> +
> + if (f_header.event_types.size) {
> +
> + lseek(fd, f_header.event_types.offset, SEEK_SET);
> + events = malloc(f_header.event_types.size);
> + if (!events)
> + die("nomem");
> + do_read(fd, events, f_header.event_types.size);
> + event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
> + }
> + self->event_offset = f_header.event_types.offset;
> + self->event_size = f_header.event_types.size;
> +
> lseek(fd, self->data_offset + self->data_size, SEEK_SET);
>
> self->frozen = 1;
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index bf28044..606a8fb 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -19,6 +19,8 @@ struct perf_header {
> s64 attr_offset;
> u64 data_offset;
> u64 data_size;
> + u64 event_offset;
> + u64 event_size;
> };
>
> struct perf_header *perf_header__read(int fd);
> @@ -27,6 +29,10 @@ void perf_header__write(struct perf_header *self, int fd);
> void perf_header__add_attr(struct perf_header *self,
> struct perf_header_attr *attr);
>
> +void perf_header__push_event(u64 id, const char *name);
> +char * perf_header__find_event(u64 id);
> +
> +
> struct perf_header_attr *
> perf_header_attr__new(struct perf_counter_attr *attr);
> void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index 4858d83..e8c5255 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -6,6 +6,7 @@
> #include "exec_cmd.h"
> #include "string.h"
> #include "cache.h"
> +#include "header.h"
>
> extern char *strcasestr(const char *haystack, const char *needle);
>
> @@ -543,10 +544,32 @@ static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
> return 1;
> }
>
> +static void store_event_type(const char *orgname)
> +{
> + char filename[PATH_MAX], *c;
> + FILE *file;
> + int id;
> +
> + sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
> + c = strchr(filename, ':');
> + if (c) *c = '/';
> +
> + file = fopen(filename, "r");
> + if (!file)
> + return;
> + fscanf(file, "%i", &id);
> + fclose(file);
> + perf_header__push_event(id, orgname);
> +}
> +
> +
> int parse_events(const struct option *opt __used, const char *str, int unset __used)
> {
> struct perf_counter_attr attr;
>
> + if (strchr(str, ':'))
> + store_event_type(str);
> +
> for (;;) {
> if (nr_counters == MAX_COUNTERS)
> return -1;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: perf: store and retrieve trace event names in the perf.data file
2009-08-09 22:44 ` Frederic Weisbecker
@ 2009-08-09 23:01 ` Arjan van de Ven
2009-08-09 23:04 ` Frederic Weisbecker
0 siblings, 1 reply; 6+ messages in thread
From: Arjan van de Ven @ 2009-08-09 23:01 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, Linux Kernel Mailing List
Frederic Weisbecker wrote:
> On Sun, Aug 09, 2009 at 02:49:23PM -0700, Arjan van de Ven wrote:
>> In order to be able to use trace events, a key aspect is the "type" field;
>> this is the id of the event that you recorded, as stored in the /sys/kernel/debug/events/*/*/id file.
>> What is currently missing is a way to map the id number (which is not abi stable)
>> to the event that was recorded.
>
>
>
> We already have that.
> See tools/perf/util/parse-events.c: char *tracepoint_id_to_name(u64 id)
sadly... we don't.
You do it *on the same boot and machine* as you created the perf.data file.
You don't have it when you reboot into a new kernel, or move the perf.data file
to a new machine........
Which is to be honest a very common usecase.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: perf: store and retrieve trace event names in the perf.data file
2009-08-09 23:01 ` Arjan van de Ven
@ 2009-08-09 23:04 ` Frederic Weisbecker
2009-08-09 23:10 ` Arjan van de Ven
0 siblings, 1 reply; 6+ messages in thread
From: Frederic Weisbecker @ 2009-08-09 23:04 UTC (permalink / raw)
To: Arjan van de Ven; +Cc: Ingo Molnar, Linux Kernel Mailing List
On Sun, Aug 09, 2009 at 04:01:30PM -0700, Arjan van de Ven wrote:
> Frederic Weisbecker wrote:
>> On Sun, Aug 09, 2009 at 02:49:23PM -0700, Arjan van de Ven wrote:
>>> In order to be able to use trace events, a key aspect is the "type" field;
>>> this is the id of the event that you recorded, as stored in the /sys/kernel/debug/events/*/*/id file.
>>> What is currently missing is a way to map the id number (which is not abi stable)
>>> to the event that was recorded.
>>
>>
>>
>> We already have that.
>> See tools/perf/util/parse-events.c: char *tracepoint_id_to_name(u64 id)
>
>
> sadly... we don't.
>
> You do it *on the same boot and machine* as you created the perf.data file.
> You don't have it when you reboot into a new kernel, or move the perf.data file
> to a new machine........
>
> Which is to be honest a very common usecase.
Ah right... I always forget the offline report case.
But you can at least reuse this existing helper to resolve
the id to name.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: perf: store and retrieve trace event names in the perf.data file
2009-08-09 23:04 ` Frederic Weisbecker
@ 2009-08-09 23:10 ` Arjan van de Ven
0 siblings, 0 replies; 6+ messages in thread
From: Arjan van de Ven @ 2009-08-09 23:10 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, Linux Kernel Mailing List
Frederic Weisbecker wrote:
> On Sun, Aug 09, 2009 at 04:01:30PM -0700, Arjan van de Ven wrote:
>> Frederic Weisbecker wrote:
>>> On Sun, Aug 09, 2009 at 02:49:23PM -0700, Arjan van de Ven wrote:
>>>> In order to be able to use trace events, a key aspect is the "type" field;
>>>> this is the id of the event that you recorded, as stored in the /sys/kernel/debug/events/*/*/id file.
>>>> What is currently missing is a way to map the id number (which is not abi stable)
>>>> to the event that was recorded.
>>>
>>>
>>> We already have that.
>>> See tools/perf/util/parse-events.c: char *tracepoint_id_to_name(u64 id)
>>
>> sadly... we don't.
>>
>> You do it *on the same boot and machine* as you created the perf.data file.
>> You don't have it when you reboot into a new kernel, or move the perf.data file
>> to a new machine........
>>
>> Which is to be honest a very common usecase.
>
>
> Ah right... I always forget the offline report case.
> But you can at least reuse this existing helper to resolve
> the id to name.
>
ok I'll unstatic it, move it to a different file and ..
eh how about not?
this helper looks up an on disk id/name pair, and is private to it's existing file.
Fine.
The other one is based on the perf data, and all that is in header.c instead....
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: perf: store and retrieve trace event names in the perf.data file
2009-08-09 21:49 perf: store and retrieve trace event names in the perf.data file Arjan van de Ven
2009-08-09 22:44 ` Frederic Weisbecker
@ 2009-08-10 9:50 ` Peter Zijlstra
1 sibling, 0 replies; 6+ messages in thread
From: Peter Zijlstra @ 2009-08-10 9:50 UTC (permalink / raw)
To: Arjan van de Ven; +Cc: Ingo Molnar, Linux Kernel Mailing List
Thanks for the CC :-)
On Sun, 2009-08-09 at 14:49 -0700, Arjan van de Ven wrote:
> +static void store_event_type(const char *orgname)
> +{
> + char filename[PATH_MAX], *c;
> + FILE *file;
> + int id;
> +
> + sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
That should be using debugfs_path, as it stands this thing won't work on
any of my machines.
> + c = strchr(filename, ':');
> + if (c) *c = '/';
> +
> + file = fopen(filename, "r");
> + if (!file)
> + return;
> + fscanf(file, "%i", &id);
> + fclose(file);
> + perf_header__push_event(id, orgname);
> +}
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-08-10 9:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-09 21:49 perf: store and retrieve trace event names in the perf.data file Arjan van de Ven
2009-08-09 22:44 ` Frederic Weisbecker
2009-08-09 23:01 ` Arjan van de Ven
2009-08-09 23:04 ` Frederic Weisbecker
2009-08-09 23:10 ` Arjan van de Ven
2009-08-10 9:50 ` Peter Zijlstra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox