aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 89b7f68a179..a368978d517 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -78,6 +78,14 @@ static int dump_symtab = 0;
static bool hide_kernel_symbols = false;
static bool hide_user_symbols = false;
+static struct winsize winsize;
+static const char *graph_line =
+ "_____________________________________________________________________"
+ "_____________________________________________________________________";
+static const char *graph_dotted_line =
+ "---------------------------------------------------------------------"
+ "---------------------------------------------------------------------"
+ "---------------------------------------------------------------------";
/*
* Source
@@ -107,6 +115,7 @@ struct sym_entry {
unsigned long snap_count;
double weight;
int skip;
+ u16 name_len;
u8 origin;
struct map *map;
struct source_line *source;
@@ -119,34 +128,40 @@ struct sym_entry {
* Source functions
*/
-/* most GUI terminals set LINES (although some don't export it) */
-static int term_rows(void)
+static void get_term_dimensions(struct winsize *ws)
{
- char *lines_string = getenv("LINES");
- int n_lines;
-
- if (lines_string && (n_lines = atoi(lines_string)) > 0)
- return n_lines;
-#ifdef TIOCGWINSZ
- else {
- struct winsize ws;
- if (!ioctl(1, TIOCGWINSZ, &ws) && ws.ws_row)
- return ws.ws_row;
+ char *s = getenv("LINES");
+
+ if (s != NULL) {
+ ws->ws_row = atoi(s);
+ s = getenv("COLUMNS");
+ if (s != NULL) {
+ ws->ws_col = atoi(s);
+ if (ws->ws_row && ws->ws_col)
+ return;
+ }
}
+#ifdef TIOCGWINSZ
+ if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
+ ws->ws_row && ws->ws_col)
+ return;
#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)
print_entries -= 9;
}
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)
@@ -423,6 +438,8 @@ static void print_sym_table(void)
struct sym_entry *syme, *n;
struct rb_root tmp = RB_ROOT;
struct rb_node *nd;
+ int sym_width = 0, dso_width;
+ const int win_width = winsize.ws_col - 1;
samples = userspace_samples = 0;
@@ -434,6 +451,7 @@ static void print_sym_table(void)
list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
syme->snap_count = syme->count[snap];
if (syme->snap_count != 0) {
+
if ((hide_user_symbols &&
syme->origin == PERF_RECORD_MISC_USER) ||
(hide_kernel_symbols &&
@@ -453,8 +471,7 @@ static void print_sym_table(void)
puts(CONSOLE_CLEAR);
- printf(
-"------------------------------------------------------------------------------\n");
+ printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [",
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)
printf(", %d CPUs)\n", nr_cpus);
}
- printf("------------------------------------------------------------------------------\n\n");
+ printf("%-*.*s\n\n", win_width, win_width, graph_dotted_line);
if (sym_filter_entry) {
show_details(sym_filter_entry);
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)
printf(" samples pcnt");
else
printf(" weight samples pcnt");
+ dso_width = winsize.ws_col - sym_width - 29;
+
if (verbose)
printf(" RIP ");
- printf(" function DSO\n");
+ printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
printf(" %s _______ _____",
nr_counters == 1 ? " " : "______");
if (verbose)
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)) {
struct symbol *sym;
@@ -534,8 +569,11 @@ static void print_sym_table(void)
percent_color_fprintf(stdout, "%4.1f%%", pcnt);
if (verbose)
printf(" %016llx", sym->start);
- printf(" %-32s", sym->name);
- printf(" %s", syme->map->dso->short_name);
+ printf(" %-*.*s", sym_width, sym_width, sym->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");
}
}
@@ -718,7 +756,7 @@ static void handle_keypress(int c)
case 'e':
prompt_integer(&print_entries, "Enter display entries (lines)");
if (print_entries == 0) {
- update_print_entries();
+ sig_winch_handler(SIGWINCH);
signal(SIGWINCH, sig_winch_handler);
} else
signal(SIGWINCH, SIG_DFL);
@@ -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;
}
@@ -1301,8 +1342,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
if (target_pid != -1 || profile_cpu != -1)
nr_cpus = 1;
+ get_term_dimensions(&winsize);
if (print_entries == 0) {
- update_print_entries();
+ update_print_entries(&winsize);
signal(SIGWINCH, sig_winch_handler);
}