提交 13cc5079 编写于 作者: A Arnaldo Carvalho de Melo 提交者: Ingo Molnar

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: NIngo Molnar <mingo@elte.hu>
Signed-off-by: NArnaldo 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: NIngo Molnar <mingo@elte.hu>
上级 cfc10d3b
...@@ -78,6 +78,14 @@ static int dump_symtab = 0; ...@@ -78,6 +78,14 @@ static int dump_symtab = 0;
static bool hide_kernel_symbols = false; static bool hide_kernel_symbols = false;
static bool hide_user_symbols = false; static bool hide_user_symbols = false;
static struct winsize winsize;
static const char *graph_line =
"_____________________________________________________________________"
"_____________________________________________________________________";
static const char *graph_dotted_line =
"---------------------------------------------------------------------"
"---------------------------------------------------------------------"
"---------------------------------------------------------------------";
/* /*
* Source * Source
...@@ -107,6 +115,7 @@ struct sym_entry { ...@@ -107,6 +115,7 @@ struct sym_entry {
unsigned long snap_count; unsigned long snap_count;
double weight; double weight;
int skip; int skip;
u16 name_len;
u8 origin; u8 origin;
struct map *map; struct map *map;
struct source_line *source; struct source_line *source;
...@@ -119,34 +128,40 @@ struct sym_entry { ...@@ -119,34 +128,40 @@ struct sym_entry {
* Source functions * Source functions
*/ */
/* most GUI terminals set LINES (although some don't export it) */ static void get_term_dimensions(struct winsize *ws)
static int term_rows(void)
{ {
char *lines_string = getenv("LINES"); char *s = getenv("LINES");
int n_lines;
if (s != NULL) {
if (lines_string && (n_lines = atoi(lines_string)) > 0) ws->ws_row = atoi(s);
return n_lines; s = getenv("COLUMNS");
#ifdef TIOCGWINSZ if (s != NULL) {
else { ws->ws_col = atoi(s);
struct winsize ws; if (ws->ws_row && ws->ws_col)
if (!ioctl(1, TIOCGWINSZ, &ws) && ws.ws_row) return;
return ws.ws_row; }
} }
#ifdef TIOCGWINSZ
if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
ws->ws_row && ws->ws_col)
return;
#endif #endif
return 25; ws->ws_row = 25;
ws->ws_col = 80;
} }
static void update_print_entries(void) static void update_print_entries(struct winsize *ws)
{ {
print_entries = term_rows(); print_entries = ws->ws_row;
if (print_entries > 9) if (print_entries > 9)
print_entries -= 9; print_entries -= 9;
} }
static void sig_winch_handler(int sig __used) static void sig_winch_handler(int sig __used)
{ {
update_print_entries(); get_term_dimensions(&winsize);
update_print_entries(&winsize);
} }
static void parse_source(struct sym_entry *syme) static void parse_source(struct sym_entry *syme)
...@@ -423,6 +438,8 @@ static void print_sym_table(void) ...@@ -423,6 +438,8 @@ static void print_sym_table(void)
struct sym_entry *syme, *n; struct sym_entry *syme, *n;
struct rb_root tmp = RB_ROOT; struct rb_root tmp = RB_ROOT;
struct rb_node *nd; struct rb_node *nd;
int sym_width = 0, dso_width;
const int win_width = winsize.ws_col - 1;
samples = userspace_samples = 0; samples = userspace_samples = 0;
...@@ -434,6 +451,7 @@ static void print_sym_table(void) ...@@ -434,6 +451,7 @@ static void print_sym_table(void)
list_for_each_entry_safe_from(syme, n, &active_symbols, node) { list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
syme->snap_count = syme->count[snap]; syme->snap_count = syme->count[snap];
if (syme->snap_count != 0) { if (syme->snap_count != 0) {
if ((hide_user_symbols && if ((hide_user_symbols &&
syme->origin == PERF_RECORD_MISC_USER) || syme->origin == PERF_RECORD_MISC_USER) ||
(hide_kernel_symbols && (hide_kernel_symbols &&
...@@ -453,8 +471,7 @@ static void print_sym_table(void) ...@@ -453,8 +471,7 @@ static void print_sym_table(void)
puts(CONSOLE_CLEAR); puts(CONSOLE_CLEAR);
printf( printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
"------------------------------------------------------------------------------\n");
printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [", printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [",
samples_per_sec, samples_per_sec,
100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
...@@ -492,26 +509,44 @@ static void print_sym_table(void) ...@@ -492,26 +509,44 @@ static void print_sym_table(void)
printf(", %d CPUs)\n", nr_cpus); printf(", %d CPUs)\n", nr_cpus);
} }
printf("------------------------------------------------------------------------------\n\n"); printf("%-*.*s\n\n", win_width, win_width, graph_dotted_line);
if (sym_filter_entry) { if (sym_filter_entry) {
show_details(sym_filter_entry); show_details(sym_filter_entry);
return; return;
} }
/*
* Find the longest symbol name that will be displayed
*/
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
syme = rb_entry(nd, struct sym_entry, rb_node);
if (++printed > print_entries ||
(int)syme->snap_count < count_filter)
continue;
if (syme->name_len > sym_width)
sym_width = syme->name_len;
}
printed = 0;
if (nr_counters == 1) if (nr_counters == 1)
printf(" samples pcnt"); printf(" samples pcnt");
else else
printf(" weight samples pcnt"); printf(" weight samples pcnt");
dso_width = winsize.ws_col - sym_width - 29;
if (verbose) if (verbose)
printf(" RIP "); printf(" RIP ");
printf(" function DSO\n"); printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
printf(" %s _______ _____", printf(" %s _______ _____",
nr_counters == 1 ? " " : "______"); nr_counters == 1 ? " " : "______");
if (verbose) if (verbose)
printf(" ________________"); printf(" ________________");
printf(" ________________________________ ________________\n\n"); printf(" %-*.*s %-*.*s\n\n", sym_width, sym_width, graph_line,
dso_width, dso_width, graph_line);
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
struct symbol *sym; struct symbol *sym;
...@@ -534,8 +569,11 @@ static void print_sym_table(void) ...@@ -534,8 +569,11 @@ static void print_sym_table(void)
percent_color_fprintf(stdout, "%4.1f%%", pcnt); percent_color_fprintf(stdout, "%4.1f%%", pcnt);
if (verbose) if (verbose)
printf(" %016llx", sym->start); printf(" %016llx", sym->start);
printf(" %-32s", sym->name); printf(" %-*.*s", sym_width, sym_width, sym->name);
printf(" %s", syme->map->dso->short_name); printf(" %-*.*s", dso_width, dso_width,
dso_width >= syme->map->dso->long_name_len ?
syme->map->dso->long_name :
syme->map->dso->short_name);
printf("\n"); printf("\n");
} }
} }
...@@ -718,7 +756,7 @@ static void handle_keypress(int c) ...@@ -718,7 +756,7 @@ static void handle_keypress(int c)
case 'e': case 'e':
prompt_integer(&print_entries, "Enter display entries (lines)"); prompt_integer(&print_entries, "Enter display entries (lines)");
if (print_entries == 0) { if (print_entries == 0) {
update_print_entries(); sig_winch_handler(SIGWINCH);
signal(SIGWINCH, sig_winch_handler); signal(SIGWINCH, sig_winch_handler);
} else } else
signal(SIGWINCH, SIG_DFL); signal(SIGWINCH, SIG_DFL);
...@@ -862,6 +900,9 @@ static int symbol_filter(struct map *map, struct symbol *sym) ...@@ -862,6 +900,9 @@ static int symbol_filter(struct map *map, struct symbol *sym)
} }
} }
if (!syme->skip)
syme->name_len = strlen(sym->name);
return 0; return 0;
} }
...@@ -1301,8 +1342,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) ...@@ -1301,8 +1342,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
if (target_pid != -1 || profile_cpu != -1) if (target_pid != -1 || profile_cpu != -1)
nr_cpus = 1; nr_cpus = 1;
get_term_dimensions(&winsize);
if (print_entries == 0) { if (print_entries == 0) {
update_print_entries(); update_print_entries(&winsize);
signal(SIGWINCH, sig_winch_handler); signal(SIGWINCH, sig_winch_handler);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册