aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-17 12:40:54 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-19 00:03:36 -0500
commit13cc5079f235906e60577dbce8da2f9607e67e93 (patch)
tree46e38168af043489b657b9d2715b4dab0aad1428 /tools/perf/builtin-top.c
parentcfc10d3bcc50d70f72c0f43d03eee965c726ccc0 (diff)
perf top: Auto adjust symbol and dso widths
We pre-calculate the symbol name length, then after we sort the entries to print, calculate the biggest one and use that for the symbol name width justification, then use the dso->long_name->len to justificate the DSO name, deciding whether using the short or long name depending on how much space we have on the terminal. IOW give as much info to the user as the terminal width allows. Suggested-by: Ingo Molnar <mingo@elte.hu> 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: <1258479655-28662-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c92
1 files changed, 67 insertions, 25 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 89b7f68a1799..a368978d5177 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -78,6 +78,14 @@ static int dump_symtab = 0;
78 78
79static bool hide_kernel_symbols = false; 79static bool hide_kernel_symbols = false;
80static bool hide_user_symbols = false; 80static bool hide_user_symbols = false;
81static struct winsize winsize;
82static const char *graph_line =
83 "_____________________________________________________________________"
84 "_____________________________________________________________________";
85static const char *graph_dotted_line =
86 "---------------------------------------------------------------------"
87 "---------------------------------------------------------------------"
88 "---------------------------------------------------------------------";
81 89
82/* 90/*
83 * Source 91 * Source
@@ -107,6 +115,7 @@ struct sym_entry {
107 unsigned long snap_count; 115 unsigned long snap_count;
108 double weight; 116 double weight;
109 int skip; 117 int skip;
118 u16 name_len;
110 u8 origin; 119 u8 origin;
111 struct map *map; 120 struct map *map;
112 struct source_line *source; 121 struct source_line *source;
@@ -119,34 +128,40 @@ struct sym_entry {
119 * Source functions 128 * Source functions
120 */ 129 */
121 130
122/* most GUI terminals set LINES (although some don't export it) */ 131static void get_term_dimensions(struct winsize *ws)
123static int term_rows(void)
124{ 132{
125 char *lines_string = getenv("LINES"); 133 char *s = getenv("LINES");
126 int n_lines; 134
127 135 if (s != NULL) {
128 if (lines_string && (n_lines = atoi(lines_string)) > 0) 136 ws->ws_row = atoi(s);
129 return n_lines; 137 s = getenv("COLUMNS");
130#ifdef TIOCGWINSZ 138 if (s != NULL) {
131 else { 139 ws->ws_col = atoi(s);
132 struct winsize ws; 140 if (ws->ws_row && ws->ws_col)
133 if (!ioctl(1, TIOCGWINSZ, &ws) && ws.ws_row) 141 return;
134 return ws.ws_row; 142 }
135 } 143 }
144#ifdef TIOCGWINSZ
145 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
146 ws->ws_row && ws->ws_col)
147 return;
136#endif 148#endif
137 return 25; 149 ws->ws_row = 25;
150 ws->ws_col = 80;
138} 151}
139 152
140static void update_print_entries(void) 153static void update_print_entries(struct winsize *ws)
141{ 154{
142 print_entries = term_rows(); 155 print_entries = ws->ws_row;
156
143 if (print_entries > 9) 157 if (print_entries > 9)
144 print_entries -= 9; 158 print_entries -= 9;
145} 159}
146 160
147static void sig_winch_handler(int sig __used) 161static void sig_winch_handler(int sig __used)
148{ 162{
149 update_print_entries(); 163 get_term_dimensions(&winsize);
164 update_print_entries(&winsize);
150} 165}
151 166
152static void parse_source(struct sym_entry *syme) 167static void parse_source(struct sym_entry *syme)
@@ -423,6 +438,8 @@ static void print_sym_table(void)
423 struct sym_entry *syme, *n; 438 struct sym_entry *syme, *n;
424 struct rb_root tmp = RB_ROOT; 439 struct rb_root tmp = RB_ROOT;
425 struct rb_node *nd; 440 struct rb_node *nd;
441 int sym_width = 0, dso_width;
442 const int win_width = winsize.ws_col - 1;
426 443
427 samples = userspace_samples = 0; 444 samples = userspace_samples = 0;
428 445
@@ -434,6 +451,7 @@ static void print_sym_table(void)
434 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 451 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
435 syme->snap_count = syme->count[snap]; 452 syme->snap_count = syme->count[snap];
436 if (syme->snap_count != 0) { 453 if (syme->snap_count != 0) {
454
437 if ((hide_user_symbols && 455 if ((hide_user_symbols &&
438 syme->origin == PERF_RECORD_MISC_USER) || 456 syme->origin == PERF_RECORD_MISC_USER) ||
439 (hide_kernel_symbols && 457 (hide_kernel_symbols &&
@@ -453,8 +471,7 @@ static void print_sym_table(void)
453 471
454 puts(CONSOLE_CLEAR); 472 puts(CONSOLE_CLEAR);
455 473
456 printf( 474 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
457"------------------------------------------------------------------------------\n");
458 printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [", 475 printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [",
459 samples_per_sec, 476 samples_per_sec,
460 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 477 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
@@ -492,26 +509,44 @@ static void print_sym_table(void)
492 printf(", %d CPUs)\n", nr_cpus); 509 printf(", %d CPUs)\n", nr_cpus);
493 } 510 }
494 511
495 printf("------------------------------------------------------------------------------\n\n"); 512 printf("%-*.*s\n\n", win_width, win_width, graph_dotted_line);
496 513
497 if (sym_filter_entry) { 514 if (sym_filter_entry) {
498 show_details(sym_filter_entry); 515 show_details(sym_filter_entry);
499 return; 516 return;
500 } 517 }
501 518
519 /*
520 * Find the longest symbol name that will be displayed
521 */
522 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
523 syme = rb_entry(nd, struct sym_entry, rb_node);
524 if (++printed > print_entries ||
525 (int)syme->snap_count < count_filter)
526 continue;
527
528 if (syme->name_len > sym_width)
529 sym_width = syme->name_len;
530 }
531
532 printed = 0;
533
502 if (nr_counters == 1) 534 if (nr_counters == 1)
503 printf(" samples pcnt"); 535 printf(" samples pcnt");
504 else 536 else
505 printf(" weight samples pcnt"); 537 printf(" weight samples pcnt");
506 538
539 dso_width = winsize.ws_col - sym_width - 29;
540
507 if (verbose) 541 if (verbose)
508 printf(" RIP "); 542 printf(" RIP ");
509 printf(" function DSO\n"); 543 printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
510 printf(" %s _______ _____", 544 printf(" %s _______ _____",
511 nr_counters == 1 ? " " : "______"); 545 nr_counters == 1 ? " " : "______");
512 if (verbose) 546 if (verbose)
513 printf(" ________________"); 547 printf(" ________________");
514 printf(" ________________________________ ________________\n\n"); 548 printf(" %-*.*s %-*.*s\n\n", sym_width, sym_width, graph_line,
549 dso_width, dso_width, graph_line);
515 550
516 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 551 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
517 struct symbol *sym; 552 struct symbol *sym;
@@ -534,8 +569,11 @@ static void print_sym_table(void)
534 percent_color_fprintf(stdout, "%4.1f%%", pcnt); 569 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
535 if (verbose) 570 if (verbose)
536 printf(" %016llx", sym->start); 571 printf(" %016llx", sym->start);
537 printf(" %-32s", sym->name); 572 printf(" %-*.*s", sym_width, sym_width, sym->name);
538 printf(" %s", syme->map->dso->short_name); 573 printf(" %-*.*s", dso_width, dso_width,
574 dso_width >= syme->map->dso->long_name_len ?
575 syme->map->dso->long_name :
576 syme->map->dso->short_name);
539 printf("\n"); 577 printf("\n");
540 } 578 }
541} 579}
@@ -718,7 +756,7 @@ static void handle_keypress(int c)
718 case 'e': 756 case 'e':
719 prompt_integer(&print_entries, "Enter display entries (lines)"); 757 prompt_integer(&print_entries, "Enter display entries (lines)");
720 if (print_entries == 0) { 758 if (print_entries == 0) {
721 update_print_entries(); 759 sig_winch_handler(SIGWINCH);
722 signal(SIGWINCH, sig_winch_handler); 760 signal(SIGWINCH, sig_winch_handler);
723 } else 761 } else
724 signal(SIGWINCH, SIG_DFL); 762 signal(SIGWINCH, SIG_DFL);
@@ -862,6 +900,9 @@ static int symbol_filter(struct map *map, struct symbol *sym)
862 } 900 }
863 } 901 }
864 902
903 if (!syme->skip)
904 syme->name_len = strlen(sym->name);
905
865 return 0; 906 return 0;
866} 907}
867 908
@@ -1301,8 +1342,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1301 if (target_pid != -1 || profile_cpu != -1) 1342 if (target_pid != -1 || profile_cpu != -1)
1302 nr_cpus = 1; 1343 nr_cpus = 1;
1303 1344
1345 get_term_dimensions(&winsize);
1304 if (print_entries == 0) { 1346 if (print_entries == 0) {
1305 update_print_entries(); 1347 update_print_entries(&winsize);
1306 signal(SIGWINCH, sig_winch_handler); 1348 signal(SIGWINCH, sig_winch_handler);
1307 } 1349 }
1308 1350