diff options
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r-- | tools/perf/builtin-report.c | 99 |
1 files changed, 67 insertions, 32 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f815de25d0fc..816edae7c5b2 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include "util/cache.h" | 14 | #include "util/cache.h" |
15 | #include <linux/rbtree.h> | 15 | #include <linux/rbtree.h> |
16 | #include "util/symbol.h" | 16 | #include "util/symbol.h" |
17 | #include "util/string.h" | ||
18 | #include "util/callchain.h" | 17 | #include "util/callchain.h" |
19 | #include "util/strlist.h" | 18 | #include "util/strlist.h" |
20 | #include "util/values.h" | 19 | #include "util/values.h" |
@@ -33,11 +32,11 @@ | |||
33 | 32 | ||
34 | static char const *input_name = "perf.data"; | 33 | static char const *input_name = "perf.data"; |
35 | 34 | ||
36 | static int force; | 35 | static bool force; |
37 | static bool hide_unresolved; | 36 | static bool hide_unresolved; |
38 | static bool dont_use_callchains; | 37 | static bool dont_use_callchains; |
39 | 38 | ||
40 | static int show_threads; | 39 | static bool show_threads; |
41 | static struct perf_read_values show_threads_values; | 40 | static struct perf_read_values show_threads_values; |
42 | 41 | ||
43 | static char default_pretty_printing_style[] = "normal"; | 42 | static char default_pretty_printing_style[] = "normal"; |
@@ -81,15 +80,20 @@ static int perf_session__add_hist_entry(struct perf_session *self, | |||
81 | struct addr_location *al, | 80 | struct addr_location *al, |
82 | struct sample_data *data) | 81 | struct sample_data *data) |
83 | { | 82 | { |
84 | struct symbol **syms = NULL, *parent = NULL; | 83 | struct map_symbol *syms = NULL; |
84 | struct symbol *parent = NULL; | ||
85 | bool hit; | 85 | bool hit; |
86 | int err; | ||
86 | struct hist_entry *he; | 87 | struct hist_entry *he; |
87 | struct event_stat_id *stats; | 88 | struct event_stat_id *stats; |
88 | struct perf_event_attr *attr; | 89 | struct perf_event_attr *attr; |
89 | 90 | ||
90 | if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) | 91 | if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) { |
91 | syms = perf_session__resolve_callchain(self, al->thread, | 92 | syms = perf_session__resolve_callchain(self, al->thread, |
92 | data->callchain, &parent); | 93 | data->callchain, &parent); |
94 | if (syms == NULL) | ||
95 | return -ENOMEM; | ||
96 | } | ||
93 | 97 | ||
94 | attr = perf_header__find_attr(data->id, &self->header); | 98 | attr = perf_header__find_attr(data->id, &self->header); |
95 | if (attr) | 99 | if (attr) |
@@ -104,13 +108,16 @@ static int perf_session__add_hist_entry(struct perf_session *self, | |||
104 | return -ENOMEM; | 108 | return -ENOMEM; |
105 | 109 | ||
106 | if (hit) | 110 | if (hit) |
107 | he->count += data->period; | 111 | __perf_session__add_count(he, al, data->period); |
108 | 112 | ||
109 | if (symbol_conf.use_callchain) { | 113 | if (symbol_conf.use_callchain) { |
110 | if (!hit) | 114 | if (!hit) |
111 | callchain_init(&he->callchain); | 115 | callchain_init(he->callchain); |
112 | append_chain(&he->callchain, data->callchain, syms); | 116 | err = append_chain(he->callchain, data->callchain, syms); |
113 | free(syms); | 117 | free(syms); |
118 | |||
119 | if (err) | ||
120 | return err; | ||
114 | } | 121 | } |
115 | 122 | ||
116 | return 0; | 123 | return 0; |
@@ -260,13 +267,27 @@ static struct perf_event_ops event_ops = { | |||
260 | .fork = event__process_task, | 267 | .fork = event__process_task, |
261 | .lost = event__process_lost, | 268 | .lost = event__process_lost, |
262 | .read = process_read_event, | 269 | .read = process_read_event, |
270 | .attr = event__process_attr, | ||
271 | .event_type = event__process_event_type, | ||
272 | .tracing_data = event__process_tracing_data, | ||
273 | .build_id = event__process_build_id, | ||
263 | }; | 274 | }; |
264 | 275 | ||
276 | extern volatile int session_done; | ||
277 | |||
278 | static void sig_handler(int sig __attribute__((__unused__))) | ||
279 | { | ||
280 | session_done = 1; | ||
281 | } | ||
282 | |||
265 | static int __cmd_report(void) | 283 | static int __cmd_report(void) |
266 | { | 284 | { |
267 | int ret = -EINVAL; | 285 | int ret = -EINVAL; |
268 | struct perf_session *session; | 286 | struct perf_session *session; |
269 | struct rb_node *next; | 287 | struct rb_node *next; |
288 | const char *help = "For a higher level overview, try: perf report --sort comm,dso"; | ||
289 | |||
290 | signal(SIGINT, sig_handler); | ||
270 | 291 | ||
271 | session = perf_session__new(input_name, O_RDONLY, force); | 292 | session = perf_session__new(input_name, O_RDONLY, force); |
272 | if (session == NULL) | 293 | if (session == NULL) |
@@ -292,39 +313,49 @@ static int __cmd_report(void) | |||
292 | perf_session__fprintf(session, stdout); | 313 | perf_session__fprintf(session, stdout); |
293 | 314 | ||
294 | if (verbose > 2) | 315 | if (verbose > 2) |
295 | dsos__fprintf(stdout); | 316 | dsos__fprintf(&session->kerninfo_root, stdout); |
296 | 317 | ||
297 | next = rb_first(&session->stats_by_id); | 318 | next = rb_first(&session->stats_by_id); |
298 | while (next) { | 319 | while (next) { |
299 | struct event_stat_id *stats; | 320 | struct event_stat_id *stats; |
321 | u64 nr_hists; | ||
300 | 322 | ||
301 | stats = rb_entry(next, struct event_stat_id, rb_node); | 323 | stats = rb_entry(next, struct event_stat_id, rb_node); |
302 | perf_session__collapse_resort(&stats->hists); | 324 | perf_session__collapse_resort(&stats->hists); |
303 | perf_session__output_resort(&stats->hists, stats->stats.total); | 325 | nr_hists = perf_session__output_resort(&stats->hists, |
304 | if (rb_first(&session->stats_by_id) == | 326 | stats->stats.total); |
305 | rb_last(&session->stats_by_id)) | 327 | if (use_browser) |
306 | fprintf(stdout, "# Samples: %Ld\n#\n", | 328 | perf_session__browse_hists(&stats->hists, nr_hists, |
307 | stats->stats.total); | 329 | stats->stats.total, help, |
308 | else | 330 | input_name); |
309 | fprintf(stdout, "# Samples: %Ld %s\n#\n", | 331 | else { |
310 | stats->stats.total, | 332 | if (rb_first(&session->stats_by_id) == |
311 | __event_name(stats->type, stats->config)); | 333 | rb_last(&session->stats_by_id)) |
312 | 334 | fprintf(stdout, "# Samples: %Ld\n#\n", | |
313 | perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, | 335 | stats->stats.total); |
336 | else | ||
337 | fprintf(stdout, "# Samples: %Ld %s\n#\n", | ||
338 | stats->stats.total, | ||
339 | __event_name(stats->type, stats->config)); | ||
340 | |||
341 | perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, | ||
314 | stats->stats.total); | 342 | stats->stats.total); |
315 | fprintf(stdout, "\n\n"); | 343 | fprintf(stdout, "\n\n"); |
344 | } | ||
345 | |||
316 | next = rb_next(&stats->rb_node); | 346 | next = rb_next(&stats->rb_node); |
317 | } | 347 | } |
318 | 348 | ||
319 | if (sort_order == default_sort_order && | 349 | if (!use_browser && sort_order == default_sort_order && |
320 | parent_pattern == default_parent_pattern) | 350 | parent_pattern == default_parent_pattern) { |
321 | fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n"); | 351 | fprintf(stdout, "#\n# (%s)\n#\n", help); |
322 | 352 | ||
323 | if (show_threads) { | 353 | if (show_threads) { |
324 | bool raw_printing_style = !strcmp(pretty_printing_style, "raw"); | 354 | bool style = !strcmp(pretty_printing_style, "raw"); |
325 | perf_read_values_display(stdout, &show_threads_values, | 355 | perf_read_values_display(stdout, &show_threads_values, |
326 | raw_printing_style); | 356 | style); |
327 | perf_read_values_destroy(&show_threads_values); | 357 | perf_read_values_destroy(&show_threads_values); |
358 | } | ||
328 | } | 359 | } |
329 | out_delete: | 360 | out_delete: |
330 | perf_session__delete(session); | 361 | perf_session__delete(session); |
@@ -400,7 +431,7 @@ static const char * const report_usage[] = { | |||
400 | static const struct option options[] = { | 431 | static const struct option options[] = { |
401 | OPT_STRING('i', "input", &input_name, "file", | 432 | OPT_STRING('i', "input", &input_name, "file", |
402 | "input file name"), | 433 | "input file name"), |
403 | OPT_BOOLEAN('v', "verbose", &verbose, | 434 | OPT_INCR('v', "verbose", &verbose, |
404 | "be more verbose (show symbol address, etc)"), | 435 | "be more verbose (show symbol address, etc)"), |
405 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 436 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
406 | "dump raw trace in ASCII"), | 437 | "dump raw trace in ASCII"), |
@@ -419,6 +450,8 @@ static const struct option options[] = { | |||
419 | "sort by key(s): pid, comm, dso, symbol, parent"), | 450 | "sort by key(s): pid, comm, dso, symbol, parent"), |
420 | OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths, | 451 | OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths, |
421 | "Don't shorten the pathnames taking into account the cwd"), | 452 | "Don't shorten the pathnames taking into account the cwd"), |
453 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | ||
454 | "Show sample percentage for different cpu modes"), | ||
422 | OPT_STRING('p', "parent", &parent_pattern, "regex", | 455 | OPT_STRING('p', "parent", &parent_pattern, "regex", |
423 | "regex filter to identify parent, see: '--sort parent'"), | 456 | "regex filter to identify parent, see: '--sort parent'"), |
424 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, | 457 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, |
@@ -447,7 +480,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
447 | { | 480 | { |
448 | argc = parse_options(argc, argv, options, report_usage, 0); | 481 | argc = parse_options(argc, argv, options, report_usage, 0); |
449 | 482 | ||
450 | setup_pager(); | 483 | if (strcmp(input_name, "-") != 0) |
484 | setup_browser(); | ||
451 | 485 | ||
452 | if (symbol__init() < 0) | 486 | if (symbol__init() < 0) |
453 | return -1; | 487 | return -1; |
@@ -455,7 +489,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
455 | setup_sorting(report_usage, options); | 489 | setup_sorting(report_usage, options); |
456 | 490 | ||
457 | if (parent_pattern != default_parent_pattern) { | 491 | if (parent_pattern != default_parent_pattern) { |
458 | sort_dimension__add("parent"); | 492 | if (sort_dimension__add("parent") < 0) |
493 | return -1; | ||
459 | sort_parent.elide = 1; | 494 | sort_parent.elide = 1; |
460 | } else | 495 | } else |
461 | symbol_conf.exclude_other = false; | 496 | symbol_conf.exclude_other = false; |