lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1447047946-1691-3-git-send-email-namhyung@kernel.org>
Date:	Mon,  9 Nov 2015 14:45:38 +0900
From:	Namhyung Kim <namhyung@...nel.org>
To:	Arnaldo Carvalho de Melo <acme@...nel.org>
Cc:	Ingo Molnar <mingo@...nel.org>,
	Peter Zijlstra <a.p.zijlstra@...llo.nl>,
	Jiri Olsa <jolsa@...hat.com>,
	LKML <linux-kernel@...r.kernel.org>,
	Brendan Gregg <brendan.d.gregg@...il.com>,
	David Ahern <dsahern@...il.com>,
	Frederic Weisbecker <fweisbec@...il.com>,
	Andi Kleen <andi@...stfloor.org>,
	Kan Liang <kan.liang@...el.com>
Subject: [PATCH] perf report: [WIP] Support '-F none' option to hide hist lines

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 <brendan.d.gregg@...il.com>
Signed-off-by: Namhyung Kim <namhyung@...nel.org>
---
 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@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ