Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752687AbbKIFp6 (ORCPT ); Mon, 9 Nov 2015 00:45:58 -0500 Received: from LGEAMRELO13.lge.com ([156.147.23.53]:43282 "EHLO lgeamrelo13.lge.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752177AbbKIFpw (ORCPT ); Mon, 9 Nov 2015 00:45:52 -0500 X-Original-SENDERIP: 156.147.1.151 X-Original-MAILFROM: namhyung@kernel.org X-Original-SENDERIP: 10.177.227.17 X-Original-MAILFROM: namhyung@kernel.org From: Namhyung Kim To: Arnaldo Carvalho de Melo Cc: Ingo Molnar , Peter Zijlstra , Jiri Olsa , LKML , Brendan Gregg , David Ahern , Frederic Weisbecker , Andi Kleen , Kan Liang Subject: [PATCH] perf report: [WIP] Support '-F none' option to hide hist lines Date: Mon, 9 Nov 2015 14:45:38 +0900 Message-Id: <1447047946-1691-3-git-send-email-namhyung@kernel.org> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1447047946-1691-1-git-send-email-namhyung@kernel.org> References: <1447047946-1691-1-git-send-email-namhyung@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10920 Lines: 331 For some reason, it sometimes wants to hide hist lines but only wants to see callchains. To do that, add virtual 'none' field name to hide all hist lines. It should be used solely and only meaningful on --stdio. WIP on TUI Cc: Brendan Gregg Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-report.txt | 3 ++ tools/perf/ui/browsers/hists.c | 22 +++++++++-- tools/perf/ui/gtk/hists.c | 65 ++++++++++++++++++++++++-------- tools/perf/ui/stdio/hist.c | 5 +++ tools/perf/util/sort.c | 5 +++ 5 files changed, 82 insertions(+), 18 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index dab99ed2b339..6cfc643c0806 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -127,6 +127,9 @@ OPTIONS By default, every sort keys not specified in -F will be appended automatically. + If "none" is specified, it hides all fields and --stdio output will show + callchains only. + If --mem-mode option is used, following sort keys are also available (incompatible with --branch-stack): symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 3efe7c74f47d..c2f586f0c729 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -78,6 +78,9 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb) nr_entries = hb->hists->nr_entries; hb->nr_callchain_rows = hist_browser__get_folding(hb); + + if (list_empty(&perf_hpp__list)) + nr_entries = 1; return nr_entries + hb->nr_callchain_rows; } @@ -255,7 +258,10 @@ static bool hist_entry__toggle_fold(struct hist_entry *he) if (!he->has_children) return false; - he->unfolded = !he->unfolded; + if (list_empty(&perf_hpp__list)) + he->unfolded = true; + else + he->unfolded = !he->unfolded; return true; } @@ -329,6 +335,10 @@ static void hist_entry__init_have_children(struct hist_entry *he) if (!he->init_have_children) { he->has_children = !RB_EMPTY_ROOT(&he->sorted_chain); callchain__init_have_children(&he->sorted_chain); + if (list_empty(&perf_hpp__list)) { + he->unfolded = true; + he->nr_rows = callchain__count_rows(&he->sorted_chain); + } he->init_have_children = true; } } @@ -1038,6 +1048,9 @@ static int hist_browser__show_entry(struct hist_browser *browser, hist_browser__gotorc(browser, row, 0); + if (list_empty(&perf_hpp__list)) + goto print_callchain; + perf_hpp__for_each_format(fmt) { if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) continue; @@ -1080,6 +1093,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, } else --row_offset; +print_callchain: if (folded_sign == '-' && row != browser->b.rows) { u64 total = hists__total_period(entry->hists); struct callchain_print_arg arg = { @@ -1313,7 +1327,8 @@ static void ui_browser__hists_seek(struct ui_browser *browser, nd = hists__filter_entries(rb_next(nd), hb->min_pcnt); if (nd == NULL) break; - --offset; + if (!list_empty(&perf_hpp__list)) + --offset; browser->top = nd; } while (offset != 0); } else if (offset < 0) { @@ -1347,7 +1362,8 @@ static void ui_browser__hists_seek(struct ui_browser *browser, hb->min_pcnt); if (nd == NULL) break; - ++offset; + if (!list_empty(&perf_hpp__list)) + ++offset; browser->top = nd; if (offset == 0) { /* diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 6105b4921754..535f8c5e74dc 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -98,12 +98,12 @@ static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *sto for (nd = rb_first(root); nd; nd = rb_next(nd)) { struct callchain_node *node; struct callchain_list *chain; - GtkTreeIter iter, new_parent; + GtkTreeIter iter, new_parent_iter, *new_parent; bool need_new_parent; node = rb_entry(nd, struct callchain_node, rb_node); - new_parent = *parent; + new_parent = parent; need_new_parent = !has_single_node; callchain_node__make_parent_list(node); @@ -111,7 +111,7 @@ static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *sto list_for_each_entry(chain, &node->parent_val, list) { char buf[128]; - gtk_tree_store_append(store, &iter, &new_parent); + gtk_tree_store_append(store, &iter, new_parent); callchain_node__sprintf_value(node, buf, sizeof(buf), total); gtk_tree_store_set(store, &iter, 0, buf, -1); @@ -124,7 +124,8 @@ static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *sto * Only show the top-most symbol in a callchain * if it's not the only callchain. */ - new_parent = iter; + new_parent_iter = iter; + new_parent = &new_parent_iter; need_new_parent = false; } } @@ -132,7 +133,7 @@ static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *sto list_for_each_entry(chain, &node->val, list) { char buf[128]; - gtk_tree_store_append(store, &iter, &new_parent); + gtk_tree_store_append(store, &iter, new_parent); callchain_node__sprintf_value(node, buf, sizeof(buf), total); gtk_tree_store_set(store, &iter, 0, buf, -1); @@ -145,7 +146,8 @@ static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *sto * Only show the top-most symbol in a callchain * if it's not the only callchain. */ - new_parent = iter; + new_parent_iter = iter; + new_parent = &new_parent_iter; need_new_parent = false; } } @@ -221,19 +223,19 @@ static void perf_gtk__add_callchain_graph(struct rb_root *root, GtkTreeStore *st for (nd = rb_first(root); nd; nd = rb_next(nd)) { struct callchain_node *node; struct callchain_list *chain; - GtkTreeIter iter, new_parent; + GtkTreeIter iter, new_parent_iter, *new_parent; bool need_new_parent; u64 child_total; node = rb_entry(nd, struct callchain_node, rb_node); - new_parent = *parent; + new_parent = parent; need_new_parent = !has_single_node && (node->val_nr > 1); list_for_each_entry(chain, &node->val, list) { char buf[128]; - gtk_tree_store_append(store, &iter, &new_parent); + gtk_tree_store_append(store, &iter, new_parent); callchain_node__sprintf_value(node, buf, sizeof(buf), total); gtk_tree_store_set(store, &iter, 0, buf, -1); @@ -246,7 +248,8 @@ static void perf_gtk__add_callchain_graph(struct rb_root *root, GtkTreeStore *st * Only show the top-most symbol in a callchain * if it's not the only callchain. */ - new_parent = iter; + new_parent_iter = iter; + new_parent = &new_parent_iter; need_new_parent = false; } } @@ -292,12 +295,14 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, GType col_types[MAX_COLUMNS]; GtkCellRenderer *renderer; GtkTreeStore *store; + GtkTreeIter *iter; struct rb_node *nd; GtkWidget *view; int col_idx; int sym_col = -1; int nr_cols; char s[512]; + bool no_hists = false; struct perf_hpp hpp = { .buf = s, @@ -309,6 +314,18 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, perf_hpp__for_each_format(fmt) col_types[nr_cols++] = G_TYPE_STRING; + if (nr_cols == 0) { + /* + * user specified '-F none' to ignore hist entries. + * Add two columns to print callchain value and symbols. + */ + no_hists = true; + + nr_cols = 2; + col_types[0] = G_TYPE_STRING; + col_types[1] = G_TYPE_STRING; + } + store = gtk_tree_store_newv(nr_cols, col_types); view = gtk_tree_view_new(); @@ -334,6 +351,18 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx++, NULL); } + if (no_hists) { + sym_col = 1; + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, "Overhead", + renderer, "markup", + 0, NULL); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, "Callchains", + renderer, "markup", + 1, NULL); + } + for (col_idx = 0; col_idx < nr_cols; col_idx++) { GtkTreeViewColumn *column; @@ -352,7 +381,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, 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; + GtkTreeIter this_iter; u64 total = hists__total_period(h->hists); float percent; @@ -363,7 +392,13 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, if (percent < min_pcnt) continue; - gtk_tree_store_append(store, &iter, NULL); + if (no_hists) { + /* NULL means that callchains are in top-level */ + iter = NULL; + } else { + iter = &this_iter; + gtk_tree_store_append(store, iter, NULL); + } col_idx = 0; @@ -376,15 +411,15 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, else fmt->entry(fmt, &hpp, h); - gtk_tree_store_set(store, &iter, col_idx++, s, -1); + gtk_tree_store_set(store, iter, col_idx++, s, -1); } - if (symbol_conf.use_callchain && sort__has_sym) { + if (symbol_conf.use_callchain) { if (callchain_param.mode == CHAIN_GRAPH_REL) total = symbol_conf.cumulate_callchain ? h->stat_acc->period : h->stat.period; - perf_gtk__add_callchain(&h->sorted_chain, store, &iter, + perf_gtk__add_callchain(&h->sorted_chain, store, iter, sym_col, total); } } diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 7ebc661be267..48ae34abf9c8 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -422,6 +422,11 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, if (size == 0 || size > bfsz) size = hpp.size = bfsz; + /* + * In case of '-F none', the bf is not set at all. + */ + bf[0] = '\0'; + hist_entry__snprintf(he, &hpp); ret = fprintf(fp, "%s\n", bf); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 2d8ccd4d9e1b..8c731906d432 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1923,6 +1923,11 @@ static int __setup_output_field(void) if (field_order == NULL) return 0; + if (!strcmp(field_order, "none")) { + symbol_conf.show_hist_headers = false; + return 0; + } + strp = str = strdup(field_order); if (str == NULL) { error("Not enough memory to setup output fields"); -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/