aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-02-03 13:52:05 -0500
committerIngo Molnar <mingo@elte.hu>2010-02-04 03:33:27 -0500
commit6122e4e4f5d0913e319ef8a4dc60a47afe4abc0a (patch)
tree77e8995f360f3cb3a8f7c392708ccf58836b0573
parent7b2567c1f57c059de29d3f2ca03aca84473865c8 (diff)
perf record: Stop intercepting events, use postprocessing to get build-ids
We want to stream events as fast as possible to perf.data, and also in the future we want to have splice working, when no interception will be possible. Using build_id__mark_dso_hit_ops to create the list of DSOs that back MMAPs we also optimize disk usage in the build-id cache by only caching DSOs that had hits. Suggested-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1265223128-11786-6-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-record.c37
-rw-r--r--tools/perf/util/header.c7
-rw-r--r--tools/perf/util/session.c64
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/symbol.c13
-rw-r--r--tools/perf/util/symbol.h2
6 files changed, 73 insertions, 53 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 949167efa1ed..706f00196b87 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -12,6 +12,7 @@
12 12
13#include "perf.h" 13#include "perf.h"
14 14
15#include "util/build-id.h"
15#include "util/util.h" 16#include "util/util.h"
16#include "util/parse-options.h" 17#include "util/parse-options.h"
17#include "util/parse-events.h" 18#include "util/parse-events.h"
@@ -65,6 +66,7 @@ static int nr_poll = 0;
65static int nr_cpu = 0; 66static int nr_cpu = 0;
66 67
67static int file_new = 1; 68static int file_new = 1;
69static off_t post_processing_offset;
68 70
69static struct perf_session *session; 71static struct perf_session *session;
70 72
@@ -114,26 +116,10 @@ static void write_output(void *buf, size_t size)
114 } 116 }
115} 117}
116 118
117static void write_event(event_t *buf, size_t size)
118{
119 /*
120 * Add it to the list of DSOs, so that when we finish this
121 * record session we can pick the available build-ids.
122 */
123 if (buf->header.type == PERF_RECORD_MMAP) {
124 struct list_head *head = &dsos__user;
125 if (buf->mmap.header.misc == 1)
126 head = &dsos__kernel;
127 __dsos__findnew(head, buf->mmap.filename);
128 }
129
130 write_output(buf, size);
131}
132
133static int process_synthesized_event(event_t *event, 119static int process_synthesized_event(event_t *event,
134 struct perf_session *self __used) 120 struct perf_session *self __used)
135{ 121{
136 write_event(event, event->header.size); 122 write_output(event, event->header.size);
137 return 0; 123 return 0;
138} 124}
139 125
@@ -185,14 +171,14 @@ static void mmap_read(struct mmap_data *md)
185 size = md->mask + 1 - (old & md->mask); 171 size = md->mask + 1 - (old & md->mask);
186 old += size; 172 old += size;
187 173
188 write_event(buf, size); 174 write_output(buf, size);
189 } 175 }
190 176
191 buf = &data[old & md->mask]; 177 buf = &data[old & md->mask];
192 size = head - old; 178 size = head - old;
193 old += size; 179 old += size;
194 180
195 write_event(buf, size); 181 write_output(buf, size);
196 182
197 md->prev = old; 183 md->prev = old;
198 mmap_write_tail(md, old); 184 mmap_write_tail(md, old);
@@ -402,10 +388,21 @@ static void open_counters(int cpu, pid_t pid)
402 nr_cpu++; 388 nr_cpu++;
403} 389}
404 390
391static int process_buildids(void)
392{
393 u64 size = lseek(output, 0, SEEK_CUR);
394
395 session->fd = output;
396 return __perf_session__process_events(session, post_processing_offset,
397 size - post_processing_offset,
398 size, &build_id__mark_dso_hit_ops);
399}
400
405static void atexit_header(void) 401static void atexit_header(void)
406{ 402{
407 session->header.data_size += bytes_written; 403 session->header.data_size += bytes_written;
408 404
405 process_buildids();
409 perf_header__write(&session->header, output, true); 406 perf_header__write(&session->header, output, true);
410} 407}
411 408
@@ -558,6 +555,8 @@ static int __cmd_record(int argc, const char **argv)
558 return err; 555 return err;
559 } 556 }
560 557
558 post_processing_offset = lseek(output, 0, SEEK_CUR);
559
561 err = event__synthesize_kernel_mmap(process_synthesized_event, 560 err = event__synthesize_kernel_mmap(process_synthesized_event,
562 session, "_text"); 561 session, "_text");
563 if (err < 0) { 562 if (err < 0) {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ed3efd728b41..d5facd5ab1f7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -205,8 +205,11 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd)
205 dsos__for_each_with_build_id(pos, head) { 205 dsos__for_each_with_build_id(pos, head) {
206 int err; 206 int err;
207 struct build_id_event b; 207 struct build_id_event b;
208 size_t len = pos->long_name_len + 1; 208 size_t len;
209 209
210 if (!pos->hit)
211 continue;
212 len = pos->long_name_len + 1;
210 len = ALIGN(len, NAME_ALIGN); 213 len = ALIGN(len, NAME_ALIGN);
211 memset(&b, 0, sizeof(b)); 214 memset(&b, 0, sizeof(b));
212 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 215 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
@@ -371,7 +374,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
371 u64 sec_start; 374 u64 sec_start;
372 int idx = 0, err; 375 int idx = 0, err;
373 376
374 if (dsos__read_build_ids()) 377 if (dsos__read_build_ids(true))
375 perf_header__set_feat(self, HEADER_BUILD_ID); 378 perf_header__set_feat(self, HEADER_BUILD_ID);
376 379
377 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 380 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index aa8a03120bbd..74cbc64a3a3c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -385,8 +385,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
385 return thread; 385 return thread;
386} 386}
387 387
388int perf_session__process_events(struct perf_session *self, 388int __perf_session__process_events(struct perf_session *self,
389 struct perf_event_ops *ops) 389 u64 data_offset, u64 data_size,
390 u64 file_size, struct perf_event_ops *ops)
390{ 391{
391 int err, mmap_prot, mmap_flags; 392 int err, mmap_prot, mmap_flags;
392 u64 head, shift; 393 u64 head, shift;
@@ -396,32 +397,11 @@ int perf_session__process_events(struct perf_session *self,
396 uint32_t size; 397 uint32_t size;
397 char *buf; 398 char *buf;
398 399
399 if (perf_session__register_idle_thread(self) == NULL)
400 return -ENOMEM;
401
402 perf_event_ops__fill_defaults(ops); 400 perf_event_ops__fill_defaults(ops);
403 401
404 page_size = sysconf(_SC_PAGESIZE); 402 page_size = sysconf(_SC_PAGESIZE);
405 403
406 head = self->header.data_offset; 404 head = data_offset;
407
408 if (!symbol_conf.full_paths) {
409 char bf[PATH_MAX];
410
411 if (getcwd(bf, sizeof(bf)) == NULL) {
412 err = -errno;
413out_getcwd_err:
414 pr_err("failed to get the current directory\n");
415 goto out_err;
416 }
417 self->cwd = strdup(bf);
418 if (self->cwd == NULL) {
419 err = -ENOMEM;
420 goto out_getcwd_err;
421 }
422 self->cwdlen = strlen(self->cwd);
423 }
424
425 shift = page_size * (head / page_size); 405 shift = page_size * (head / page_size);
426 offset += shift; 406 offset += shift;
427 head -= shift; 407 head -= shift;
@@ -486,10 +466,10 @@ more:
486 466
487 head += size; 467 head += size;
488 468
489 if (offset + head >= self->header.data_offset + self->header.data_size) 469 if (offset + head >= data_offset + data_size)
490 goto done; 470 goto done;
491 471
492 if (offset + head < self->size) 472 if (offset + head < file_size)
493 goto more; 473 goto more;
494done: 474done:
495 err = 0; 475 err = 0;
@@ -497,6 +477,38 @@ out_err:
497 return err; 477 return err;
498} 478}
499 479
480int perf_session__process_events(struct perf_session *self,
481 struct perf_event_ops *ops)
482{
483 int err;
484
485 if (perf_session__register_idle_thread(self) == NULL)
486 return -ENOMEM;
487
488 if (!symbol_conf.full_paths) {
489 char bf[PATH_MAX];
490
491 if (getcwd(bf, sizeof(bf)) == NULL) {
492 err = -errno;
493out_getcwd_err:
494 pr_err("failed to get the current directory\n");
495 goto out_err;
496 }
497 self->cwd = strdup(bf);
498 if (self->cwd == NULL) {
499 err = -ENOMEM;
500 goto out_getcwd_err;
501 }
502 self->cwdlen = strlen(self->cwd);
503 }
504
505 err = __perf_session__process_events(self, self->header.data_offset,
506 self->header.data_size,
507 self->size, ops);
508out_err:
509 return err;
510}
511
500bool perf_session__has_traces(struct perf_session *self, const char *msg) 512bool perf_session__has_traces(struct perf_session *self, const char *msg)
501{ 513{
502 if (!(self->sample_type & PERF_SAMPLE_RAW)) { 514 if (!(self->sample_type & PERF_SAMPLE_RAW)) {
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 752d75aebade..31950fcd8a4d 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -50,6 +50,9 @@ void perf_session__delete(struct perf_session *self);
50 50
51void perf_event_header__bswap(struct perf_event_header *self); 51void perf_event_header__bswap(struct perf_event_header *self);
52 52
53int __perf_session__process_events(struct perf_session *self,
54 u64 data_offset, u64 data_size, u64 size,
55 struct perf_event_ops *ops);
53int perf_session__process_events(struct perf_session *self, 56int perf_session__process_events(struct perf_session *self,
54 struct perf_event_ops *event_ops); 57 struct perf_event_ops *event_ops);
55 58
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e752837363ee..bfb055459670 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1076,25 +1076,28 @@ static bool dso__build_id_equal(const struct dso *self, u8 *build_id)
1076 return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; 1076 return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0;
1077} 1077}
1078 1078
1079static bool __dsos__read_build_ids(struct list_head *head) 1079static bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1080{ 1080{
1081 bool have_build_id = false; 1081 bool have_build_id = false;
1082 struct dso *pos; 1082 struct dso *pos;
1083 1083
1084 list_for_each_entry(pos, head, node) 1084 list_for_each_entry(pos, head, node) {
1085 if (with_hits && !pos->hit)
1086 continue;
1085 if (filename__read_build_id(pos->long_name, pos->build_id, 1087 if (filename__read_build_id(pos->long_name, pos->build_id,
1086 sizeof(pos->build_id)) > 0) { 1088 sizeof(pos->build_id)) > 0) {
1087 have_build_id = true; 1089 have_build_id = true;
1088 pos->has_build_id = true; 1090 pos->has_build_id = true;
1089 } 1091 }
1092 }
1090 1093
1091 return have_build_id; 1094 return have_build_id;
1092} 1095}
1093 1096
1094bool dsos__read_build_ids(void) 1097bool dsos__read_build_ids(bool with_hits)
1095{ 1098{
1096 bool kbuildids = __dsos__read_build_ids(&dsos__kernel), 1099 bool kbuildids = __dsos__read_build_ids(&dsos__kernel, with_hits),
1097 ubuildids = __dsos__read_build_ids(&dsos__user); 1100 ubuildids = __dsos__read_build_ids(&dsos__user, with_hits);
1098 return kbuildids || ubuildids; 1101 return kbuildids || ubuildids;
1099} 1102}
1100 1103
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e90568a9e467..1b4192ee5300 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -157,7 +157,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
157 157
158int filename__read_build_id(const char *filename, void *bf, size_t size); 158int filename__read_build_id(const char *filename, void *bf, size_t size);
159int sysfs__read_build_id(const char *filename, void *bf, size_t size); 159int sysfs__read_build_id(const char *filename, void *bf, size_t size);
160bool dsos__read_build_ids(void); 160bool dsos__read_build_ids(bool with_hits);
161int build_id__sprintf(const u8 *self, int len, char *bf); 161int build_id__sprintf(const u8 *self, int len, char *bf);
162int kallsyms__parse(const char *filename, void *arg, 162int kallsyms__parse(const char *filename, void *arg,
163 int (*process_symbol)(void *arg, const char *name, 163 int (*process_symbol)(void *arg, const char *name,