Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1218543 > unrolled thread
| Started by | kan.liang@intel.com |
|---|---|
| First post | 2015-09-03 21:50 +0200 |
| Last post | 2015-09-07 13:40 +0200 |
| Articles | 7 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH V8 0/7] Freq/CPU%/CORE_BUSY% support kan.liang@intel.com - 2015-09-03 21:50 +0200
[PATCH V8 7/7] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report --stdio kan.liang@intel.com - 2015-09-03 21:50 +0200
Re: [PATCH V8 7/7] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report --stdio Jiri Olsa <jolsa@redhat.com> - 2015-09-07 13:20 +0200
[PATCH V8 4/7] perf,tools: fix dump_sample crash when evsel is NULL. kan.liang@intel.com - 2015-09-03 21:50 +0200
[tip:perf/core] perf session: Don't call dump_sample() when evsel is NULL tip-bot for Kan Liang <tipbot@zytor.com> - 2015-09-08 16:40 +0200
[PATCH V8 2/7] perf,tools: read msr pmu type from header. kan.liang@intel.com - 2015-09-03 21:50 +0200
Re: [PATCH V8 0/7] Freq/CPU%/CORE_BUSY% support Jiri Olsa <jolsa@redhat.com> - 2015-09-07 13:40 +0200
| From | kan.liang@intel.com |
|---|---|
| Date | 2015-09-03 21:50 +0200 |
| Subject | [PATCH V8 0/7] Freq/CPU%/CORE_BUSY% support |
| Message-ID | <q4IGe-4OA-5@gated-at.bofh.it> |
From: Kan Liang <kan.liang@intel.com>
This patch set supports per-sample freq/CPU%/CORE_BUSY% print in perf
report -D and --stdio.
For printing these information, the perf.data file must have been obtained
by group read and using special events cycles, ref-cycles, msr/tsc/,
msr/aperf/ or msr/mperf/.
- Freq (MHz): The frequency during the sample interval. Needs cycles
ref-cycles event.
- CPU%: CPU utilization during the sample interval. Needs ref-cycles and
msr/tsc/ events.
- CORE_BUSY%: actual percent performance (APERF/MPERF%) during the
sample interval. Needs msr/aperf/ and msr/mperf/ events.
Here is an example:
$ perf record --freq-perf ~/tchain_edit
$ perf report --stdio --group --show-freq-perf
Overhead FREQ MHz CPU% CORE_BUSY%
Command Shared Object Symbol
........................................ ......... ..... ..........
........... ................ ......................
99.54% 99.54% 99.53% 99.53% 99.53% 2301 96 99
tchain_edit tchain_edit [.] f3
0.20% 0.20% 0.20% 0.20% 0.20% 2301 98 99
tchain_edit tchain_edit [.] f2
0.05% 0.05% 0.05% 0.05% 0.05% 2300 98 99
tchain_edit [kernel.vmlinux] [k] read_tsc
Changes since V1:
- Save cpu max freq to header when recording
- Read cpu max freq and msr type from header when reporting
Changes since V2:
- Introduce generic FEAT for CPU related data stored
- Make cpu max freq and msr type part of perf_session_env
- rename cpu_u to cpu_util
- Don't save sample value in perf_sample and discards new iterator.
Calculating the freq_perf_info in add_entry_cb callback
- Introduce symbol_conf.freq_perf_type for related hpp column visibility
Changes since V3:
- add a identifier 'tag' for CPU attributes, max frequency.
- add backpointers to evlist for env, and evsel for evlist.
- Use bitmask for freq_perf_type
- Replace macros by functions to caculate freq, cpu_util and core_busy
- Move all caculation codes under symbol_conf.show_freq_perf condition.
Changes since V4:
- Store cpu attributes id as tag and more readable cpu_attr
Changes since V5:
- Rename freq to max_freq and use it
- Add a loop in process_cpu_attributes to facility future extension
Changes since V6:
- Split rename perf_session_env and add backpointer to evlist patches
Changes since V7:
- Introduce --freq-perf option for perf record
- Factor out fix for dump_sample
Kan Liang (7):
perf,tools: introduce generic FEAT for CPU attributes
perf,tools: read msr pmu type from header.
perf,record: introduce --freq-perf option
perf,tools: fix dump_sample crash when evsel is NULL.
perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat
perf,tools: Show freq/CPU%/CORE_BUSY% in perf report --stdio
tools/perf/Documentation/perf-record.txt | 4 ++
tools/perf/Documentation/perf-report.txt | 12 ++++++
tools/perf/builtin-record.c | 39 +++++++++++++++++-
tools/perf/builtin-report.c | 56 +++++++++++++++++++++++++
tools/perf/ui/hist.c | 71 +++++++++++++++++++++++++++++---
tools/perf/util/cpumap.c | 32 ++++++++++++++
tools/perf/util/cpumap.h | 1 +
tools/perf/util/header.c | 62 ++++++++++++++++++++++++++++
tools/perf/util/header.h | 13 ++++++
tools/perf/util/hist.h | 3 ++
tools/perf/util/session.c | 33 +++++++++++++--
tools/perf/util/session.h | 64 ++++++++++++++++++++++++++++
tools/perf/util/sort.c | 3 ++
tools/perf/util/sort.h | 3 ++
tools/perf/util/symbol.h | 12 +++++-
15 files changed, 397 insertions(+), 11 deletions(-)
--
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/
[toc] | [next] | [standalone]
| From | kan.liang@intel.com |
|---|---|
| Date | 2015-09-03 21:50 +0200 |
| Subject | [PATCH V8 7/7] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report --stdio |
| Message-ID | <q4IGf-4OA-21@gated-at.bofh.it> |
| In reply to | #1218543 |
From: Kan Liang <kan.liang@intel.com>
Show frequency, CPU Utilization and percent performance for each symbol
in perf report by --stdio --show-freq-perf
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-perf
Overhead FREQ MHz CPU% CORE_BUSY%
Command Shared Object Symbol
........................................ ......... ..... ..........
........... ................ ......................
99.54% 99.54% 99.53% 99.53% 99.53% 2301 96 99
tchain_edit tchain_edit [.] f3
0.20% 0.20% 0.20% 0.20% 0.20% 2301 98 99
tchain_edit tchain_edit [.] f2
0.05% 0.05% 0.05% 0.05% 0.05% 2300 98 99
tchain_edit [kernel.vmlinux] [k] read_tsc
Signed-off-by: Kan Liang <kan.liang@intel.com>
---
tools/perf/Documentation/perf-report.txt | 12 ++++++
tools/perf/builtin-report.c | 22 +++++++++-
tools/perf/ui/hist.c | 71 +++++++++++++++++++++++++++++---
tools/perf/util/hist.h | 3 ++
tools/perf/util/session.c | 33 ++++++++-------
tools/perf/util/sort.c | 3 ++
tools/perf/util/symbol.h | 12 +++++-
7 files changed, 134 insertions(+), 22 deletions(-)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9c7981b..6280e22 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -306,6 +306,18 @@ OPTIONS
special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
'perf mem' for simpler access.
+--show-freq-perf::
+ Show CPU frequency and performance result from sample read.
+ To generate the frequency and performance output, the perf.data file
+ must have been obtained by group read and using special events cycles,
+ ref-cycles, msr/tsc/, msr/aperf/ or msr/mperf/
+ Freq MHz: The frequency during the sample interval. Needs cycles and
+ ref-cycles event.
+ CPU%: CPU utilization during the sample interval. Needs ref-cycles and
+ msr/tsc/ events.
+ CORE_BUSY%: actual percent performance (APERF/MPERF%) during the
+ sample interval. Needs msr/aperf/ and msr/mperf/ events.
+
--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 7673f1c..ebcbe4c 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -133,7 +133,8 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
struct branch_info *bi;
if ((iter->ops == &hist_iter_normal) &&
- perf_evsel__is_group_leader(evsel))
+ perf_evsel__is_group_leader(evsel) &&
+ symbol_conf.show_freq_perf)
set_he_freq_perf(rep->session, iter);
if (!ui__has_annotation())
@@ -772,6 +773,8 @@ 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-perf", &symbol_conf.show_freq_perf,
+ "show CPU freqency and performance info"),
OPT_CALLBACK(0, "percent-limit", &report, "percent",
"Don't show entries under that percent", parse_percent_limit),
OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
@@ -788,7 +791,9 @@ 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();
+ perf_freq_t freq_data_status = { 0 };
if (ret < 0)
return ret;
@@ -873,6 +878,21 @@ repeat:
symbol_conf.cumulate_callchain = false;
}
+
+ if (symbol_conf.show_freq_perf) {
+ symbol_conf.freq_perf_type = 0;
+ evlist__for_each(session->evlist, pos) {
+ perf_freq__init(session->header.env.msr_pmu_type,
+ pos, freq_data_status, 1);
+ }
+ if (perf_freq__has_freq(freq_data_status))
+ symbol_conf.freq_perf_type |= 1U << DISPLAY_FREQ;
+ if (perf_freq__has_cpu_util(freq_data_status))
+ symbol_conf.freq_perf_type |= 1U << DISPLAY_CPU_UTIL;
+ if (perf_freq__has_core_busy(freq_data_status))
+ symbol_conf.freq_perf_type |= 1U << DISPLAY_CORE_BUSY;
+ }
+
if (setup_sorting() < 0) {
if (sort_order)
parse_options_usage(report_usage, options, "s", 1);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 25d6083..c2be455 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,16 @@ 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 (((fmt == &perf_hpp__format[PERF_HPP__FREQ]) ||
+ (fmt == &perf_hpp__format[PERF_HPP__CPU_UTIL]) ||
+ (fmt == &perf_hpp__format[PERF_HPP__CORE_BUSY])))
+ 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 +126,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 +240,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_perf)
+ 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 +393,9 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period)
HPP_RAW_FNS(samples, nr_events)
HPP_RAW_FNS(period, period)
+HPP_RAW_FNS(freq, freq)
+HPP_RAW_FNS(cpu_util, cpu_util)
+HPP_RAW_FNS(core_busy, core_busy)
static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
struct hist_entry *a __maybe_unused,
@@ -395,6 +428,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 +458,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("FREQ MHz", freq),
+ HPP__SINGLE_PRINT_FNS("CPU%", cpu_util),
+ HPP__SINGLE_PRINT_FNS("CORE_BUSY%", core_busy)
};
LIST_HEAD(perf_hpp__list);
@@ -485,6 +532,15 @@ void perf_hpp__init(void)
if (symbol_conf.show_total_period)
perf_hpp__column_enable(PERF_HPP__PERIOD);
+ if (symbol_conf.show_freq_perf) {
+ if (symbol_conf.freq_perf_type & (1U << DISPLAY_FREQ))
+ perf_hpp__column_enable(PERF_HPP__FREQ);
+ if (symbol_conf.freq_perf_type & (1U << DISPLAY_CPU_UTIL))
+ perf_hpp__column_enable(PERF_HPP__CPU_UTIL);
+ if (symbol_conf.freq_perf_type & (1U << DISPLAY_CORE_BUSY))
+ perf_hpp__column_enable(PERF_HPP__CORE_BUSY);
+ }
+
/* prepend overhead field for backward compatiblity. */
list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
if (list_empty(list))
@@ -652,6 +708,9 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
return;
switch (idx) {
+ case PERF_HPP__CPU_UTIL:
+ fmt->len = 5;
+ break;
case PERF_HPP__OVERHEAD:
case PERF_HPP__OVERHEAD_SYS:
case PERF_HPP__OVERHEAD_US:
@@ -661,6 +720,8 @@ 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__FREQ:
+ case PERF_HPP__CORE_BUSY:
fmt->len = 9;
break;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index de6d58e..df07f28 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__FREQ,
+ PERF_HPP__CPU_UTIL,
+ PERF_HPP__CORE_BUSY,
PERF_HPP__MAX_INDEX
};
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ba763f7..071fe65 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -908,26 +908,29 @@ static void sample_read__printf(struct perf_sample *sample,
printf("..... id %016" PRIx64
", value %016" PRIx64 "\n",
value->id, value->value);
-
- sid = perf_evlist__id2sid(evlist, value->id);
- evsel = sid->evsel;
- if (evsel != NULL)
- perf_freq__init(evlist->env->msr_pmu_type,
- evsel, data, value->value);
+ if (symbol_conf.show_freq_perf) {
+ sid = perf_evlist__id2sid(evlist, value->id);
+ evsel = sid->evsel;
+ if (evsel != NULL)
+ perf_freq__init(evlist->env->msr_pmu_type,
+ evsel, data, value->value);
+ }
}
} else
printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
sample->read.one.id, sample->read.one.value);
- if (perf_freq__has_freq(data))
- printf("..... Freq %lu MHz\n",
- perf_freq__get_freq(data, cpu_max_freq/1000));
- if (perf_freq__has_cpu_util(data))
- printf("..... CPU%% %lu%%\n",
- perf_freq__get_cpu_util(data));
- if (perf_freq__has_core_busy(data))
- printf("..... CORE_BUSY%% %lu%%\n",
- perf_freq__get_core_busy(data));
+ if (symbol_conf.show_freq_perf) {
+ if (perf_freq__has_freq(data))
+ printf("..... Freq %lu MHz\n",
+ perf_freq__get_freq(data, cpu_max_freq/1000));
+ if (perf_freq__has_cpu_util(data))
+ printf("..... CPU%% %lu%%\n",
+ perf_freq__get_cpu_util(data));
+ if (perf_freq__has_core_busy(data))
+ printf("..... CORE_BUSY%% %lu%%\n",
+ perf_freq__get_core_busy(data));
+ }
}
static void dump_event(struct perf_evlist *evlist, union perf_event *event,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index a97bcee..1d5c7d8 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1303,6 +1303,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__FREQ, "freq"),
+ DIM(PERF_HPP__CPU_UTIL, "cpu_u"),
+ DIM(PERF_HPP__CORE_BUSY, "core_busy"),
};
#undef DIM
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 440ba8a..8b21fb4 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -80,6 +80,14 @@ static inline size_t symbol__size(const struct symbol *sym)
struct strlist;
struct intlist;
+enum freq_perf_type_index {
+ DISPLAY_FREQ = 0,
+ DISPLAY_CPU_UTIL,
+ DISPLAY_CORE_BUSY,
+
+ DISPLAY_MAX
+};
+
struct symbol_conf {
unsigned short priv_size;
unsigned short nr_events;
@@ -107,7 +115,8 @@ struct symbol_conf {
show_hist_headers,
branch_callstack,
has_filter,
- show_ref_callgraph;
+ show_ref_callgraph,
+ show_freq_perf;
const char *vmlinux_name,
*kallsyms_name,
*source_prefix,
@@ -132,6 +141,7 @@ struct symbol_conf {
struct intlist *pid_list,
*tid_list;
const char *symfs;
+ u64 freq_perf_type;
};
extern struct symbol_conf symbol_conf;
--
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/
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2015-09-07 13:20 +0200 |
| Subject | Re: [PATCH V8 7/7] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report --stdio |
| Message-ID | <q62CS-3We-19@gated-at.bofh.it> |
| In reply to | #1218544 |
On Thu, Sep 03, 2015 at 08:31:03AM -0400, kan.liang@intel.com wrote:
> From: Kan Liang <kan.liang@intel.com>
>
> Show frequency, CPU Utilization and percent performance for each symbol
> in perf report by --stdio --show-freq-perf
>
> 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-perf
Ithink the --show-freq-perf option should imply --group, so user would type:
perf record --freq-perf
perf report --show-freq-perf
I wonder we should use --freq-perf for report as well 'perf report --freq-perf'
jirka
>
> Overhead FREQ MHz CPU% CORE_BUSY%
> Command Shared Object Symbol
> ........................................ ......... ..... ..........
> ........... ................ ......................
>
> 99.54% 99.54% 99.53% 99.53% 99.53% 2301 96 99
> tchain_edit tchain_edit [.] f3
> 0.20% 0.20% 0.20% 0.20% 0.20% 2301 98 99
> tchain_edit tchain_edit [.] f2
> 0.05% 0.05% 0.05% 0.05% 0.05% 2300 98 99
> tchain_edit [kernel.vmlinux] [k] read_tsc
>
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> ---
> tools/perf/Documentation/perf-report.txt | 12 ++++++
> tools/perf/builtin-report.c | 22 +++++++++-
> tools/perf/ui/hist.c | 71 +++++++++++++++++++++++++++++---
> tools/perf/util/hist.h | 3 ++
> tools/perf/util/session.c | 33 ++++++++-------
> tools/perf/util/sort.c | 3 ++
> tools/perf/util/symbol.h | 12 +++++-
> 7 files changed, 134 insertions(+), 22 deletions(-)
>
> diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
> index 9c7981b..6280e22 100644
> --- a/tools/perf/Documentation/perf-report.txt
> +++ b/tools/perf/Documentation/perf-report.txt
> @@ -306,6 +306,18 @@ OPTIONS
> special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
> 'perf mem' for simpler access.
>
> +--show-freq-perf::
> + Show CPU frequency and performance result from sample read.
> + To generate the frequency and performance output, the perf.data file
> + must have been obtained by group read and using special events cycles,
> + ref-cycles, msr/tsc/, msr/aperf/ or msr/mperf/
> + Freq MHz: The frequency during the sample interval. Needs cycles and
> + ref-cycles event.
> + CPU%: CPU utilization during the sample interval. Needs ref-cycles and
> + msr/tsc/ events.
> + CORE_BUSY%: actual percent performance (APERF/MPERF%) during the
> + sample interval. Needs msr/aperf/ and msr/mperf/ events.
> +
> --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 7673f1c..ebcbe4c 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -133,7 +133,8 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
> struct branch_info *bi;
>
> if ((iter->ops == &hist_iter_normal) &&
> - perf_evsel__is_group_leader(evsel))
> + perf_evsel__is_group_leader(evsel) &&
> + symbol_conf.show_freq_perf)
> set_he_freq_perf(rep->session, iter);
>
> if (!ui__has_annotation())
> @@ -772,6 +773,8 @@ 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-perf", &symbol_conf.show_freq_perf,
> + "show CPU freqency and performance info"),
> OPT_CALLBACK(0, "percent-limit", &report, "percent",
> "Don't show entries under that percent", parse_percent_limit),
> OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
> @@ -788,7 +791,9 @@ 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();
> + perf_freq_t freq_data_status = { 0 };
>
> if (ret < 0)
> return ret;
> @@ -873,6 +878,21 @@ repeat:
> symbol_conf.cumulate_callchain = false;
> }
>
> +
> + if (symbol_conf.show_freq_perf) {
> + symbol_conf.freq_perf_type = 0;
> + evlist__for_each(session->evlist, pos) {
> + perf_freq__init(session->header.env.msr_pmu_type,
> + pos, freq_data_status, 1);
> + }
> + if (perf_freq__has_freq(freq_data_status))
> + symbol_conf.freq_perf_type |= 1U << DISPLAY_FREQ;
> + if (perf_freq__has_cpu_util(freq_data_status))
> + symbol_conf.freq_perf_type |= 1U << DISPLAY_CPU_UTIL;
> + if (perf_freq__has_core_busy(freq_data_status))
> + symbol_conf.freq_perf_type |= 1U << DISPLAY_CORE_BUSY;
> + }
> +
> if (setup_sorting() < 0) {
> if (sort_order)
> parse_options_usage(report_usage, options, "s", 1);
> diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
> index 25d6083..c2be455 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,16 @@ 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 (((fmt == &perf_hpp__format[PERF_HPP__FREQ]) ||
> + (fmt == &perf_hpp__format[PERF_HPP__CPU_UTIL]) ||
> + (fmt == &perf_hpp__format[PERF_HPP__CORE_BUSY])))
> + 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 +126,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 +240,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_perf)
> + 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 +393,9 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period)
>
> HPP_RAW_FNS(samples, nr_events)
> HPP_RAW_FNS(period, period)
> +HPP_RAW_FNS(freq, freq)
> +HPP_RAW_FNS(cpu_util, cpu_util)
> +HPP_RAW_FNS(core_busy, core_busy)
>
> static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
> struct hist_entry *a __maybe_unused,
> @@ -395,6 +428,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 +458,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("FREQ MHz", freq),
> + HPP__SINGLE_PRINT_FNS("CPU%", cpu_util),
> + HPP__SINGLE_PRINT_FNS("CORE_BUSY%", core_busy)
> };
>
> LIST_HEAD(perf_hpp__list);
> @@ -485,6 +532,15 @@ void perf_hpp__init(void)
> if (symbol_conf.show_total_period)
> perf_hpp__column_enable(PERF_HPP__PERIOD);
>
> + if (symbol_conf.show_freq_perf) {
> + if (symbol_conf.freq_perf_type & (1U << DISPLAY_FREQ))
> + perf_hpp__column_enable(PERF_HPP__FREQ);
> + if (symbol_conf.freq_perf_type & (1U << DISPLAY_CPU_UTIL))
> + perf_hpp__column_enable(PERF_HPP__CPU_UTIL);
> + if (symbol_conf.freq_perf_type & (1U << DISPLAY_CORE_BUSY))
> + perf_hpp__column_enable(PERF_HPP__CORE_BUSY);
> + }
> +
> /* prepend overhead field for backward compatiblity. */
> list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
> if (list_empty(list))
> @@ -652,6 +708,9 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
> return;
>
> switch (idx) {
> + case PERF_HPP__CPU_UTIL:
> + fmt->len = 5;
> + break;
> case PERF_HPP__OVERHEAD:
> case PERF_HPP__OVERHEAD_SYS:
> case PERF_HPP__OVERHEAD_US:
> @@ -661,6 +720,8 @@ 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__FREQ:
> + case PERF_HPP__CORE_BUSY:
> fmt->len = 9;
> break;
>
> diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
> index de6d58e..df07f28 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__FREQ,
> + PERF_HPP__CPU_UTIL,
> + PERF_HPP__CORE_BUSY,
>
> PERF_HPP__MAX_INDEX
> };
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index ba763f7..071fe65 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -908,26 +908,29 @@ static void sample_read__printf(struct perf_sample *sample,
> printf("..... id %016" PRIx64
> ", value %016" PRIx64 "\n",
> value->id, value->value);
> -
> - sid = perf_evlist__id2sid(evlist, value->id);
> - evsel = sid->evsel;
> - if (evsel != NULL)
> - perf_freq__init(evlist->env->msr_pmu_type,
> - evsel, data, value->value);
> + if (symbol_conf.show_freq_perf) {
> + sid = perf_evlist__id2sid(evlist, value->id);
> + evsel = sid->evsel;
> + if (evsel != NULL)
> + perf_freq__init(evlist->env->msr_pmu_type,
> + evsel, data, value->value);
> + }
> }
> } else
> printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
> sample->read.one.id, sample->read.one.value);
>
> - if (perf_freq__has_freq(data))
> - printf("..... Freq %lu MHz\n",
> - perf_freq__get_freq(data, cpu_max_freq/1000));
> - if (perf_freq__has_cpu_util(data))
> - printf("..... CPU%% %lu%%\n",
> - perf_freq__get_cpu_util(data));
> - if (perf_freq__has_core_busy(data))
> - printf("..... CORE_BUSY%% %lu%%\n",
> - perf_freq__get_core_busy(data));
> + if (symbol_conf.show_freq_perf) {
> + if (perf_freq__has_freq(data))
> + printf("..... Freq %lu MHz\n",
> + perf_freq__get_freq(data, cpu_max_freq/1000));
> + if (perf_freq__has_cpu_util(data))
> + printf("..... CPU%% %lu%%\n",
> + perf_freq__get_cpu_util(data));
> + if (perf_freq__has_core_busy(data))
> + printf("..... CORE_BUSY%% %lu%%\n",
> + perf_freq__get_core_busy(data));
> + }
> }
>
> static void dump_event(struct perf_evlist *evlist, union perf_event *event,
> diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> index a97bcee..1d5c7d8 100644
> --- a/tools/perf/util/sort.c
> +++ b/tools/perf/util/sort.c
> @@ -1303,6 +1303,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__FREQ, "freq"),
> + DIM(PERF_HPP__CPU_UTIL, "cpu_u"),
> + DIM(PERF_HPP__CORE_BUSY, "core_busy"),
> };
>
> #undef DIM
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index 440ba8a..8b21fb4 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -80,6 +80,14 @@ static inline size_t symbol__size(const struct symbol *sym)
> struct strlist;
> struct intlist;
>
> +enum freq_perf_type_index {
> + DISPLAY_FREQ = 0,
> + DISPLAY_CPU_UTIL,
> + DISPLAY_CORE_BUSY,
> +
> + DISPLAY_MAX
> +};
> +
> struct symbol_conf {
> unsigned short priv_size;
> unsigned short nr_events;
> @@ -107,7 +115,8 @@ struct symbol_conf {
> show_hist_headers,
> branch_callstack,
> has_filter,
> - show_ref_callgraph;
> + show_ref_callgraph,
> + show_freq_perf;
> const char *vmlinux_name,
> *kallsyms_name,
> *source_prefix,
> @@ -132,6 +141,7 @@ struct symbol_conf {
> struct intlist *pid_list,
> *tid_list;
> const char *symfs;
> + u64 freq_perf_type;
> };
>
> extern struct symbol_conf symbol_conf;
> --
> 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/
[toc] | [prev] | [next] | [standalone]
| From | kan.liang@intel.com |
|---|---|
| Date | 2015-09-03 21:50 +0200 |
| Subject | [PATCH V8 4/7] perf,tools: fix dump_sample crash when evsel is NULL. |
| Message-ID | <q4IGf-4OA-27@gated-at.bofh.it> |
| In reply to | #1218543 |
From: Kan Liang <kan.liang@intel.com>
Need to check evsel before using in dump_sample.
Signed-off-by: Kan Liang <kan.liang@intel.com>
---
tools/perf/util/session.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 61669be..23fed17 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1080,11 +1080,11 @@ static int machines__deliver_event(struct machines *machines,
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
- dump_sample(evsel, event, sample);
if (evsel == NULL) {
++evlist->stats.nr_unknown_id;
return 0;
}
+ dump_sample(evsel, event, sample);
if (machine == NULL) {
++evlist->stats.nr_unprocessable_samples;
return 0;
--
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/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Kan Liang <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-08 16:40 +0200 |
| Subject | [tip:perf/core] perf session: Don't call dump_sample() when evsel is NULL |
| Message-ID | <q6sdZ-71F-49@gated-at.bofh.it> |
| In reply to | #1218545 |
Commit-ID: 1b29ac59b1d692c06ec543a5f35e0d9ebb98e003
Gitweb: http://git.kernel.org/tip/1b29ac59b1d692c06ec543a5f35e0d9ebb98e003
Author: Kan Liang <kan.liang@intel.com>
AuthorDate: Thu, 3 Sep 2015 08:31:00 -0400
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 4 Sep 2015 12:01:04 -0300
perf session: Don't call dump_sample() when evsel is NULL
Need to check evsel before passing it to dump_sample().
Signed-off-by: Kan Liang <kan.liang@intel.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1441283463-51050-5-git-send-email-kan.liang@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/session.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 61669be..23fed17 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1080,11 +1080,11 @@ static int machines__deliver_event(struct machines *machines,
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
- dump_sample(evsel, event, sample);
if (evsel == NULL) {
++evlist->stats.nr_unknown_id;
return 0;
}
+ dump_sample(evsel, event, sample);
if (machine == NULL) {
++evlist->stats.nr_unprocessable_samples;
return 0;
--
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/
[toc] | [prev] | [next] | [standalone]
| From | kan.liang@intel.com |
|---|---|
| Date | 2015-09-03 21:50 +0200 |
| Subject | [PATCH V8 2/7] perf,tools: read msr pmu type from header. |
| Message-ID | <q4IGf-4OA-31@gated-at.bofh.it> |
| In reply to | #1218543 |
From: Kan Liang <kan.liang@intel.com>
Get msr pmu type when processing pmu_mappings
Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/header.c | 3 +++
tools/perf/util/header.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3535dcb..04f415d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1879,6 +1879,9 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
/* include a NULL character at the end */
strbuf_add(&sb, "", 1);
+ if (!strcmp(name, "msr"))
+ ph->env.msr_pmu_type = type;
+
free(name);
pmu_num--;
}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index dd9f6b0..d9034e8 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -107,6 +107,7 @@ struct perf_env {
u64 max_freq;
} cpuattr;
};
+ unsigned int msr_pmu_type;
};
struct perf_header {
--
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/
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2015-09-07 13:40 +0200 |
| Message-ID | <q62We-4iH-25@gated-at.bofh.it> |
| In reply to | #1218543 |
On Thu, Sep 03, 2015 at 08:30:56AM -0400, kan.liang@intel.com wrote: > From: Kan Liang <kan.liang@intel.com> > > This patch set supports per-sample freq/CPU%/CORE_BUSY% print in perf > report -D and --stdio. > For printing these information, the perf.data file must have been obtained > by group read and using special events cycles, ref-cycles, msr/tsc/, > msr/aperf/ or msr/mperf/. > > - Freq (MHz): The frequency during the sample interval. Needs cycles > ref-cycles event. > - CPU%: CPU utilization during the sample interval. Needs ref-cycles and > msr/tsc/ events. > - CORE_BUSY%: actual percent performance (APERF/MPERF%) during the > sample interval. Needs msr/aperf/ and msr/mperf/ events. > > Here is an example: other than my latest 2 comments, I'm ok with the patchset jirka -- 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/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web