Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756461AbbGQDuW (ORCPT ); Thu, 16 Jul 2015 23:50:22 -0400 Received: from mga11.intel.com ([192.55.52.93]:34073 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754560AbbGQDsf (ORCPT ); Thu, 16 Jul 2015 23:48:35 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,492,1432623600"; d="scan'208";a="607841831" 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 Subject: [PATCH 9/9] perf,tools: Show freq in perf report --stdio Date: Thu, 16 Jul 2015 16:33:51 -0400 Message-Id: <1437078831-10152-10-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1437078831-10152-1-git-send-email-kan.liang@intel.com> References: <1437078831-10152-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 11994 Lines: 348 From: Kan Liang 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 --- 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 -- 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/