aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-03-05 19:40:06 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-03-06 11:13:40 -0500
commite248de331a452f8771eda6ed4bb30d92c82df28b (patch)
tree7ef04743a7bf7a1da354a3b82536ef32504823d9 /tools/perf/builtin-annotate.c
parent3d3b5e95997208067c963923db90ed1517565d14 (diff)
perf tools: Improve support for sessions with multiple events
By creating an perf_evlist out of the attributes in the perf.data file header, so that we can use evlists and evsels when reading recorded sessions in addition to when we record sessions. More work is needed to allow tools to allow the user to select which events are wanted when browsing sessions, be it just one or a subset of them, aggregated or showed at the same time but with different indications on the UI to allow seeing workloads thru different views at the same time. But the overall goal/trend is to more uniformly use evsels and evlists. 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>
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 427182953fd7..695de4b5ae63 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -19,6 +19,8 @@
19#include "perf.h" 19#include "perf.h"
20#include "util/debug.h" 20#include "util/debug.h"
21 21
22#include "util/evlist.h"
23#include "util/evsel.h"
22#include "util/annotate.h" 24#include "util/annotate.h"
23#include "util/event.h" 25#include "util/event.h"
24#include "util/parse-options.h" 26#include "util/parse-options.h"
@@ -38,9 +40,13 @@ static bool print_line;
38 40
39static const char *sym_hist_filter; 41static const char *sym_hist_filter;
40 42
41static int hists__add_entry(struct hists *self, struct addr_location *al) 43static int perf_evlist__add_sample(struct perf_evlist *evlist,
44 struct perf_sample *sample,
45 struct addr_location *al)
42{ 46{
47 struct perf_evsel *evsel;
43 struct hist_entry *he; 48 struct hist_entry *he;
49 int ret;
44 50
45 if (sym_hist_filter != NULL && 51 if (sym_hist_filter != NULL &&
46 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) { 52 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) {
@@ -53,23 +59,35 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
53 return 0; 59 return 0;
54 } 60 }
55 61
56 he = __hists__add_entry(self, al, NULL, 1); 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 he = __hists__add_entry(&evsel->hists, al, NULL, 1);
57 if (he == NULL) 75 if (he == NULL)
58 return -ENOMEM; 76 return -ENOMEM;
59 77
78 ret = 0;
60 if (he->ms.sym != NULL) { 79 if (he->ms.sym != NULL) {
61 /*
62 * All aggregated on the first sym_hist.
63 */
64 struct annotation *notes = symbol__annotation(he->ms.sym); 80 struct annotation *notes = symbol__annotation(he->ms.sym);
65 if (notes->src == NULL && 81 if (notes->src == NULL &&
66 symbol__alloc_hist(he->ms.sym, 1) < 0) 82 symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
67 return -ENOMEM; 83 return -ENOMEM;
68 84
69 return hist_entry__inc_addr_samples(he, 0, al->addr); 85 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
70 } 86 }
71 87
72 return 0; 88 evsel->hists.stats.total_period += sample->period;
89 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
90 return ret;
73} 91}
74 92
75static int process_sample_event(union perf_event *event, 93static int process_sample_event(union perf_event *event,
@@ -85,7 +103,7 @@ static int process_sample_event(union perf_event *event,
85 return -1; 103 return -1;
86 } 104 }
87 105
88 if (!al.filtered && hists__add_entry(&session->hists, &al)) { 106 if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) {
89 pr_warning("problem incrementing symbol count, " 107 pr_warning("problem incrementing symbol count, "
90 "skipping event\n"); 108 "skipping event\n");
91 return -1; 109 return -1;
@@ -100,7 +118,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
100 print_line, full_paths, 0, 0); 118 print_line, full_paths, 0, 0);
101} 119}
102 120
103static void hists__find_annotations(struct hists *self) 121static void hists__find_annotations(struct hists *self, int evidx)
104{ 122{
105 struct rb_node *nd = rb_first(&self->entries), *next; 123 struct rb_node *nd = rb_first(&self->entries), *next;
106 int key = KEY_RIGHT; 124 int key = KEY_RIGHT;
@@ -123,8 +141,7 @@ find_next:
123 } 141 }
124 142
125 if (use_browser > 0) { 143 if (use_browser > 0) {
126 /* For now all is aggregated on the first */ 144 key = hist_entry__tui_annotate(he, evidx);
127 key = hist_entry__tui_annotate(he, 0);
128 switch (key) { 145 switch (key) {
129 case KEY_RIGHT: 146 case KEY_RIGHT:
130 next = rb_next(nd); 147 next = rb_next(nd);
@@ -139,8 +156,7 @@ find_next:
139 if (next != NULL) 156 if (next != NULL)
140 nd = next; 157 nd = next;
141 } else { 158 } else {
142 /* For now all is aggregated on the first */ 159 hist_entry__tty_annotate(he, evidx);
143 hist_entry__tty_annotate(he, 0);
144 nd = rb_next(nd); 160 nd = rb_next(nd);
145 /* 161 /*
146 * Since we have a hist_entry per IP for the same 162 * Since we have a hist_entry per IP for the same
@@ -166,6 +182,8 @@ static int __cmd_annotate(void)
166{ 182{
167 int ret; 183 int ret;
168 struct perf_session *session; 184 struct perf_session *session;
185 struct perf_evsel *pos;
186 u64 total_nr_samples;
169 187
170 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 188 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
171 if (session == NULL) 189 if (session == NULL)
@@ -186,12 +204,36 @@ static int __cmd_annotate(void)
186 if (verbose > 2) 204 if (verbose > 2)
187 perf_session__fprintf_dsos(session, stdout); 205 perf_session__fprintf_dsos(session, stdout);
188 206
189 hists__collapse_resort(&session->hists); 207 total_nr_samples = 0;
190 hists__output_resort(&session->hists); 208 list_for_each_entry(pos, &session->evlist->entries, node) {
191 hists__find_annotations(&session->hists); 209 struct hists *hists = &pos->hists;
192out_delete: 210 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
193 perf_session__delete(session); 211
212 if (nr_samples > 0) {
213 total_nr_samples += nr_samples;
214 hists__collapse_resort(hists);
215 hists__output_resort(hists);
216 hists__find_annotations(hists, pos->idx);
217 }
218 }
194 219
220 if (total_nr_samples == 0) {
221 ui__warning("The %s file has no samples!\n", input_name);
222 goto out_delete;
223 }
224out_delete:
225 /*
226 * Speed up the exit process, for large files this can
227 * take quite a while.
228 *
229 * XXX Enable this when using valgrind or if we ever
230 * librarize this command.
231 *
232 * Also experiment with obstacks to see how much speed
233 * up we'll get here.
234 *
235 * perf_session__delete(session);
236 */
195 return ret; 237 return ret;
196} 238}
197 239