Commit 9e69c210822c4035708a6111567c96364ca244d5
1 parent
880f573184
Exists in
master
and in
39 other branches
perf session: Pass evsel in event_ops->sample()
Resolving the sample->id to an evsel since the most advanced tools, report and annotate, and the others will too when they evolve to properly support multi-event perf.data files. Good also because it does an extra validation, checking that the ID is valid when present. When that is not the case, the overhead is just a branch + function call (perf_evlist__id2evsel). Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Showing 17 changed files with 73 additions and 46 deletions Side-by-side Diff
- tools/perf/builtin-annotate.c
- tools/perf/builtin-diff.c
- tools/perf/builtin-inject.c
- tools/perf/builtin-kmem.c
- tools/perf/builtin-lock.c
- tools/perf/builtin-report.c
- tools/perf/builtin-sched.c
- tools/perf/builtin-script.c
- tools/perf/builtin-timechart.c
- tools/perf/util/build-id.c
- tools/perf/util/hist.h
- tools/perf/util/scripting-engines/trace-event-perl.c
- tools/perf/util/scripting-engines/trace-event-python.c
- tools/perf/util/session.c
- tools/perf/util/session.h
- tools/perf/util/trace-event-scripting.c
- tools/perf/util/trace-event.h
tools/perf/builtin-annotate.c
... | ... | @@ -42,9 +42,9 @@ |
42 | 42 | |
43 | 43 | static int perf_evlist__add_sample(struct perf_evlist *evlist, |
44 | 44 | struct perf_sample *sample, |
45 | + struct perf_evsel *evsel, | |
45 | 46 | struct addr_location *al) |
46 | 47 | { |
47 | - struct perf_evsel *evsel; | |
48 | 48 | struct hist_entry *he; |
49 | 49 | int ret; |
50 | 50 | |
... | ... | @@ -59,18 +59,6 @@ |
59 | 59 | return 0; |
60 | 60 | } |
61 | 61 | |
62 | - evsel = perf_evlist__id2evsel(evlist, sample->id); | |
63 | - if (evsel == NULL) { | |
64 | - /* | |
65 | - * FIXME: Propagate this back, but at least we're in a builtin, | |
66 | - * where exit() is allowed. ;-) | |
67 | - */ | |
68 | - ui__warning("Invalid %s file, contains samples with id not in " | |
69 | - "its header!\n", input_name); | |
70 | - exit_browser(0); | |
71 | - exit(1); | |
72 | - } | |
73 | - | |
74 | 62 | he = __hists__add_entry(&evsel->hists, al, NULL, 1); |
75 | 63 | if (he == NULL) |
76 | 64 | return -ENOMEM; |
... | ... | @@ -92,6 +80,7 @@ |
92 | 80 | |
93 | 81 | static int process_sample_event(union perf_event *event, |
94 | 82 | struct perf_sample *sample, |
83 | + struct perf_evsel *evsel, | |
95 | 84 | struct perf_session *session) |
96 | 85 | { |
97 | 86 | struct addr_location al; |
... | ... | @@ -103,7 +92,8 @@ |
103 | 92 | return -1; |
104 | 93 | } |
105 | 94 | |
106 | - if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) { | |
95 | + if (!al.filtered && | |
96 | + perf_evlist__add_sample(session->evlist, sample, evsel, &al)) { | |
107 | 97 | pr_warning("problem incrementing symbol count, " |
108 | 98 | "skipping event\n"); |
109 | 99 | return -1; |
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
... | ... | @@ -43,6 +43,14 @@ |
43 | 43 | return perf_event__repipe_synth(event, session); |
44 | 44 | } |
45 | 45 | |
46 | +static int perf_event__repipe_sample(union perf_event *event, | |
47 | + struct perf_sample *sample __used, | |
48 | + struct perf_evsel *evsel __used, | |
49 | + struct perf_session *session) | |
50 | +{ | |
51 | + return perf_event__repipe_synth(event, session); | |
52 | +} | |
53 | + | |
46 | 54 | static int perf_event__repipe_mmap(union perf_event *event, |
47 | 55 | struct perf_sample *sample, |
48 | 56 | struct perf_session *session) |
... | ... | @@ -124,6 +132,7 @@ |
124 | 132 | |
125 | 133 | static int perf_event__inject_buildid(union perf_event *event, |
126 | 134 | struct perf_sample *sample, |
135 | + struct perf_evsel *evsel __used, | |
127 | 136 | struct perf_session *session) |
128 | 137 | { |
129 | 138 | struct addr_location al; |
... | ... | @@ -164,7 +173,7 @@ |
164 | 173 | } |
165 | 174 | |
166 | 175 | struct perf_event_ops inject_ops = { |
167 | - .sample = perf_event__repipe, | |
176 | + .sample = perf_event__repipe_sample, | |
168 | 177 | .mmap = perf_event__repipe, |
169 | 178 | .comm = perf_event__repipe, |
170 | 179 | .fork = perf_event__repipe, |
tools/perf/builtin-kmem.c
... | ... | @@ -305,6 +305,7 @@ |
305 | 305 | |
306 | 306 | static int process_sample_event(union perf_event *event, |
307 | 307 | struct perf_sample *sample, |
308 | + struct perf_evsel *evsel __used, | |
308 | 309 | struct perf_session *session) |
309 | 310 | { |
310 | 311 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
tools/perf/builtin-lock.c
... | ... | @@ -845,7 +845,9 @@ |
845 | 845 | die("Unknown type of information\n"); |
846 | 846 | } |
847 | 847 | |
848 | -static int process_sample_event(union perf_event *event, struct perf_sample *sample, | |
848 | +static int process_sample_event(union perf_event *event, | |
849 | + struct perf_sample *sample, | |
850 | + struct perf_evsel *evsel __used, | |
849 | 851 | struct perf_session *s) |
850 | 852 | { |
851 | 853 | struct thread *thread = perf_session__findnew(s, sample->tid); |
tools/perf/builtin-report.c
... | ... | @@ -50,12 +50,12 @@ |
50 | 50 | |
51 | 51 | static int perf_session__add_hist_entry(struct perf_session *session, |
52 | 52 | struct addr_location *al, |
53 | - struct perf_sample *sample) | |
53 | + struct perf_sample *sample, | |
54 | + struct perf_evsel *evsel) | |
54 | 55 | { |
55 | 56 | struct symbol *parent = NULL; |
56 | 57 | int err = 0; |
57 | 58 | struct hist_entry *he; |
58 | - struct perf_evsel *evsel; | |
59 | 59 | |
60 | 60 | if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { |
61 | 61 | err = perf_session__resolve_callchain(session, al->thread, |
... | ... | @@ -64,18 +64,6 @@ |
64 | 64 | return err; |
65 | 65 | } |
66 | 66 | |
67 | - evsel = perf_evlist__id2evsel(session->evlist, sample->id); | |
68 | - if (evsel == NULL) { | |
69 | - /* | |
70 | - * FIXME: Propagate this back, but at least we're in a builtin, | |
71 | - * where exit() is allowed. ;-) | |
72 | - */ | |
73 | - ui__warning("Invalid %s file, contains samples with id %" PRIu64 " not in " | |
74 | - "its header!\n", input_name, sample->id); | |
75 | - exit_browser(0); | |
76 | - exit(1); | |
77 | - } | |
78 | - | |
79 | 67 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period); |
80 | 68 | if (he == NULL) |
81 | 69 | return -ENOMEM; |
... | ... | @@ -113,6 +101,7 @@ |
113 | 101 | |
114 | 102 | static int process_sample_event(union perf_event *event, |
115 | 103 | struct perf_sample *sample, |
104 | + struct perf_evsel *evsel, | |
116 | 105 | struct perf_session *session) |
117 | 106 | { |
118 | 107 | struct addr_location al; |
... | ... | @@ -127,7 +116,7 @@ |
127 | 116 | if (al.filtered || (hide_unresolved && al.sym == NULL)) |
128 | 117 | return 0; |
129 | 118 | |
130 | - if (perf_session__add_hist_entry(session, &al, sample)) { | |
119 | + if (perf_session__add_hist_entry(session, &al, sample, evsel)) { | |
131 | 120 | pr_debug("problem incrementing symbol period, skipping event\n"); |
132 | 121 | return -1; |
133 | 122 | } |
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
... | ... | @@ -162,20 +162,12 @@ |
162 | 162 | |
163 | 163 | static void process_event(union perf_event *event __unused, |
164 | 164 | struct perf_sample *sample, |
165 | + struct perf_evsel *evsel, | |
165 | 166 | struct perf_session *session, |
166 | 167 | struct thread *thread) |
167 | 168 | { |
168 | - struct perf_event_attr *attr; | |
169 | - struct perf_evsel *evsel; | |
169 | + struct perf_event_attr *attr = &evsel->attr; | |
170 | 170 | |
171 | - evsel = perf_evlist__id2evsel(session->evlist, sample->id); | |
172 | - if (evsel == NULL) { | |
173 | - pr_err("Invalid data. Contains samples with id not in " | |
174 | - "its header!\n"); | |
175 | - return; | |
176 | - } | |
177 | - attr = &evsel->attr; | |
178 | - | |
179 | 171 | if (output_fields[attr->type] == 0) |
180 | 172 | return; |
181 | 173 | |
... | ... | @@ -244,6 +236,7 @@ |
244 | 236 | |
245 | 237 | static int process_sample_event(union perf_event *event, |
246 | 238 | struct perf_sample *sample, |
239 | + struct perf_evsel *evsel, | |
247 | 240 | struct perf_session *session) |
248 | 241 | { |
249 | 242 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
... | ... | @@ -264,7 +257,7 @@ |
264 | 257 | last_timestamp = sample->time; |
265 | 258 | return 0; |
266 | 259 | } |
267 | - scripting_ops->process_event(event, sample, session, thread); | |
260 | + scripting_ops->process_event(event, sample, evsel, session, thread); | |
268 | 261 | |
269 | 262 | session->hists.stats.total_period += sample->period; |
270 | 263 | return 0; |
tools/perf/builtin-timechart.c
... | ... | @@ -488,6 +488,7 @@ |
488 | 488 | |
489 | 489 | static int process_sample_event(union perf_event *event __used, |
490 | 490 | struct perf_sample *sample, |
491 | + struct perf_evsel *evsel __used, | |
491 | 492 | struct perf_session *session) |
492 | 493 | { |
493 | 494 | struct trace_entry *te; |
... | ... | @@ -506,6 +507,16 @@ |
506 | 507 | struct power_entry_old *peo; |
507 | 508 | peo = (void *)te; |
508 | 509 | #endif |
510 | + /* | |
511 | + * FIXME: use evsel, its already mapped from id to perf_evsel, | |
512 | + * remove perf_header__find_event infrastructure bits. | |
513 | + * Mapping all these "power:cpu_idle" strings to the tracepoint | |
514 | + * ID and then just comparing against evsel->attr.config. | |
515 | + * | |
516 | + * e.g.: | |
517 | + * | |
518 | + * if (evsel->attr.config == power_cpu_idle_id) | |
519 | + */ | |
509 | 520 | event_str = perf_header__find_event(te->type); |
510 | 521 | |
511 | 522 | if (!event_str) |
tools/perf/util/build-id.c
tools/perf/util/hist.h
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
... | ... | @@ -280,6 +280,15 @@ |
280 | 280 | return 0; |
281 | 281 | } |
282 | 282 | |
283 | +static int process_event_sample_stub(union perf_event *event __used, | |
284 | + struct perf_sample *sample __used, | |
285 | + struct perf_evsel *evsel __used, | |
286 | + struct perf_session *session __used) | |
287 | +{ | |
288 | + dump_printf(": unhandled!\n"); | |
289 | + return 0; | |
290 | +} | |
291 | + | |
283 | 292 | static int process_event_stub(union perf_event *event __used, |
284 | 293 | struct perf_sample *sample __used, |
285 | 294 | struct perf_session *session __used) |
... | ... | @@ -303,7 +312,7 @@ |
303 | 312 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) |
304 | 313 | { |
305 | 314 | if (handler->sample == NULL) |
306 | - handler->sample = process_event_stub; | |
315 | + handler->sample = process_event_sample_stub; | |
307 | 316 | if (handler->mmap == NULL) |
308 | 317 | handler->mmap = process_event_stub; |
309 | 318 | if (handler->comm == NULL) |
310 | 319 | |
... | ... | @@ -698,12 +707,19 @@ |
698 | 707 | struct perf_event_ops *ops, |
699 | 708 | u64 file_offset) |
700 | 709 | { |
710 | + struct perf_evsel *evsel; | |
711 | + | |
701 | 712 | dump_event(session, event, file_offset, sample); |
702 | 713 | |
703 | 714 | switch (event->header.type) { |
704 | 715 | case PERF_RECORD_SAMPLE: |
705 | 716 | dump_sample(session, event, sample); |
706 | - return ops->sample(event, sample, session); | |
717 | + evsel = perf_evlist__id2evsel(session->evlist, sample->id); | |
718 | + if (evsel == NULL) { | |
719 | + ++session->hists.stats.nr_unknown_id; | |
720 | + return -1; | |
721 | + } | |
722 | + return ops->sample(event, sample, evsel, session); | |
707 | 723 | case PERF_RECORD_MMAP: |
708 | 724 | return ops->mmap(event, sample, session); |
709 | 725 | case PERF_RECORD_COMM: |
... | ... | @@ -843,6 +859,11 @@ |
843 | 859 | "If that is not the case, consider " |
844 | 860 | "reporting to linux-kernel@vger.kernel.org.\n\n", |
845 | 861 | session->hists.stats.nr_unknown_events); |
862 | + } | |
863 | + | |
864 | + if (session->hists.stats.nr_unknown_id != 0) { | |
865 | + ui__warning("%u samples with id not present in the header\n", | |
866 | + session->hists.stats.nr_unknown_id); | |
846 | 867 | } |
847 | 868 | |
848 | 869 | if (session->hists.stats.nr_invalid_chains != 0) { |
tools/perf/util/session.h
... | ... | @@ -55,8 +55,11 @@ |
55 | 55 | char filename[0]; |
56 | 56 | }; |
57 | 57 | |
58 | +struct perf_evsel; | |
58 | 59 | struct perf_event_ops; |
59 | 60 | |
61 | +typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample, | |
62 | + struct perf_evsel *evsel, struct perf_session *session); | |
60 | 63 | typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, |
61 | 64 | struct perf_session *session); |
62 | 65 | typedef int (*event_synth_op)(union perf_event *self, |
... | ... | @@ -65,8 +68,8 @@ |
65 | 68 | struct perf_event_ops *ops); |
66 | 69 | |
67 | 70 | struct perf_event_ops { |
68 | - event_op sample, | |
69 | - mmap, | |
71 | + event_sample sample; | |
72 | + event_op mmap, | |
70 | 73 | comm, |
71 | 74 | fork, |
72 | 75 | exit, |
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.h
... | ... | @@ -280,6 +280,7 @@ |
280 | 280 | int (*stop_script) (void); |
281 | 281 | void (*process_event) (union perf_event *event, |
282 | 282 | struct perf_sample *sample, |
283 | + struct perf_evsel *evsel, | |
283 | 284 | struct perf_session *session, |
284 | 285 | struct thread *thread); |
285 | 286 | int (*generate_script) (const char *outfile); |