diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2009-12-01 01:04:49 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-01 02:14:08 -0500 |
commit | bab81b624e970f1138535a465ad2b26b6bb0dd6c (patch) | |
tree | 4e62c0dd293b18c7bc1593437e2a6fd18e811b5b /tools/perf | |
parent | 1ed091c45ae33b2179d387573c3fe3f3b4adf60a (diff) |
perf annotate: Fix perf data parsing
perf-annotate doesn't parse perf.data correctly in that it
doesn't read perf header. Fix this by using
mmap_dispatch_perf_file().
Before:
TOTAL events: 17565
MMAP events: 3221
LOST events: 10
COMM events: 235
EXIT events: 2
THROTTLE events: 1
UNTHROTTLE events: 2
FORK events: 10
READ events: 1
SAMPLE events: 14083
After:
TOTAL events: 17290
MMAP events: 3203
LOST events: 0
COMM events: 234
EXIT events: 1
THROTTLE events: 0
UNTHROTTLE events: 0
FORK events: 0
READ events: 0
SAMPLE events: 13852
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arjan van de Ven <arjan@infradead.org>
LKML-Reference: <4B14B201.9030708@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-annotate.c | 143 | ||||
-rw-r--r-- | tools/perf/util/event.c | 3 |
2 files changed, 19 insertions, 127 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 7f85c6e159a4..0bf2e8f9af57 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -25,19 +25,16 @@ | |||
25 | #include "util/thread.h" | 25 | #include "util/thread.h" |
26 | #include "util/sort.h" | 26 | #include "util/sort.h" |
27 | #include "util/hist.h" | 27 | #include "util/hist.h" |
28 | #include "util/data_map.h" | ||
28 | 29 | ||
29 | static char const *input_name = "perf.data"; | 30 | static char const *input_name = "perf.data"; |
30 | 31 | ||
31 | static int force; | 32 | static int force; |
32 | static int input; | ||
33 | 33 | ||
34 | static int full_paths; | 34 | static int full_paths; |
35 | 35 | ||
36 | static int print_line; | 36 | static int print_line; |
37 | 37 | ||
38 | static unsigned long page_size; | ||
39 | static unsigned long mmap_window = 32; | ||
40 | |||
41 | struct sym_hist { | 38 | struct sym_hist { |
42 | u64 sum; | 39 | u64 sum; |
43 | u64 ip[0]; | 40 | u64 ip[0]; |
@@ -156,35 +153,6 @@ static int process_sample_event(event_t *event) | |||
156 | return 0; | 153 | return 0; |
157 | } | 154 | } |
158 | 155 | ||
159 | static int event__process(event_t *self) | ||
160 | { | ||
161 | switch (self->header.type) { | ||
162 | case PERF_RECORD_SAMPLE: | ||
163 | return process_sample_event(self); | ||
164 | |||
165 | case PERF_RECORD_MMAP: | ||
166 | return event__process_mmap(self); | ||
167 | |||
168 | case PERF_RECORD_COMM: | ||
169 | return event__process_comm(self); | ||
170 | |||
171 | case PERF_RECORD_FORK: | ||
172 | return event__process_task(self); | ||
173 | /* | ||
174 | * We dont process them right now but they are fine: | ||
175 | */ | ||
176 | |||
177 | case PERF_RECORD_THROTTLE: | ||
178 | case PERF_RECORD_UNTHROTTLE: | ||
179 | return 0; | ||
180 | |||
181 | default: | ||
182 | return -1; | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int parse_line(FILE *file, struct hist_entry *he, u64 len) | 156 | static int parse_line(FILE *file, struct hist_entry *he, u64 len) |
189 | { | 157 | { |
190 | struct symbol *sym = he->sym; | 158 | struct symbol *sym = he->sym; |
@@ -485,99 +453,26 @@ static void find_annotations(void) | |||
485 | } | 453 | } |
486 | } | 454 | } |
487 | 455 | ||
456 | static struct perf_file_handler file_handler = { | ||
457 | .process_sample_event = process_sample_event, | ||
458 | .process_mmap_event = event__process_mmap, | ||
459 | .process_comm_event = event__process_comm, | ||
460 | .process_fork_event = event__process_task, | ||
461 | }; | ||
462 | |||
488 | static int __cmd_annotate(void) | 463 | static int __cmd_annotate(void) |
489 | { | 464 | { |
490 | int ret, rc = EXIT_FAILURE; | 465 | struct perf_header *header; |
491 | unsigned long offset = 0; | 466 | struct thread *idle; |
492 | unsigned long head = 0; | 467 | int ret; |
493 | struct stat input_stat; | ||
494 | event_t *event; | ||
495 | uint32_t size; | ||
496 | char *buf; | ||
497 | |||
498 | register_idle_thread(); | ||
499 | |||
500 | input = open(input_name, O_RDONLY); | ||
501 | if (input < 0) { | ||
502 | perror("failed to open file"); | ||
503 | exit(-1); | ||
504 | } | ||
505 | |||
506 | ret = fstat(input, &input_stat); | ||
507 | if (ret < 0) { | ||
508 | perror("failed to stat file"); | ||
509 | exit(-1); | ||
510 | } | ||
511 | |||
512 | if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { | ||
513 | fprintf(stderr, "file: %s not owned by current user or root\n", input_name); | ||
514 | exit(-1); | ||
515 | } | ||
516 | |||
517 | if (!input_stat.st_size) { | ||
518 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | ||
519 | exit(0); | ||
520 | } | ||
521 | |||
522 | remap: | ||
523 | buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, | ||
524 | MAP_SHARED, input, offset); | ||
525 | if (buf == MAP_FAILED) { | ||
526 | perror("failed to mmap file"); | ||
527 | exit(-1); | ||
528 | } | ||
529 | |||
530 | more: | ||
531 | event = (event_t *)(buf + head); | ||
532 | |||
533 | size = event->header.size; | ||
534 | if (!size) | ||
535 | size = 8; | ||
536 | |||
537 | if (head + event->header.size >= page_size * mmap_window) { | ||
538 | unsigned long shift = page_size * (head / page_size); | ||
539 | int munmap_ret; | ||
540 | |||
541 | munmap_ret = munmap(buf, page_size * mmap_window); | ||
542 | assert(munmap_ret == 0); | ||
543 | |||
544 | offset += shift; | ||
545 | head -= shift; | ||
546 | goto remap; | ||
547 | } | ||
548 | |||
549 | size = event->header.size; | ||
550 | |||
551 | dump_printf("%p [%p]: event: %d\n", | ||
552 | (void *)(offset + head), | ||
553 | (void *)(long)event->header.size, | ||
554 | event->header.type); | ||
555 | |||
556 | if (!size || event__process(event) < 0) { | ||
557 | |||
558 | dump_printf("%p [%p]: skipping unknown header type: %d\n", | ||
559 | (void *)(offset + head), | ||
560 | (void *)(long)(event->header.size), | ||
561 | event->header.type); | ||
562 | /* | ||
563 | * assume we lost track of the stream, check alignment, and | ||
564 | * increment a single u64 in the hope to catch on again 'soon'. | ||
565 | */ | ||
566 | |||
567 | if (unlikely(head & 7)) | ||
568 | head &= ~7ULL; | ||
569 | |||
570 | size = 8; | ||
571 | } | ||
572 | |||
573 | head += size; | ||
574 | |||
575 | if (offset + head < (unsigned long)input_stat.st_size) | ||
576 | goto more; | ||
577 | 468 | ||
578 | rc = EXIT_SUCCESS; | 469 | idle = register_idle_thread(); |
579 | close(input); | 470 | register_perf_file_handler(&file_handler); |
580 | 471 | ||
472 | ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, | ||
473 | &event__cwdlen, &event__cwd); | ||
474 | if (ret) | ||
475 | return ret; | ||
581 | 476 | ||
582 | if (dump_trace) { | 477 | if (dump_trace) { |
583 | event__print_totals(); | 478 | event__print_totals(); |
@@ -595,7 +490,7 @@ more: | |||
595 | 490 | ||
596 | find_annotations(); | 491 | find_annotations(); |
597 | 492 | ||
598 | return rc; | 493 | return ret; |
599 | } | 494 | } |
600 | 495 | ||
601 | static const char * const annotate_usage[] = { | 496 | static const char * const annotate_usage[] = { |
@@ -644,8 +539,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
644 | if (symbol__init(&symbol_conf) < 0) | 539 | if (symbol__init(&symbol_conf) < 0) |
645 | return -1; | 540 | return -1; |
646 | 541 | ||
647 | page_size = getpagesize(); | ||
648 | |||
649 | argc = parse_options(argc, argv, options, annotate_usage, 0); | 542 | argc = parse_options(argc, argv, options, annotate_usage, 0); |
650 | 543 | ||
651 | setup_sorting(); | 544 | setup_sorting(); |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 233d7ad9bd7f..414b89d1bde9 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -186,8 +186,7 @@ int event__process_comm(event_t *self) | |||
186 | { | 186 | { |
187 | struct thread *thread = threads__findnew(self->comm.pid); | 187 | struct thread *thread = threads__findnew(self->comm.pid); |
188 | 188 | ||
189 | dump_printf("PERF_RECORD_COMM: %s:%d\n", | 189 | dump_printf(": %s:%d\n", self->comm.comm, self->comm.pid); |
190 | self->comm.comm, self->comm.pid); | ||
191 | 190 | ||
192 | if (thread == NULL || thread__set_comm(thread, self->comm.comm)) { | 191 | if (thread == NULL || thread__set_comm(thread, self->comm.comm)) { |
193 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); | 192 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); |