mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: kan.liang@intel.com
To: a.p.zijlstra@chello.nl
Cc: mingo@redhat.com, acme@kernel.org, eranian@google.com,
	ak@linux.intel.com, mark.rutland@arm.com,
	adrian.hunter@intel.com, dsahern@gmail.com, jolsa@kernel.org,
	namhyung@kernel.org, linux-kernel@vger.kernel.org,
	Kan Liang <kan.liang@intel.com>
Subject: [PATCH 9/9] perf,tools: Show freq in perf report --stdio
Date: Thu, 16 Jul 2015 16:33:51 -0400	[thread overview]
Message-ID: <1437078831-10152-10-git-send-email-kan.liang@intel.com> (raw)
In-Reply-To: <1437078831-10152-1-git-send-email-kan.liang@intel.com>

From: Kan Liang <kan.liang@intel.com>

Show freq for each symbol in perf report by --stdio --show-freq

In sampling group, only group leader do sampling. So only need to print
group leader's freq in --group.

Here is an example.

 $ perf report --stdio --group --show-freq

 # Samples: 71K of event 'anon group { ref-cycles, core_misc/tsc/,
 core_misc/power-mperf/, core_misc/power-aperf/ }'
 # Event count (approx.): 215265868412
 #
 #                         Overhead    TSC MHz    AVG MHz    BZY MHz
 Command       Shared Object     Symbol
 # ................................  .........  .........  .........
 ............  ................  ..................................
 #
     98.85%   5.41%  98.89%  98.95%       2293       1474       2302
 tchain_edit   tchain_edit       [.] f3
      0.39%   1.64%   0.39%   0.37%       2295          1       3053
 kworker/25:1  [kernel.vmlinux]  [k] delay_tsc
      0.08%  24.20%   0.07%   0.06%       2295         82       2746
 swapper       [kernel.vmlinux]  [k] acpi_idle_do_entry
      0.05%   0.00%   0.05%   0.05%       2295       2289       2295
 tchain_edit   tchain_edit       [.] f2

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 tools/perf/Documentation/perf-report.txt | 10 +++++
 tools/perf/builtin-report.c              | 17 ++++++++
 tools/perf/perf.h                        |  1 +
 tools/perf/ui/hist.c                     | 69 +++++++++++++++++++++++++++++---
 tools/perf/util/hist.h                   |  3 ++
 tools/perf/util/session.c                |  2 +-
 tools/perf/util/sort.c                   |  3 ++
 tools/perf/util/symbol.h                 |  3 +-
 tools/perf/util/util.c                   |  4 ++
 9 files changed, 105 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index c33b69f..fb82390 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -303,6 +303,16 @@ OPTIONS
 	special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
 	'perf mem' for simpler access.
 
+--show-freq::
+	Show frequency result from sample read.
+	To generate the frequency output, the perf.data file must have been
+	obtained using perf record -a --running-time, using special events
+	-e core_misc/tsc/, core_misc/power-mperf/ or core_misc/power-aperf/,
+	and group read.
+	TSC MHz: average MHz that the TSC ran during the sample interval.
+	AVG MHz: number of cycles executed divided by time elapsed.
+	BZY MHz: average clock rate while the CPU was busy (in "c0" state).
+
 --percent-limit::
 	Do not show entries which have an overhead under that percent.
 	(Default: 0).
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 95a4771..00e77e2 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -164,6 +164,8 @@ static int process_sample_event(struct perf_tool *tool,
 		iter.ops = &hist_iter_mem;
 	else if (symbol_conf.cumulate_callchain)
 		iter.ops = &hist_iter_cumulative;
+	else if (symbol_conf.show_freq)
+		iter.ops = &hist_iter_freq;
 	else
 		iter.ops = &hist_iter_normal;
 
@@ -721,6 +723,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 		    "Enable kernel symbol demangling"),
 	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
+	OPT_BOOLEAN(0, "show-freq", &symbol_conf.show_freq, "freqency profile"),
 	OPT_CALLBACK(0, "percent-limit", &report, "percent",
 		     "Don't show entries under that percent", parse_percent_limit),
 	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
@@ -733,6 +736,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	struct perf_data_file file = {
 		.mode  = PERF_DATA_MODE_READ,
 	};
+	struct perf_evsel *pos;
 	int ret = hists__init();
 
 	if (ret < 0)
@@ -818,6 +822,19 @@ repeat:
 		symbol_conf.cumulate_callchain = false;
 	}
 
+	if (symbol_conf.show_freq) {
+		evlist__for_each(session->evlist, pos) {
+			if (pos->attr.type == PERF_TYPE_CORE_MISC_FREE) {
+				if (pos->attr.config == PERF_POWER_APERF)
+					perf_aperf = true;
+				if (pos->attr.config == PERF_POWER_MPERF)
+					perf_mperf = true;
+				if (pos->attr.config == PERF_TSC)
+					perf_tsc = true;
+			}
+		}
+	}
+
 	if (setup_sorting() < 0) {
 		if (sort_order)
 			parse_options_usage(report_usage, options, "s", 1);
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 937b16a..54d248ec 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -33,6 +33,7 @@ static inline unsigned long long rdclock(void)
 
 extern const char *input_name;
 extern bool perf_host, perf_guest;
+extern bool perf_tsc, perf_aperf, perf_mperf;
 extern const char perf_version_string[];
 
 void pthread__unblock_sigwinch(void);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 25d6083..3cb2cd5 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -17,7 +17,7 @@
 
 static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
 		      hpp_field_fn get_field, const char *fmt, int len,
-		      hpp_snprint_fn print_fn, bool fmt_percent)
+		      hpp_snprint_fn print_fn, bool fmt_percent, bool single)
 {
 	int ret;
 	struct hists *hists = he->hists;
@@ -36,7 +36,7 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
 	} else
 		ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
 
-	if (perf_evsel__is_group_event(evsel)) {
+	if (perf_evsel__is_group_event(evsel) && !single) {
 		int prev_idx, idx_delta;
 		struct hist_entry *pair;
 		int nr_members = evsel->nr_members;
@@ -109,10 +109,17 @@ int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	     const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
 {
 	int len = fmt->user_len ?: fmt->len;
+	bool single = false;
+
+	if (symbol_conf.show_freq &&
+	    ((fmt == &perf_hpp__format[PERF_HPP__TSC]) ||
+	     (fmt == &perf_hpp__format[PERF_HPP__AVG]) ||
+	     (fmt == &perf_hpp__format[PERF_HPP__BZY])))
+		single = true;
 
 	if (symbol_conf.field_sep) {
 		return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
-				  print_fn, fmt_percent);
+				  print_fn, fmt_percent, single);
 	}
 
 	if (fmt_percent)
@@ -120,7 +127,7 @@ int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	else
 		len -= 1;
 
-	return  __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
+	return  __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent, single);
 }
 
 int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -234,6 +241,30 @@ static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
 }
 
+static int hpp__single_width_fn(struct perf_hpp_fmt *fmt,
+			 struct perf_hpp *hpp __maybe_unused,
+			 struct perf_evsel *evsel)
+{
+	int len = fmt->user_len ?: fmt->len;
+
+	if (symbol_conf.event_group && !symbol_conf.show_freq)
+		len = max(len, evsel->nr_members * fmt->len);
+
+	if (len < (int)strlen(fmt->name))
+		len = strlen(fmt->name);
+
+	return len;
+}
+
+static int hpp__single_header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+			  struct perf_evsel *evsel)
+{
+	int len = hpp__single_width_fn(fmt, hpp, evsel);
+
+	return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
+}
+
+
 static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
 {
 	va_list args;
@@ -363,6 +394,9 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period)
 
 HPP_RAW_FNS(samples, nr_events)
 HPP_RAW_FNS(period, period)
+HPP_RAW_FNS(tsc_freq, tsc_freq)
+HPP_RAW_FNS(avg_freq, avg_freq)
+HPP_RAW_FNS(bzy_freq, bzy_freq)
 
 static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
 			    struct hist_entry *a __maybe_unused,
@@ -395,6 +429,17 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
 		.sort	= hpp__sort_ ## _fn,		\
 	}
 
+#define HPP__SINGLE_PRINT_FNS(_name, _fn)		\
+	{						\
+		.name   = _name,			\
+		.header	= hpp__single_header_fn,	\
+		.width	= hpp__single_width_fn,		\
+		.entry	= hpp__entry_ ## _fn,		\
+		.cmp	= hpp__nop_cmp,			\
+		.collapse = hpp__nop_cmp,		\
+		.sort	= hpp__sort_ ## _fn,		\
+	}
+
 #define HPP__PRINT_FNS(_name, _fn)			\
 	{						\
 		.name   = _name,			\
@@ -414,7 +459,10 @@ struct perf_hpp_fmt perf_hpp__format[] = {
 	HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
 	HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
 	HPP__PRINT_FNS("Samples", samples),
-	HPP__PRINT_FNS("Period", period)
+	HPP__PRINT_FNS("Period", period),
+	HPP__SINGLE_PRINT_FNS("TSC MHz", tsc_freq),
+	HPP__SINGLE_PRINT_FNS("AVG MHz", avg_freq),
+	HPP__SINGLE_PRINT_FNS("BZY MHz", bzy_freq)
 };
 
 LIST_HEAD(perf_hpp__list);
@@ -485,6 +533,14 @@ void perf_hpp__init(void)
 	if (symbol_conf.show_total_period)
 		perf_hpp__column_enable(PERF_HPP__PERIOD);
 
+	if (symbol_conf.show_freq) {
+		if (perf_tsc)
+			perf_hpp__column_enable(PERF_HPP__TSC);
+		if (perf_aperf)
+			perf_hpp__column_enable(PERF_HPP__AVG);
+		if (perf_mperf && perf_tsc && perf_aperf)
+			perf_hpp__column_enable(PERF_HPP__BZY);
+	}
 	/* prepend overhead field for backward compatiblity.  */
 	list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
 	if (list_empty(list))
@@ -661,6 +717,9 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
 
 	case PERF_HPP__OVERHEAD_GUEST_SYS:
 	case PERF_HPP__OVERHEAD_GUEST_US:
+	case PERF_HPP__TSC:
+	case PERF_HPP__AVG:
+	case PERF_HPP__BZY:
 		fmt->len = 9;
 		break;
 
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 3601658..71e2fa3 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -237,6 +237,9 @@ enum {
 	PERF_HPP__OVERHEAD_ACC,
 	PERF_HPP__SAMPLES,
 	PERF_HPP__PERIOD,
+	PERF_HPP__TSC,
+	PERF_HPP__AVG,
+	PERF_HPP__BZY,
 
 	PERF_HPP__MAX_INDEX
 };
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index bffa58b..e14128a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1026,7 +1026,7 @@ static int deliver_sample_value(struct perf_evlist *evlist,
 			    (++nr >= sample->read.group.nr))
 				break;
 
-			if (evsel->attr.type == PERF_TYPE_CORE_MISC_FREE) {
+			if (symbol_conf.show_freq && evsel->attr.type == PERF_TYPE_CORE_MISC_FREE) {
 				if (evsel->attr.config == PERF_POWER_APERF)
 					sample->aperf = sample->read.group.values[nr].value;
 				if (evsel->attr.config == PERF_POWER_MPERF)
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 4c65a14..f618fba 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1225,6 +1225,9 @@ static struct hpp_dimension hpp_sort_dimensions[] = {
 	DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
 	DIM(PERF_HPP__SAMPLES, "sample"),
 	DIM(PERF_HPP__PERIOD, "period"),
+	DIM(PERF_HPP__TSC, "tsc"),
+	DIM(PERF_HPP__AVG, "avg"),
+	DIM(PERF_HPP__BZY, "bzy"),
 };
 
 #undef DIM
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b71d575..60a6f1a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -106,7 +106,8 @@ struct symbol_conf {
 			filter_relative,
 			show_hist_headers,
 			branch_callstack,
-			has_filter;
+			has_filter,
+			show_freq;
 	const char	*vmlinux_name,
 			*kallsyms_name,
 			*source_prefix,
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index edc2d63..c299af9 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -34,6 +34,10 @@ bool test_attr__enabled;
 bool perf_host  = true;
 bool perf_guest = false;
 
+bool perf_tsc = false;
+bool perf_aperf = false;
+bool perf_mperf = false;
+
 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
 
 void event_attr_init(struct perf_event_attr *attr)
-- 
1.8.3.1


  parent reply	other threads:[~2015-07-17  3:50 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-16 20:33 [PATCH 0/9] Intel core misc PMUs support kan.liang
2015-07-16 20:33 ` [PATCH 1/9] perf/x86: Add " kan.liang
2015-07-16 20:33 ` [PATCH 2/9] perf/x86: core_misc PMU disable and enable support kan.liang
2015-07-17 12:11   ` Mark Rutland
2015-07-17 13:46     ` Peter Zijlstra
2015-07-17 13:51       ` Peter Zijlstra
2015-07-17 15:35         ` Liang, Kan
2015-07-17 17:01           ` Andy Lutomirski
2015-07-17 17:52             ` Liang, Kan
2015-07-17 17:58               ` Andy Lutomirski
2015-07-17 18:15                 ` Liang, Kan
2015-07-17 18:56                   ` Andy Lutomirski
2015-07-17 21:11                   ` Peter Zijlstra
2015-07-16 20:33 ` [PATCH 3/9] perf/x86: Add is_hardware_event kan.liang
2015-07-17 10:48   ` Mark Rutland
2015-07-17 15:03     ` Liang, Kan
2015-07-17 15:47       ` Mark Rutland
2015-07-17 16:11         ` Mark Rutland
2015-07-16 20:33 ` [PATCH 4/9] perf/x86: special case per-cpu core misc PMU events kan.liang
2015-07-17 12:21   ` Mark Rutland
2015-07-17 12:55     ` Peter Zijlstra
2015-07-17 18:11       ` Stephane Eranian
2015-07-17 20:17     ` Andi Kleen
2015-07-20 16:12       ` Mark Rutland
2015-07-16 20:33 ` [PATCH 5/9] perf,tools: open event with it's own cpus and threads kan.liang
2015-07-16 20:33 ` [PATCH 6/9] perf,tools: Dump per-sample freq in report -D kan.liang
2015-07-16 20:33 ` [PATCH 7/9] perf,tools: save APERF/MPERF/TSC in struct perf_sample kan.liang
2015-07-16 20:33 ` [PATCH 8/9] perf,tools: caculate and save tsc/avg/bzy freq in he_stat kan.liang
2015-07-17 20:25   ` Andi Kleen
2015-07-17 20:57     ` Liang, Kan
2015-07-17 21:27       ` Andi Kleen
2015-07-16 20:33 ` kan.liang [this message]
2015-07-17 11:39 ` [PATCH 0/9] Intel core misc PMUs support Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1437078831-10152-10-git-send-email-kan.liang@intel.com \
    --to=kan.liang@intel.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=dsahern@gmail.com \
    --cc=eranian@google.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®