diff options
Diffstat (limited to 'tools/perf/ui')
-rw-r--r-- | tools/perf/ui/browser.c | 7 | ||||
-rw-r--r-- | tools/perf/ui/browsers/annotate.c | 6 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 133 | ||||
-rw-r--r-- | tools/perf/ui/gtk/browser.c | 111 | ||||
-rw-r--r-- | tools/perf/ui/gtk/gtk.h | 3 | ||||
-rw-r--r-- | tools/perf/ui/gtk/helpline.c | 56 | ||||
-rw-r--r-- | tools/perf/ui/gtk/setup.c | 6 | ||||
-rw-r--r-- | tools/perf/ui/gtk/util.c | 9 | ||||
-rw-r--r-- | tools/perf/ui/helpline.c | 56 | ||||
-rw-r--r-- | tools/perf/ui/helpline.h | 33 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 390 | ||||
-rw-r--r-- | tools/perf/ui/setup.c | 10 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 498 | ||||
-rw-r--r-- | tools/perf/ui/tui/helpline.c | 57 | ||||
-rw-r--r-- | tools/perf/ui/tui/setup.c | 10 |
15 files changed, 1275 insertions, 110 deletions
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 1818a531f1d..4aeb7d5df93 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -269,7 +269,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title, return err ? 0 : -1; } -void ui_browser__hide(struct ui_browser *browser __used) +void ui_browser__hide(struct ui_browser *browser __maybe_unused) { pthread_mutex_lock(&ui__lock); ui_helpline__pop(); @@ -518,7 +518,7 @@ static struct ui_browser__colorset { static int ui_browser__color_config(const char *var, const char *value, - void *data __used) + void *data __maybe_unused) { char *fg = NULL, *bg; int i; @@ -602,7 +602,8 @@ void __ui_browser__vline(struct ui_browser *browser, unsigned int column, SLsmg_set_char_set(0); } -void ui_browser__write_graph(struct ui_browser *browser __used, int graph) +void ui_browser__write_graph(struct ui_browser *browser __maybe_unused, + int graph) { SLsmg_set_char_set(1); SLsmg_write_char(graph); diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 67a2703e666..8f8cd2d73b3 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -54,7 +54,8 @@ static inline struct browser_disasm_line *disasm_line__browser(struct disasm_lin return (struct browser_disasm_line *)(dl + 1); } -static bool disasm_line__filter(struct ui_browser *browser __used, void *entry) +static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, + void *entry) { if (annotate_browser__opts.hide_src_code) { struct disasm_line *dl = list_entry(entry, struct disasm_line, node); @@ -928,7 +929,8 @@ static int annotate_config__cmp(const void *name, const void *cfgp) return strcmp(name, cfg->name); } -static int annotate__config(const char *var, const char *value, void *data __used) +static int annotate__config(const char *var, const char *value, + void *data __maybe_unused) { struct annotate__config *cfg; const char *name; diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 413bd62eedb..a21f40bebba 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -24,9 +24,12 @@ struct hist_browser { struct hist_entry *he_selection; struct map_symbol *selection; int print_seq; + bool show_dso; bool has_symbols; }; +extern void hist_browser__init_hpp(void); + static int hists__browser_title(struct hists *hists, char *bf, size_t size, const char *ev_name); @@ -376,12 +379,19 @@ out: } static char *callchain_list__sym_name(struct callchain_list *cl, - char *bf, size_t bfsize) + char *bf, size_t bfsize, bool show_dso) { + int printed; + if (cl->ms.sym) - return cl->ms.sym->name; + printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); + else + printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); + + if (show_dso) + scnprintf(bf + printed, bfsize - printed, " %s", + cl->ms.map ? cl->ms.map->dso->short_name : "unknown"); - snprintf(bf, bfsize, "%#" PRIx64, cl->ip); return bf; } @@ -417,7 +427,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse remaining -= cumul; list_for_each_entry(chain, &child->val, list) { - char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; + char bf[1024], *alloc_str; const char *str; int color; bool was_first = first; @@ -434,7 +444,8 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse } alloc_str = NULL; - str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); + str = callchain_list__sym_name(chain, bf, sizeof(bf), + browser->show_dso); if (was_first) { double percent = cumul * 100.0 / new_total; @@ -493,7 +504,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, char folded_sign = ' '; list_for_each_entry(chain, &node->val, list) { - char ipstr[BITS_PER_LONG / 4 + 1], *s; + char bf[1024], *s; int color; folded_sign = callchain_list__folded(chain); @@ -510,7 +521,8 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, *is_current_entry = true; } - s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); + s = callchain_list__sym_name(chain, bf, sizeof(bf), + browser->show_dso); ui_browser__gotorc(&browser->b, row, 0); ui_browser__set_color(&browser->b, color); slsmg_write_nstring(" ", offset); @@ -553,14 +565,47 @@ static int hist_browser__show_callchain(struct hist_browser *browser, return row - first_row; } +#define HPP__COLOR_FN(_name, _field) \ +static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ + struct hist_entry *he) \ +{ \ + double percent = 100.0 * he->_field / hpp->total_period; \ + *(double *)hpp->ptr = percent; \ + return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ +} + +HPP__COLOR_FN(overhead, period) +HPP__COLOR_FN(overhead_sys, period_sys) +HPP__COLOR_FN(overhead_us, period_us) +HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) +HPP__COLOR_FN(overhead_guest_us, period_guest_us) + +#undef HPP__COLOR_FN + +void hist_browser__init_hpp(void) +{ + perf_hpp__init(false, false); + + perf_hpp__format[PERF_HPP__OVERHEAD].color = + hist_browser__hpp_color_overhead; + perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = + hist_browser__hpp_color_overhead_sys; + perf_hpp__format[PERF_HPP__OVERHEAD_US].color = + hist_browser__hpp_color_overhead_us; + perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = + hist_browser__hpp_color_overhead_guest_sys; + perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = + hist_browser__hpp_color_overhead_guest_us; +} + static int hist_browser__show_entry(struct hist_browser *browser, struct hist_entry *entry, unsigned short row) { char s[256]; double percent; - int printed = 0; - int width = browser->b.width - 6; /* The percentage */ + int i, printed = 0; + int width = browser->b.width; char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(&browser->b, row); off_t row_offset = entry->row_offset; @@ -576,35 +621,50 @@ static int hist_browser__show_entry(struct hist_browser *browser, } if (row_offset == 0) { - hist_entry__snprintf(entry, s, sizeof(s), browser->hists); - percent = (entry->period * 100.0) / browser->hists->stats.total_period; + struct perf_hpp hpp = { + .buf = s, + .size = sizeof(s), + .total_period = browser->hists->stats.total_period, + }; - ui_browser__set_percent_color(&browser->b, percent, current_entry); ui_browser__gotorc(&browser->b, row, 0); - if (symbol_conf.use_callchain) { - slsmg_printf("%c ", folded_sign); - width -= 2; - } - slsmg_printf(" %5.2f%%", percent); + for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { + if (!perf_hpp__format[i].cond) + continue; - /* The scroll bar isn't being used */ - if (!browser->b.navkeypressed) - width += 1; + if (i) { + slsmg_printf(" "); + width -= 2; + } - if (!current_entry || !browser->b.navkeypressed) - ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); + if (perf_hpp__format[i].color) { + hpp.ptr = &percent; + /* It will set percent for us. See HPP__COLOR_FN above. */ + width -= perf_hpp__format[i].color(&hpp, entry); - if (symbol_conf.show_nr_samples) { - slsmg_printf(" %11u", entry->nr_events); - width -= 12; - } + ui_browser__set_percent_color(&browser->b, percent, current_entry); + + if (i == 0 && symbol_conf.use_callchain) { + slsmg_printf("%c ", folded_sign); + width -= 2; + } + + slsmg_printf("%s", s); - if (symbol_conf.show_total_period) { - slsmg_printf(" %12" PRIu64, entry->period); - width -= 13; + if (!current_entry || !browser->b.navkeypressed) + ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); + } else { + width -= perf_hpp__format[i].entry(&hpp, entry); + slsmg_printf("%s", s); + } } + /* The scroll bar isn't being used */ + if (!browser->b.navkeypressed) + width += 1; + + hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists); slsmg_write_nstring(s, width); ++row; ++printed; @@ -830,7 +890,7 @@ static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *bro remaining -= cumul; list_for_each_entry(chain, &child->val, list) { - char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; + char bf[1024], *alloc_str; const char *str; bool was_first = first; @@ -842,7 +902,8 @@ static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *bro folded_sign = callchain_list__folded(chain); alloc_str = NULL; - str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); + str = callchain_list__sym_name(chain, bf, sizeof(bf), + browser->show_dso); if (was_first) { double percent = cumul * 100.0 / new_total; @@ -880,10 +941,10 @@ static int hist_browser__fprintf_callchain_node(struct hist_browser *browser, int printed = 0; list_for_each_entry(chain, &node->val, list) { - char ipstr[BITS_PER_LONG / 4 + 1], *s; + char bf[1024], *s; folded_sign = callchain_list__folded(chain); - s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); + s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso); printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s); } @@ -920,7 +981,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) folded_sign = hist_entry__folded(he); - hist_entry__snprintf(he, s, sizeof(s), browser->hists); + hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists); percent = (he->period * 100.0) / browser->hists->stats.total_period; if (symbol_conf.use_callchain) @@ -1133,6 +1194,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, continue; case 'd': goto zoom_dso; + case 'V': + browser->show_dso = !browser->show_dso; + continue; case 't': goto zoom_thread; case '/': @@ -1164,6 +1228,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "d Zoom into current DSO\n" "t Zoom into current Thread\n" "P Print histograms to perf.hist.N\n" + "V Verbose (DSO names in callchains, etc)\n" "/ Filter symbol by name"); continue; case K_ENTER: diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index ec12e0b4ded..7ff99ec1d95 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -3,6 +3,7 @@ #include "../evsel.h" #include "../sort.h" #include "../hist.h" +#include "../helpline.h" #include "gtk.h" #include <signal.h> @@ -35,6 +36,57 @@ static void perf_gtk__resize_window(GtkWidget *window) gtk_window_resize(GTK_WINDOW(window), width, height); } +static const char *perf_gtk__get_percent_color(double percent) +{ + if (percent >= MIN_RED) + return "<span fgcolor='red'>"; + if (percent >= MIN_GREEN) + return "<span fgcolor='dark green'>"; + return NULL; +} + +#define HPP__COLOR_FN(_name, _field) \ +static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ + struct hist_entry *he) \ +{ \ + double percent = 100.0 * he->_field / hpp->total_period; \ + const char *markup; \ + int ret = 0; \ + \ + markup = perf_gtk__get_percent_color(percent); \ + if (markup) \ + ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ + ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); \ + if (markup) \ + ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); \ + \ + return ret; \ +} + +HPP__COLOR_FN(overhead, period) +HPP__COLOR_FN(overhead_sys, period_sys) +HPP__COLOR_FN(overhead_us, period_us) +HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) +HPP__COLOR_FN(overhead_guest_us, period_guest_us) + +#undef HPP__COLOR_FN + +void perf_gtk__init_hpp(void) +{ + perf_hpp__init(false, false); + + perf_hpp__format[PERF_HPP__OVERHEAD].color = + perf_gtk__hpp_color_overhead; + perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = + perf_gtk__hpp_color_overhead_sys; + perf_hpp__format[PERF_HPP__OVERHEAD_US].color = + perf_gtk__hpp_color_overhead_us; + perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = + perf_gtk__hpp_color_overhead_guest_sys; + perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = + perf_gtk__hpp_color_overhead_guest_us; +} + static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) { GType col_types[MAX_COLUMNS]; @@ -42,15 +94,25 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) struct sort_entry *se; GtkListStore *store; struct rb_node *nd; - u64 total_period; GtkWidget *view; - int col_idx; + int i, col_idx; int nr_cols; + char s[512]; + + struct perf_hpp hpp = { + .buf = s, + .size = sizeof(s), + .total_period = hists->stats.total_period, + }; nr_cols = 0; - /* The percentage column */ - col_types[nr_cols++] = G_TYPE_STRING; + for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { + if (!perf_hpp__format[i].cond) + continue; + + col_types[nr_cols++] = G_TYPE_STRING; + } list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -67,11 +129,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) col_idx = 0; - /* The percentage column */ - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, "Overhead (%)", - renderer, "text", - col_idx++, NULL); + for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { + if (!perf_hpp__format[i].cond) + continue; + + perf_hpp__format[i].header(&hpp); + + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, s, + renderer, "markup", + col_idx++, NULL); + } list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -87,13 +155,9 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) g_object_unref(GTK_TREE_MODEL(store)); - total_period = hists->stats.total_period; - for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); GtkTreeIter iter; - double percent; - char s[512]; if (h->filtered) continue; @@ -102,11 +166,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) col_idx = 0; - percent = (h->period * 100.0) / total_period; + for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { + if (!perf_hpp__format[i].cond) + continue; - snprintf(s, ARRAY_SIZE(s), "%.2f", percent); + if (perf_hpp__format[i].color) + perf_hpp__format[i].color(&hpp, h); + else + perf_hpp__format[i].entry(&hpp, h); - gtk_list_store_set(store, &iter, col_idx++, s, -1); + gtk_list_store_set(store, &iter, col_idx++, s, -1); + } list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -166,9 +236,10 @@ static GtkWidget *perf_gtk__setup_statusbar(void) } int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, - const char *help __used, - void (*timer) (void *arg)__used, - void *arg __used, int delay_secs __used) + const char *help, + void (*timer) (void *arg)__maybe_unused, + void *arg __maybe_unused, + int delay_secs __maybe_unused) { struct perf_evsel *pos; GtkWidget *vbox; @@ -233,6 +304,8 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + ui_helpline__push(help); + gtk_main(); perf_gtk__deactivate_context(&pgctx); diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index a4d0f2b4a2d..687af0bba18 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -29,6 +29,9 @@ static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx) struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window); int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); +void perf_gtk__init_helpline(void); +void perf_gtk__init_hpp(void); + #ifndef HAVE_GTK_INFO_BAR static inline GtkWidget *perf_gtk__setup_info_bar(void) { diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c new file mode 100644 index 00000000000..5db4432ff12 --- /dev/null +++ b/tools/perf/ui/gtk/helpline.c @@ -0,0 +1,56 @@ +#include <stdio.h> +#include <string.h> + +#include "gtk.h" +#include "../ui.h" +#include "../helpline.h" +#include "../../util/debug.h" + +static void gtk_helpline_pop(void) +{ + if (!perf_gtk__is_active_context(pgctx)) + return; + + gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar), + pgctx->statbar_ctx_id); +} + +static void gtk_helpline_push(const char *msg) +{ + if (!perf_gtk__is_active_context(pgctx)) + return; + + gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar), + pgctx->statbar_ctx_id, msg); +} + +static struct ui_helpline gtk_helpline_fns = { + .pop = gtk_helpline_pop, + .push = gtk_helpline_push, +}; + +void perf_gtk__init_helpline(void) +{ + helpline_fns = >k_helpline_fns; +} + +int perf_gtk__show_helpline(const char *fmt, va_list ap) +{ + int ret; + char *ptr; + static int backlog; + + ret = vscnprintf(ui_helpline__current + backlog, + sizeof(ui_helpline__current) - backlog, fmt, ap); + backlog += ret; + + /* only first line can be displayed */ + ptr = strchr(ui_helpline__current, '\n'); + if (ptr && (ptr - ui_helpline__current) <= backlog) { + *ptr = '\0'; + ui_helpline__puts(ui_helpline__current); + backlog = 0; + } + + return ret; +} diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index 92879ce61e2..3c4c6ef7828 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c @@ -7,11 +7,15 @@ extern struct perf_error_ops perf_gtk_eops; int perf_gtk__init(void) { perf_error__register(&perf_gtk_eops); + perf_gtk__init_helpline(); + perf_gtk__init_hpp(); return gtk_init_check(NULL, NULL) ? 0 : -1; } -void perf_gtk__exit(bool wait_for_ok __used) +void perf_gtk__exit(bool wait_for_ok __maybe_unused) { + if (!perf_gtk__is_active_context(pgctx)) + return; perf_error__unregister(&perf_gtk_eops); gtk_main_quit(); } diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index 0ead373c0df..8aada5b3c04 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -117,13 +117,8 @@ struct perf_error_ops perf_gtk_eops = { * For now, just add stubs for NO_NEWT=1 build. */ #ifdef NO_NEWT_SUPPORT -int ui_helpline__show_help(const char *format __used, va_list ap __used) -{ - return 0; -} - -void ui_progress__update(u64 curr __used, u64 total __used, - const char *title __used) +void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, + const char *title __maybe_unused) { } #endif diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c index 2f950c2641c..a49bcf3c190 100644 --- a/tools/perf/ui/helpline.c +++ b/tools/perf/ui/helpline.c @@ -5,23 +5,32 @@ #include "../debug.h" #include "helpline.h" #include "ui.h" -#include "libslang.h" -void ui_helpline__pop(void) +char ui_helpline__current[512]; + +static void nop_helpline__pop(void) { } -char ui_helpline__current[512]; +static void nop_helpline__push(const char *msg __maybe_unused) +{ +} -void ui_helpline__push(const char *msg) +static struct ui_helpline default_helpline_fns = { + .pop = nop_helpline__pop, + .push = nop_helpline__push, +}; + +struct ui_helpline *helpline_fns = &default_helpline_fns; + +void ui_helpline__pop(void) { - const size_t sz = sizeof(ui_helpline__current); + helpline_fns->pop(); +} - SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); - SLsmg_set_color(0); - SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols); - SLsmg_refresh(); - strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; +void ui_helpline__push(const char *msg) +{ + helpline_fns->push(msg); } void ui_helpline__vpush(const char *fmt, va_list ap) @@ -50,30 +59,3 @@ void ui_helpline__puts(const char *msg) ui_helpline__pop(); ui_helpline__push(msg); } - -void ui_helpline__init(void) -{ - ui_helpline__puts(" "); -} - -char ui_helpline__last_msg[1024]; - -int ui_helpline__show_help(const char *format, va_list ap) -{ - int ret; - static int backlog; - - pthread_mutex_lock(&ui__lock); - ret = vscnprintf(ui_helpline__last_msg + backlog, - sizeof(ui_helpline__last_msg) - backlog, format, ap); - backlog += ret; - - if (ui_helpline__last_msg[backlog - 1] == '\n') { - ui_helpline__puts(ui_helpline__last_msg); - SLsmg_refresh(); - backlog = 0; - } - pthread_mutex_unlock(&ui__lock); - - return ret; -} diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h index 7bab6b34e35..2b667ee454c 100644 --- a/tools/perf/ui/helpline.h +++ b/tools/perf/ui/helpline.h @@ -4,13 +4,44 @@ #include <stdio.h> #include <stdarg.h> +#include "../util/cache.h" + +struct ui_helpline { + void (*pop)(void); + void (*push)(const char *msg); +}; + +extern struct ui_helpline *helpline_fns; + void ui_helpline__init(void); + void ui_helpline__pop(void); void ui_helpline__push(const char *msg); void ui_helpline__vpush(const char *fmt, va_list ap); void ui_helpline__fpush(const char *fmt, ...); void ui_helpline__puts(const char *msg); -extern char ui_helpline__current[]; +extern char ui_helpline__current[512]; + +#ifdef NO_NEWT_SUPPORT +static inline int ui_helpline__show_help(const char *format __maybe_unused, + va_list ap __maybe_unused) +{ + return 0; +} +#else +extern char ui_helpline__last_msg[]; +int ui_helpline__show_help(const char *format, va_list ap); +#endif /* NO_NEWT_SUPPORT */ + +#ifdef NO_GTK2_SUPPORT +static inline int perf_gtk__show_helpline(const char *format __maybe_unused, + va_list ap __maybe_unused) +{ + return 0; +} +#else +int perf_gtk__show_helpline(const char *format, va_list ap); +#endif /* NO_GTK2_SUPPORT */ #endif /* _PERF_UI_HELPLINE_H_ */ diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c new file mode 100644 index 00000000000..e3f8cd46e7d --- /dev/null +++ b/tools/perf/ui/hist.c @@ -0,0 +1,390 @@ +#include <math.h> + +#include "../util/hist.h" +#include "../util/util.h" +#include "../util/sort.h" + + +/* hist period print (hpp) functions */ +static int hpp__header_overhead(struct perf_hpp *hpp) +{ + const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; + + return scnprintf(hpp->buf, hpp->size, fmt); +} + +static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) +{ + return 8; +} + +static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = 100.0 * he->period / hpp->total_period; + + if (hpp->ptr) { + struct hists *old_hists = hpp->ptr; + u64 total_period = old_hists->stats.total_period; + u64 base_period = he->pair ? he->pair->period : 0; + + if (total_period) + percent = 100.0 * base_period / total_period; + else + percent = 0.0; + } + + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); +} + +static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = 100.0 * he->period / hpp->total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; + + if (hpp->ptr) { + struct hists *old_hists = hpp->ptr; + u64 total_period = old_hists->stats.total_period; + u64 base_period = he->pair ? he->pair->period : 0; + + if (total_period) + percent = 100.0 * base_period / total_period; + else + percent = 0.0; + } + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_overhead_sys(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "sys"); +} + +static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) +{ + return 7; +} + +static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = 100.0 * he->period_sys / hpp->total_period; + return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); +} + +static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = 100.0 * he->period_sys / hpp->total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_overhead_us(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "user"); +} + +static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) +{ + return 7; +} + +static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = 100.0 * he->period_us / hpp->total_period; + return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); +} + +static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = 100.0 * he->period_us / hpp->total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp) +{ + return scnprintf(hpp->buf, hpp->size, "guest sys"); +} + +static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused) +{ + return 9; +} + +static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, + struct hist_entry *he) +{ + double percent = 100.0 * he->period_guest_sys / hpp->total_period; + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); +} + +static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, + struct hist_entry *he) +{ + double percent = 100.0 * he->period_guest_sys / hpp->total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_overhead_guest_us(struct perf_hpp *hpp) +{ + return scnprintf(hpp->buf, hpp->size, "guest usr"); +} + +static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused) +{ + return 9; +} + +static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, + struct hist_entry *he) +{ + double percent = 100.0 * he->period_guest_us / hpp->total_period; + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); +} + +static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, + struct hist_entry *he) +{ + double percent = 100.0 * he->period_guest_us / hpp->total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_samples(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); +} + +static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused) +{ + return 11; +} + +static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he) +{ + const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; + + return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); +} + +static int hpp__header_period(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "Period"); +} + +static int hpp__width_period(struct perf_hpp *hpp __maybe_unused) +{ + return 12; +} + +static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he) +{ + const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; + + return scnprintf(hpp->buf, hpp->size, fmt, he->period); +} + +static int hpp__header_delta(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); +} + +static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) +{ + return 7; +} + +static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) +{ + struct hists *pair_hists = hpp->ptr; + u64 old_total, new_total; + double old_percent = 0, new_percent = 0; + double diff; + const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; + char buf[32] = " "; + + old_total = pair_hists->stats.total_period; + if (old_total > 0 && he->pair) + old_percent = 100.0 * he->pair->period / old_total; + + new_total = hpp->total_period; + if (new_total > 0) + new_percent = 100.0 * he->period / new_total; + + diff = new_percent - old_percent; + if (fabs(diff) >= 0.01) + scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); + + return scnprintf(hpp->buf, hpp->size, fmt, buf); +} + +static int hpp__header_displ(struct perf_hpp *hpp) +{ + return scnprintf(hpp->buf, hpp->size, "Displ."); +} + +static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) +{ + return 6; +} + +static int hpp__entry_displ(struct perf_hpp *hpp, + struct hist_entry *he __maybe_unused) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; + char buf[32] = " "; + + if (hpp->displacement) + scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); + + return scnprintf(hpp->buf, hpp->size, fmt, buf); +} + +#define HPP__COLOR_PRINT_FNS(_name) \ + .header = hpp__header_ ## _name, \ + .width = hpp__width_ ## _name, \ + .color = hpp__color_ ## _name, \ + .entry = hpp__entry_ ## _name + +#define HPP__PRINT_FNS(_name) \ + .header = hpp__header_ ## _name, \ + .width = hpp__width_ ## _name, \ + .entry = hpp__entry_ ## _name + +struct perf_hpp_fmt perf_hpp__format[] = { + { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, + { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, + { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, + { .cond = false, |