aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c99
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
34static char const *input_name = "perf.data"; 33static char const *input_name = "perf.data";
35 34
36static int force; 35static bool force;
37static bool hide_unresolved; 36static bool hide_unresolved;
38static bool dont_use_callchains; 37static bool dont_use_callchains;
39 38
40static int show_threads; 39static bool show_threads;
41static struct perf_read_values show_threads_values; 40static struct perf_read_values show_threads_values;
42 41
43static char default_pretty_printing_style[] = "normal"; 42static 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
276extern volatile int session_done;
277
278static void sig_handler(int sig __attribute__((__unused__)))
279{
280 session_done = 1;
281}
282
265static int __cmd_report(void) 283static 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 }
329out_delete: 360out_delete:
330 perf_session__delete(session); 361 perf_session__delete(session);
@@ -400,7 +431,7 @@ static const char * const report_usage[] = {
400static const struct option options[] = { 431static 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;