aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-12-15 17:04:41 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-16 02:53:49 -0500
commitc410a33887c17cac95ed8b0d860cdfb5c087a7d8 (patch)
tree54fe6ed5ac64ff77763ff686af58bd36b04e73d6 /tools
parent655000e7c75a559681ee7f15f6fa870c80ae3194 (diff)
perf symbols: Move symbol filtering to event__preprocess_sample()
So that --dsos, --comm, --symbols can bem used in more tools, like in perf diff: $ perf record -f find / > /dev/null $ perf record -f find / > /dev/null $ perf diff --dsos /lib64/libc-2.10.1.so | head -5 1 +22392124 /lib64/libc-2.10.1.so _IO_vfprintf_internal 2 +6410655 /lib64/libc-2.10.1.so __GI_memmove 3 +1 +9192692 /lib64/libc-2.10.1.so _int_malloc 4 -1 -15158605 /lib64/libc-2.10.1.so _int_free 5 +45669 /lib64/libc-2.10.1.so _IO_new_file_xsputn $ Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1260914682-29652-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-diff.c19
-rw-r--r--tools/perf/builtin-report.c86
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/util/event.c42
-rw-r--r--tools/perf/util/symbol.c5
-rw-r--r--tools/perf/util/symbol.h4
7 files changed, 84 insertions, 76 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 645d58058431..593ff25006de 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -141,7 +141,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
141 return -1; 141 return -1;
142 } 142 }
143 143
144 if (perf_session__add_hist_entry(session, &al, 1)) { 144 if (!al.filtered && perf_session__add_hist_entry(session, &al, 1)) {
145 fprintf(stderr, "problem incrementing symbol count, " 145 fprintf(stderr, "problem incrementing symbol count, "
146 "skipping event\n"); 146 "skipping event\n");
147 return -1; 147 return -1;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 4fde60655341..ff91e9c291bb 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -50,6 +50,9 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
50 return -1; 50 return -1;
51 } 51 }
52 52
53 if (al.filtered)
54 return 0;
55
53 event__parse_sample(event, session->sample_type, &data); 56 event__parse_sample(event, session->sample_type, &data);
54 57
55 if (al.sym && perf_session__add_hist_entry(session, &al, data.period)) { 58 if (al.sym && perf_session__add_hist_entry(session, &al, data.period)) {
@@ -182,10 +185,14 @@ blank: memset(displacement, ' ', sizeof(displacement));
182 printed = fprintf(fp, "%4lu %5.5s ", pos, displacement); 185 printed = fprintf(fp, "%4lu %5.5s ", pos, displacement);
183 186
184 if (show_percent) { 187 if (show_percent) {
185 double old_percent = (old_count * 100) / pair_session->events_stats.total, 188 double old_percent = 0, new_percent = 0, diff;
186 new_percent = (self->count * 100) / session->events_stats.total; 189
187 double diff = old_percent - new_percent; 190 if (pair_session->events_stats.total > 0)
191 old_percent = (old_count * 100) / pair_session->events_stats.total;
192 if (session->events_stats.total > 0)
193 new_percent = (self->count * 100) / session->events_stats.total;
188 194
195 diff = old_percent - new_percent;
189 if (verbose) 196 if (verbose)
190 printed += fprintf(fp, " %3.2f%% %3.2f%%", old_percent, new_percent); 197 printed += fprintf(fp, " %3.2f%% %3.2f%%", old_percent, new_percent);
191 198
@@ -260,6 +267,12 @@ static const struct option options[] = {
260 "Don't shorten the pathnames taking into account the cwd"), 267 "Don't shorten the pathnames taking into account the cwd"),
261 OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths, 268 OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths,
262 "Don't shorten the pathnames taking into account the cwd"), 269 "Don't shorten the pathnames taking into account the cwd"),
270 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
271 "only consider symbols in these dsos"),
272 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
273 "only consider symbols in these comms"),
274 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
275 "only consider these symbols"),
263 OPT_END() 276 OPT_END()
264}; 277};
265 278
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 03afac3b56ef..9c595340326a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -316,14 +316,14 @@ static size_t hist_entry__fprintf(FILE *fp, struct hist_entry *self,
316 316
317 if (total_samples) 317 if (total_samples)
318 ret = percent_color_fprintf(fp, 318 ret = percent_color_fprintf(fp,
319 field_sep ? "%.2f" : " %6.2f%%", 319 symbol_conf.field_sep ? "%.2f" : " %6.2f%%",
320 (self->count * 100.0) / total_samples); 320 (self->count * 100.0) / total_samples);
321 else 321 else
322 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count); 322 ret = fprintf(fp, symbol_conf.field_sep ? "%lld" : "%12lld ", self->count);
323 323
324 if (show_nr_samples) { 324 if (show_nr_samples) {
325 if (field_sep) 325 if (symbol_conf.field_sep)
326 fprintf(fp, "%c%lld", *field_sep, self->count); 326 fprintf(fp, "%c%lld", *symbol_conf.field_sep, self->count);
327 else 327 else
328 fprintf(fp, "%11lld", self->count); 328 fprintf(fp, "%11lld", self->count);
329 } 329 }
@@ -332,7 +332,7 @@ static size_t hist_entry__fprintf(FILE *fp, struct hist_entry *self,
332 if (se->elide) 332 if (se->elide)
333 continue; 333 continue;
334 334
335 fprintf(fp, "%s", field_sep ?: " "); 335 fprintf(fp, "%s", symbol_conf.field_sep ?: " ");
336 ret += se->print(fp, self, se->width ? *se->width : 0); 336 ret += se->print(fp, self, se->width ? *se->width : 0);
337 } 337 }
338 338
@@ -355,28 +355,11 @@ static size_t hist_entry__fprintf(FILE *fp, struct hist_entry *self,
355 return ret; 355 return ret;
356} 356}
357 357
358/*
359 *
360 */
361
362static void dso__calc_col_width(struct dso *self)
363{
364 if (!symbol_conf.col_width_list_str && !field_sep &&
365 (!symbol_conf.dso_list ||
366 strlist__has_entry(symbol_conf.dso_list, self->name))) {
367 unsigned int slen = strlen(self->name);
368 if (slen > dsos__col_width)
369 dsos__col_width = slen;
370 }
371
372 self->slen_calculated = 1;
373}
374
375static void thread__comm_adjust(struct thread *self) 358static void thread__comm_adjust(struct thread *self)
376{ 359{
377 char *comm = self->comm; 360 char *comm = self->comm;
378 361
379 if (!symbol_conf.col_width_list_str && !field_sep && 362 if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
380 (!symbol_conf.comm_list || 363 (!symbol_conf.comm_list ||
381 strlist__has_entry(symbol_conf.comm_list, comm))) { 364 strlist__has_entry(symbol_conf.comm_list, comm))) {
382 unsigned int slen = strlen(comm); 365 unsigned int slen = strlen(comm);
@@ -452,16 +435,16 @@ static size_t perf_session__fprintf_hist_entries(struct perf_session *self,
452 435
453 fprintf(fp, "# Overhead"); 436 fprintf(fp, "# Overhead");
454 if (show_nr_samples) { 437 if (show_nr_samples) {
455 if (field_sep) 438 if (symbol_conf.field_sep)
456 fprintf(fp, "%cSamples", *field_sep); 439 fprintf(fp, "%cSamples", *symbol_conf.field_sep);
457 else 440 else
458 fputs(" Samples ", fp); 441 fputs(" Samples ", fp);
459 } 442 }
460 list_for_each_entry(se, &hist_entry__sort_list, list) { 443 list_for_each_entry(se, &hist_entry__sort_list, list) {
461 if (se->elide) 444 if (se->elide)
462 continue; 445 continue;
463 if (field_sep) { 446 if (symbol_conf.field_sep) {
464 fprintf(fp, "%c%s", *field_sep, se->header); 447 fprintf(fp, "%c%s", *symbol_conf.field_sep, se->header);
465 continue; 448 continue;
466 } 449 }
467 width = strlen(se->header); 450 width = strlen(se->header);
@@ -480,7 +463,7 @@ static size_t perf_session__fprintf_hist_entries(struct perf_session *self,
480 } 463 }
481 fprintf(fp, "\n"); 464 fprintf(fp, "\n");
482 465
483 if (field_sep) 466 if (symbol_conf.field_sep)
484 goto print_entries; 467 goto print_entries;
485 468
486 fprintf(fp, "# ........"); 469 fprintf(fp, "# ........");
@@ -542,13 +525,8 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
542 525
543static int process_sample_event(event_t *event, struct perf_session *session) 526static int process_sample_event(event_t *event, struct perf_session *session)
544{ 527{
545 struct sample_data data; 528 struct sample_data data = { .period = 1, };
546 int cpumode;
547 struct addr_location al; 529 struct addr_location al;
548 struct thread *thread;
549
550 memset(&data, 0, sizeof(data));
551 data.period = 1;
552 530
553 event__parse_sample(event, session->sample_type, &data); 531 event__parse_sample(event, session->sample_type, &data);
554 532
@@ -576,39 +554,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
576 } 554 }
577 } 555 }
578 556
579 thread = perf_session__findnew(session, data.pid); 557 if (event__preprocess_sample(event, session, &al, NULL) < 0) {
580 if (thread == NULL) { 558 fprintf(stderr, "problem processing %d event, skipping it.\n",
581 pr_debug("problem processing %d event, skipping it.\n",
582 event->header.type); 559 event->header.type);
583 return -1; 560 return -1;
584 } 561 }
585 562
586 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 563 if (al.filtered)
587
588 if (symbol_conf.comm_list &&
589 !strlist__has_entry(symbol_conf.comm_list, thread->comm))
590 return 0;
591
592 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
593
594 thread__find_addr_location(thread, session, cpumode,
595 MAP__FUNCTION, data.ip, &al, NULL);
596 /*
597 * We have to do this here as we may have a dso with no symbol hit that
598 * has a name longer than the ones with symbols sampled.
599 */
600 if (al.map && !sort_dso.elide && !al.map->dso->slen_calculated)
601 dso__calc_col_width(al.map->dso);
602
603 if (symbol_conf.dso_list &&
604 (!al.map || !al.map->dso ||
605 !(strlist__has_entry(symbol_conf.dso_list, al.map->dso->short_name) ||
606 (al.map->dso->short_name != al.map->dso->long_name &&
607 strlist__has_entry(symbol_conf.dso_list, al.map->dso->long_name)))))
608 return 0;
609
610 if (symbol_conf.sym_list && al.sym &&
611 !strlist__has_entry(symbol_conf.sym_list, al.sym->name))
612 return 0; 564 return 0;
613 565
614 if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) { 566 if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) {
@@ -834,7 +786,7 @@ static const struct option options[] = {
834 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, 786 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
835 "width[,width...]", 787 "width[,width...]",
836 "don't try to adjust column width, use these fixed values"), 788 "don't try to adjust column width, use these fixed values"),
837 OPT_STRING('t', "field-separator", &field_sep, "separator", 789 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
838 "separator for columns, no spaces will be added between " 790 "separator for columns, no spaces will be added between "
839 "columns '.' is reserved."), 791 "columns '.' is reserved."),
840 OPT_END() 792 OPT_END()
@@ -877,11 +829,5 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
877 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); 829 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
878 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); 830 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
879 831
880 if (field_sep && *field_sep == '.') {
881 fputs("'.' is the only non valid --field-separator argument\n",
882 stderr);
883 exit(129);
884 }
885
886 return __cmd_report(); 832 return __cmd_report();
887} 833}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index cd89b6d036b7..ddc584b64871 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -948,7 +948,7 @@ static void event__process_sample(const event_t *self,
948 } 948 }
949 949
950 if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 || 950 if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 ||
951 al.sym == NULL) 951 al.sym == NULL || al.filtered)
952 return; 952 return;
953 953
954 syme = symbol__priv(al.sym); 954 syme = symbol__priv(al.sym);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 375fb6dca1cf..bf491fda1f47 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -2,7 +2,9 @@
2#include "event.h" 2#include "event.h"
3#include "debug.h" 3#include "debug.h"
4#include "session.h" 4#include "session.h"
5#include "sort.h"
5#include "string.h" 6#include "string.h"
7#include "strlist.h"
6#include "thread.h" 8#include "thread.h"
7 9
8static pid_t event__synthesize_comm(pid_t pid, int full, 10static pid_t event__synthesize_comm(pid_t pid, int full,
@@ -299,6 +301,19 @@ try_again:
299 } 301 }
300} 302}
301 303
304static void dso__calc_col_width(struct dso *self)
305{
306 if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
307 (!symbol_conf.dso_list ||
308 strlist__has_entry(symbol_conf.dso_list, self->name))) {
309 unsigned int slen = strlen(self->name);
310 if (slen > dsos__col_width)
311 dsos__col_width = slen;
312 }
313
314 self->slen_calculated = 1;
315}
316
302int event__preprocess_sample(const event_t *self, struct perf_session *session, 317int event__preprocess_sample(const event_t *self, struct perf_session *session,
303 struct addr_location *al, symbol_filter_t filter) 318 struct addr_location *al, symbol_filter_t filter)
304{ 319{
@@ -308,6 +323,10 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
308 if (thread == NULL) 323 if (thread == NULL)
309 return -1; 324 return -1;
310 325
326 if (symbol_conf.comm_list &&
327 !strlist__has_entry(symbol_conf.comm_list, thread->comm))
328 goto out_filtered;
329
311 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 330 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
312 331
313 thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION, 332 thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION,
@@ -315,6 +334,29 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
315 dump_printf(" ...... dso: %s\n", 334 dump_printf(" ...... dso: %s\n",
316 al->map ? al->map->dso->long_name : 335 al->map ? al->map->dso->long_name :
317 al->level == 'H' ? "[hypervisor]" : "<not found>"); 336 al->level == 'H' ? "[hypervisor]" : "<not found>");
337 /*
338 * We have to do this here as we may have a dso with no symbol hit that
339 * has a name longer than the ones with symbols sampled.
340 */
341 if (al->map && !sort_dso.elide && !al->map->dso->slen_calculated)
342 dso__calc_col_width(al->map->dso);
343
344 if (symbol_conf.dso_list &&
345 (!al->map || !al->map->dso ||
346 !(strlist__has_entry(symbol_conf.dso_list, al->map->dso->short_name) ||
347 (al->map->dso->short_name != al->map->dso->long_name &&
348 strlist__has_entry(symbol_conf.dso_list, al->map->dso->long_name)))))
349 goto out_filtered;
350
351 if (symbol_conf.sym_list && al->sym &&
352 !strlist__has_entry(symbol_conf.sym_list, al->sym->name))
353 goto out_filtered;
354
355 al->filtered = false;
356 return 0;
357
358out_filtered:
359 al->filtered = true;
318 return 0; 360 return 0;
319} 361}
320 362
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 164286ace7df..7707897b59f1 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1764,6 +1764,11 @@ int symbol__init(void)
1764 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1764 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0)
1765 return -1; 1765 return -1;
1766 1766
1767 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
1768 pr_err("'.' is the only non valid --field-separator argument\n");
1769 return -1;
1770 }
1771
1767 if (setup_list(&symbol_conf.dso_list, 1772 if (setup_list(&symbol_conf.dso_list,
1768 symbol_conf.dso_list_str, "dso") < 0) 1773 symbol_conf.dso_list_str, "dso") < 0)
1769 return -1; 1774 return -1;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d61f35074997..60151521f41d 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -56,7 +56,8 @@ struct symbol_conf {
56 bool try_vmlinux_path, 56 bool try_vmlinux_path,
57 use_modules, 57 use_modules,
58 sort_by_name; 58 sort_by_name;
59 const char *vmlinux_name; 59 const char *vmlinux_name,
60 *field_sep;
60 char *dso_list_str, 61 char *dso_list_str,
61 *comm_list_str, 62 *comm_list_str,
62 *sym_list_str, 63 *sym_list_str,
@@ -79,6 +80,7 @@ struct addr_location {
79 struct symbol *sym; 80 struct symbol *sym;
80 u64 addr; 81 u64 addr;
81 char level; 82 char level;
83 bool filtered;
82}; 84};
83 85
84struct dso { 86struct dso {