* [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support
@ 2015-09-16 14:21 kan.liang
2015-09-16 14:21 ` [PATCH V10 1/8] perf,tools: introduce generic FEAT for CPU attributes kan.liang
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
This patch set supports per-sample freq/CPU%/CORE_BUSY% print in perf
report.
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 --perf-freq ~/tchain_edit
$ perf report --stdio --perf-freq
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
Changes since V8:
- Rename --show-freq-perf to --freq-perf
- --freq-perf option imply --group
Changes since V9:
- Rebase on commit d71b0ad8d309
- Error handling for CPU attributes header write and process
- Rewrite the description for --perf-freq in perf record
- Add perf_freq_t in perf_sample to store frequency and performance data.
- rename --freq-perf to --perf-freq
- The last patch is split into three patches (6/8 only show leader value in hpp__fmt,
7/8 HPP__SINGLE_PRINT_FNS support and 8/8 perf report --perf-freq support)
Kan Liang (8):
perf,tools: introduce generic FEAT for CPU attributes
perf,record: introduce --perf-freq option
perf,tools: caculate freq per sample
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: only show leader's value in hpp__fmt
perf,tools: Introduce HPP__SINGLE_PRINT_FNS support
perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --perf-freq
tools/perf/Documentation/perf-record.txt | 8 ++++
tools/perf/Documentation/perf-report.txt | 12 ++++++
tools/perf/builtin-record.c | 39 ++++++++++++++++++-
tools/perf/builtin-report.c | 41 ++++++++++++++++++++
tools/perf/ui/hist.c | 66 +++++++++++++++++++++++++++++---
tools/perf/util/env.h | 11 ++++++
tools/perf/util/event.h | 13 +++++++
tools/perf/util/header.c | 62 ++++++++++++++++++++++++++++++
tools/perf/util/header.h | 1 +
tools/perf/util/hist.h | 3 ++
tools/perf/util/session.c | 44 +++++++++++++++++++--
tools/perf/util/session.h | 52 +++++++++++++++++++++++++
tools/perf/util/sort.c | 3 ++
tools/perf/util/sort.h | 3 ++
tools/perf/util/symbol.h | 12 +++++-
15 files changed, 360 insertions(+), 10 deletions(-)
--
1.8.3.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH V10 1/8] perf,tools: introduce generic FEAT for CPU attributes
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 2/8] perf, record: introduce --perf-freq option kan.liang
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
This patch introduces generic FEAT for CPU attributes. For the patch
set, we only need cpu max frequency. But it can be easily extented to
support more other CPU attributes.
Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/env.h | 11 +++++++++
| 62 ++++++++++++++++++++++++++++++++++++++++++++++++
| 1 +
3 files changed, 74 insertions(+)
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 0132b95..0eee628 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -6,6 +6,11 @@ struct cpu_topology_map {
int core_id;
};
+enum perf_header_cpu_attr {
+ PERF_HEADER_CPU_MAX_FREQ = 0,
+ PERF_HEADER_CPU_ATTR_MAX,
+};
+
struct perf_env {
char *hostname;
char *os_release;
@@ -31,6 +36,12 @@ struct perf_env {
char *numa_nodes;
char *pmu_mappings;
struct cpu_topology_map *cpu;
+ union {
+ unsigned long long cpu_attr[PERF_HEADER_CPU_ATTR_MAX];
+ struct {
+ unsigned long long max_freq;
+ } cpuattr;
+ };
};
extern struct perf_env perf_env;
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4383800..e4326f3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <sys/utsname.h>
+#include <api/cpu.h>
#include "evlist.h"
#include "evsel.h"
@@ -847,6 +848,25 @@ write_it:
return do_write_string(fd, buffer);
}
+static int write_cpu_attributes(int fd, struct perf_header *h __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused)
+{
+ u32 tag_id;
+ unsigned long long max_freq;
+ int ret;
+
+ tag_id = PERF_HEADER_CPU_MAX_FREQ;
+ ret = do_write(fd, &tag_id, sizeof(tag_id));
+ if (ret < 0)
+ return ret;
+
+ ret = cpu__get_max_freq(&max_freq);
+ if (ret < 0)
+ return ret;
+
+ return do_write(fd, &max_freq, sizeof(max_freq));
+}
+
static int write_branch_stack(int fd __maybe_unused,
struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
@@ -1147,6 +1167,11 @@ static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
fprintf(fp, "# cpuid : %s\n", ph->env.cpuid);
}
+static void print_cpu_attributes(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
+{
+ fprintf(fp, "# CPU attributes: max frequency = %llu KHz\n", ph->env.cpuattr.max_freq);
+}
+
static void print_branch_stack(struct perf_header *ph __maybe_unused,
int fd __maybe_unused, FILE *fp)
{
@@ -1460,6 +1485,42 @@ static int process_cpuid(struct perf_file_section *section __maybe_unused,
return ph->env.cpuid ? 0 : -ENOMEM;
}
+static int process_cpu_attributes(struct perf_file_section *section __maybe_unused,
+ struct perf_header *ph, int fd,
+ void *data __maybe_unused)
+{
+ ssize_t ret;
+ u32 i, tag_id;
+ u64 nr;
+
+ for (i = 0; i < PERF_HEADER_CPU_ATTR_MAX; i++) {
+
+ ret = readn(fd, &tag_id, sizeof(tag_id));
+ if (ret != sizeof(tag_id))
+ return (ret < 0) ? errno : -1;
+
+ if (ph->needs_swap)
+ nr = bswap_32(tag_id);
+
+ if (tag_id >= PERF_HEADER_CPU_ATTR_MAX) {
+ pr_debug("The number of cpu attributes is not expected. "
+ "You may need to upgrade the perf tool.\n");
+ return -EINVAL;
+ }
+
+ ret = readn(fd, &nr, sizeof(nr));
+ if (ret != sizeof(nr))
+ return (ret < 0) ? errno : -1;
+
+ if (ph->needs_swap)
+ nr = bswap_64(nr);
+
+ ph->env.cpu_attr[tag_id] = nr;
+ }
+
+ return 0;
+}
+
static int process_total_mem(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int fd,
void *data __maybe_unused)
@@ -1948,6 +2009,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
FEAT_OPP(HEADER_GROUP_DESC, group_desc),
FEAT_OPP(HEADER_AUXTRACE, auxtrace),
+ FEAT_OPP(HEADER_CPU_ATTR, cpu_attributes),
};
struct header_print_data {
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 05f27cb..09e6e1f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,7 @@ enum {
HEADER_PMU_MAPPINGS,
HEADER_GROUP_DESC,
HEADER_AUXTRACE,
+ HEADER_CPU_ATTR,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 2/8] perf, record: introduce --perf-freq option
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
2015-09-16 14:21 ` [PATCH V10 1/8] perf,tools: introduce generic FEAT for CPU attributes kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 3/8] perf,tools: caculate freq per sample kan.liang
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
To generate the frequency and performance output, perf must sample read
special events like cycles, ref-cycles, msr/tsc/, msr/aperf/ or
msr/mperf/.
With the --perf-freq option, perf record can automatically check and add
those event into evlist as group for sampling read.
Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/Documentation/perf-record.txt | 8 +++++++
tools/perf/builtin-record.c | 39 +++++++++++++++++++++++++++++++-
tools/perf/util/event.h | 10 ++++++++
3 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2e9ce77..8a65f37 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -308,6 +308,14 @@ This option sets the time out limit. The default value is 500 ms.
Record context switch events i.e. events of type PERF_RECORD_SWITCH or
PERF_RECORD_SWITCH_CPU_WIDE.
+--perf-freq::
+Collect CPU frequency and performance result per sample. It includes frequency,
+CPU utilization and actual percent performance (APERF/MPERF%).
+To generate the frequency and performance output, special events cycles,
+ref-cycles, msr/tsc/, msr/aperf/ or msr/mperf/ must be read by group.
+This option can automatically probe available special events on system, and
+read their sample value by group.
+
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 142eeb3..8c4da18 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -13,7 +13,7 @@
#include "util/util.h"
#include "util/parse-options.h"
#include "util/parse-events.h"
-
+#include "util/pmu.h"
#include "util/callchain.h"
#include "util/cgroup.h"
#include "util/header.h"
@@ -50,6 +50,7 @@ struct record {
bool no_buildid;
bool no_buildid_cache;
long samples;
+ bool perf_freq;
};
static int record__write(struct record *rec, void *bf, size_t size)
@@ -948,6 +949,35 @@ out_free:
return ret;
}
+const char *perf_freq_events[PERF_FREQ_MAX][3] = {
+ { "msr", "tsc", "msr/tsc/" },
+ { "msr", "aperf", "msr/aperf/" },
+ { "msr", "mperf", "msr/mperf/" },
+ { NULL, "cycles", "cycles" },
+ { NULL, "ref-cycles", "ref-cycles" },
+};
+
+static int
+record_add_perf_freq_events(struct perf_evlist *evlist)
+{
+ int i;
+ char perf_freq_attrs[100];
+
+ strcpy(perf_freq_attrs, "{cycles,ref-cycles");
+ for (i = 0; i < PERF_FREQ_MAX; i++) {
+ if ((i == PERF_FREQ_CYCLES) ||
+ (i == PERF_FREQ_REF_CYCLES))
+ continue;
+ if (pmu_have_event(perf_freq_events[i][0], perf_freq_events[i][1])) {
+ strcat(perf_freq_attrs, ",");
+ strcat(perf_freq_attrs, perf_freq_events[i][2]);
+ }
+ }
+ strcat(perf_freq_attrs, "}:S");
+
+ return parse_events(evlist, perf_freq_attrs, NULL);
+}
+
static const char * const __record_usage[] = {
"perf record [<options>] [<command>]",
"perf record [<options>] -- <command> [<options>]",
@@ -1096,6 +1126,8 @@ struct option __record_options[] = {
"per thread proc mmap processing timeout in ms"),
OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
"Record context switch events"),
+ OPT_BOOLEAN(0, "perf-freq", &record.perf_freq,
+ "Collect CPU frequency and performance result per sample"),
OPT_END()
};
@@ -1157,6 +1189,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
if (rec->no_buildid_cache || rec->no_buildid)
disable_buildid_cache();
+ if (rec->perf_freq && record_add_perf_freq_events(rec->evlist)) {
+ pr_err("Cannot set up freq and performance events\n");
+ goto out_symbol_exit;
+ }
+
if (rec->evlist->nr_entries == 0 &&
perf_evlist__add_default(rec->evlist) < 0) {
pr_err("Not enough memory for event selector list\n");
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index f729df5..3439462 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -177,6 +177,16 @@ enum {
PERF_IP_FLAG_TRACE_BEGIN |\
PERF_IP_FLAG_TRACE_END)
+enum perf_freqs {
+ PERF_FREQ_TSC = 0,
+ PERF_FREQ_APERF = 1,
+ PERF_FREQ_MPERF = 2,
+ PERF_FREQ_CYCLES = 3,
+ PERF_FREQ_REF_CYCLES = 4,
+
+ PERF_FREQ_MAX
+};
+
struct perf_sample {
u64 ip;
u32 pid, tid;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 3/8] perf,tools: caculate freq per sample
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
2015-09-16 14:21 ` [PATCH V10 1/8] perf,tools: introduce generic FEAT for CPU attributes kan.liang
2015-09-16 14:21 ` [PATCH V10 2/8] perf, record: introduce --perf-freq option kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 4/8] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
This patch store the vaule for calculating frequency, CPU Utilization
and percent performance in struct perf_sample, when sample group read
is detected and dump_trace is enabled.
Signed-off-by: Kan Liang <kan.liang@intel.com>
---
tools/perf/util/event.h | 3 +++
tools/perf/util/session.c | 26 +++++++++++++++++++++++++-
tools/perf/util/session.h | 25 +++++++++++++++++++++++++
3 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 3439462..edffeca 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -187,6 +187,8 @@ enum perf_freqs {
PERF_FREQ_MAX
};
+typedef u64 perf_freq_t[PERF_FREQ_MAX];
+
struct perf_sample {
u64 ip;
u32 pid, tid;
@@ -202,6 +204,7 @@ struct perf_sample {
u64 data_src;
u32 flags;
u16 insn_len;
+ perf_freq_t freq;
void *raw_data;
struct ip_callchain *callchain;
struct branch_stack *branch_stack;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d1a43a3..e8cb98d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -7,7 +7,6 @@
#include <sys/mman.h>
#include "evlist.h"
-#include "evsel.h"
#include "session.h"
#include "tool.h"
#include "sort.h"
@@ -1047,6 +1046,26 @@ static int
&sample->read.one, machine);
}
+static void perf_caculate_freq(struct perf_sample *sample,
+ struct perf_evsel *evsel)
+{
+ u64 i;
+ struct perf_evlist *evlist = evsel->evlist;
+ struct sample_read_value *value;
+ struct perf_sample_id *sid;
+ struct perf_evsel *event;
+
+ for (i = 0; i < sample->read.group.nr; i++) {
+
+ value = &sample->read.group.values[i];
+ sid = perf_evlist__id2sid(evlist, value->id);
+ event = sid->evsel;
+ if (event != NULL)
+ perf_freq__init(evlist->env->msr_pmu_type,
+ event, sample->freq, value->value);
+ }
+}
+
static int machines__deliver_event(struct machines *machines,
struct perf_evlist *evlist,
union perf_event *event,
@@ -1068,6 +1087,11 @@ static int machines__deliver_event(struct machines *machines,
++evlist->stats.nr_unknown_id;
return 0;
}
+ if (dump_trace &&
+ (evsel->attr.sample_type & PERF_SAMPLE_READ) &&
+ (evsel->attr.read_format & PERF_FORMAT_GROUP))
+ perf_caculate_freq(sample, evsel);
+
dump_sample(evsel, event, sample);
if (machine == NULL) {
++evlist->stats.nr_unprocessable_samples;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index b44afc7..f70d3a1 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -9,6 +9,7 @@
#include "thread.h"
#include "data.h"
#include "ordered-events.h"
+#include "evsel.h"
#include <linux/rbtree.h>
#include <linux/perf_event.h>
@@ -42,6 +43,30 @@ struct perf_session {
#define PRINT_IP_OPT_ONELINE (1<<4)
#define PRINT_IP_OPT_SRCLINE (1<<5)
+#define PERF_MSR_TSC 0
+#define PERF_MSR_APERF 1
+#define PERF_MSR_MPERF 2
+
+static inline void perf_freq__init(unsigned int msr_pmu_type,
+ struct perf_evsel *evsel,
+ perf_freq_t array,
+ u64 value)
+{
+ if (evsel->attr.type == msr_pmu_type) {
+ if (evsel->attr.config == PERF_MSR_TSC)
+ array[PERF_FREQ_TSC] = value;
+ if (evsel->attr.config == PERF_MSR_APERF)
+ array[PERF_FREQ_APERF] = value;
+ if (evsel->attr.config == PERF_MSR_MPERF)
+ array[PERF_FREQ_MPERF] = value;
+ }
+ if (evsel->attr.type == PERF_TYPE_HARDWARE) {
+ if (evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES)
+ array[PERF_FREQ_CYCLES] = value;
+ if (evsel->attr.config == PERF_COUNT_HW_REF_CPU_CYCLES)
+ array[PERF_FREQ_REF_CYCLES] = value;
+ }
+}
struct perf_tool;
struct perf_session *perf_session__new(struct perf_data_file *file,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 4/8] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
` (2 preceding siblings ...)
2015-09-16 14:21 ` [PATCH V10 3/8] perf,tools: caculate freq per sample kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 5/8] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
The value from cycles/ref-cycles/TSC/ASTATE/MSTATE event in perf_sample
can be used to calculate the frequency, CPU Utilization and percent
performance during each sampling period.
This patch shows them in report -D.
Here is an example:
$ perf record --perf-freq ~/tchain_edit
Here is one sample from perf report -D
1972044565107 0x3498 [0x88]: PERF_RECORD_SAMPLE(IP, 0x2): 10608/10608:
0x4005fd period: 564686 addr: 0
... sample_read:
.... group nr 5
..... id 0000000000000012, value 0000000002143901
..... id 0000000000000052, value 0000000002143896
..... id 0000000000000094, value 00000000021e443d
..... id 00000000000000d4, value 00000000021db984
..... id 0000000000000114, value 00000000021db964
..... Freq 2301 MHz
..... CPU% 98%
..... CORE_BUSY% 99%
Signed-off-by: Kan Liang <kan.liang@intel.com>
---
tools/perf/util/session.c | 18 ++++++++++++++++--
tools/perf/util/session.h | 27 +++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e8cb98d..6ba3a68 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -861,8 +861,12 @@ static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
printf("%" PRIu64 " ", sample->time);
}
-static void sample_read__printf(struct perf_sample *sample, u64 read_format)
+static void sample_read__printf(struct perf_sample *sample,
+ struct perf_evsel *evsel)
{
+ u64 read_format = evsel->attr.read_format;
+ u64 cpu_max_freq = evsel->evlist->env->cpuattr.max_freq;
+
printf("... sample_read:\n");
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
@@ -889,6 +893,16 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
} else
printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
sample->read.one.id, sample->read.one.value);
+
+ if (perf_freq__has_freq(sample->freq))
+ printf("..... Freq %lu MHz\n",
+ perf_freq__get_freq(sample->freq, cpu_max_freq/1000));
+ if (perf_freq__has_cpu_util(sample->freq))
+ printf("..... CPU%% %lu%%\n",
+ perf_freq__get_cpu_util(sample->freq));
+ if (perf_freq__has_core_busy(sample->freq))
+ printf("..... CORE_BUSY%% %lu%%\n",
+ perf_freq__get_core_busy(sample->freq));
}
static void dump_event(struct perf_evlist *evlist, union perf_event *event,
@@ -948,7 +962,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
printf("... transaction: %" PRIx64 "\n", sample->transaction);
if (sample_type & PERF_SAMPLE_READ)
- sample_read__printf(sample, evsel->attr.read_format);
+ sample_read__printf(sample, evsel);
}
static struct machine *machines__find_for_cpumode(struct machines *machines,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index f70d3a1..0ee3027 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -67,6 +67,33 @@ static inline void perf_freq__init(unsigned int msr_pmu_type,
array[PERF_FREQ_REF_CYCLES] = value;
}
}
+
+static inline bool perf_freq__has_freq(perf_freq_t array)
+{
+ return ((array[PERF_FREQ_CYCLES] > 0) && (array[PERF_FREQ_REF_CYCLES] > 0));
+}
+static inline u64 perf_freq__get_freq(perf_freq_t array, u64 cpu_max_freq)
+{
+ return ((array[PERF_FREQ_CYCLES] * cpu_max_freq) / array[PERF_FREQ_REF_CYCLES]);
+}
+static inline bool perf_freq__has_cpu_util(perf_freq_t array)
+{
+ return ((array[PERF_FREQ_TSC] > 0) && (array[PERF_FREQ_REF_CYCLES] > 0));
+}
+static inline u64 perf_freq__get_cpu_util(perf_freq_t array)
+{
+ return ((100 * array[PERF_FREQ_REF_CYCLES]) / array[PERF_FREQ_TSC]);
+}
+
+static inline bool perf_freq__has_core_busy(perf_freq_t array)
+{
+ return ((array[PERF_FREQ_APERF] > 0) && (array[PERF_FREQ_MPERF] > 0));
+}
+static inline u64 perf_freq__get_core_busy(perf_freq_t array)
+{
+ return ((100 * array[PERF_FREQ_APERF]) / array[PERF_FREQ_MPERF]);
+}
+
struct perf_tool;
struct perf_session *perf_session__new(struct perf_data_file *file,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 5/8] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
` (3 preceding siblings ...)
2015-09-16 14:21 ` [PATCH V10 4/8] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 6/8] perf,tools: only show leader's value in hpp__fmt kan.liang
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
Caculate freq/CPU%/CORE_BUSY% in add_entry_cb, and update the value in
he_stat.
Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/builtin-report.c | 20 ++++++++++++++++++++
tools/perf/util/sort.h | 3 +++
2 files changed, 23 insertions(+)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e4e3f14..e2a2fdd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -90,6 +90,21 @@ static int report__config(const char *var, const char *value, void *cb)
return perf_default_config(var, value, cb);
}
+static void set_he_perf_freq(struct perf_session *session,
+ struct hist_entry_iter *iter)
+{
+ struct hist_entry *he = iter->he;
+ struct perf_sample *sample = iter->sample;
+ u64 cpu_max_freq = session->header.env.cpuattr.max_freq;
+
+ if (perf_freq__has_freq(sample->freq))
+ he->stat.freq = perf_freq__get_freq(sample->freq, cpu_max_freq/1000);
+ if (perf_freq__has_cpu_util(sample->freq))
+ he->stat.cpu_util = perf_freq__get_cpu_util(sample->freq);
+ if (perf_freq__has_core_busy(sample->freq))
+ he->stat.core_busy = perf_freq__get_core_busy(sample->freq);
+}
+
static int hist_iter__report_callback(struct hist_entry_iter *iter,
struct addr_location *al, bool single,
void *arg)
@@ -101,6 +116,11 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
struct mem_info *mi;
struct branch_info *bi;
+ if (dump_trace &&
+ (iter->ops == &hist_iter_normal) &&
+ perf_evsel__is_group_leader(evsel))
+ set_he_perf_freq(rep->session, iter);
+
if (!ui__has_annotation())
return 0;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index c06b757..0ff2bdd 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -55,6 +55,9 @@ struct he_stat {
u64 period_guest_us;
u64 weight;
u32 nr_events;
+ u64 freq;
+ u64 cpu_util;
+ u64 core_busy;
};
struct hist_entry_diff {
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 6/8] perf,tools: only show leader's value in hpp__fmt
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
` (4 preceding siblings ...)
2015-09-16 14:21 ` [PATCH V10 5/8] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 7/8] perf,tools: Introduce HPP__SINGLE_PRINT_FNS support kan.liang
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
If group option is set, perf report shows the values from each events in
the same group one by one. However, sometimes only leader's value is
enough. For example, we only caculate and store the freq value for
leader.
Signed-off-by: Kan Liang <kan.liang@intel.com>
---
tools/perf/ui/hist.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 25d6083..c37aa6f 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 leader_only)
{
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) && !leader_only) {
int prev_idx, idx_delta;
struct hist_entry *pair;
int nr_members = evsel->nr_members;
@@ -109,10 +109,11 @@ 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 leader_only = false;
if (symbol_conf.field_sep) {
return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
- print_fn, fmt_percent);
+ print_fn, fmt_percent, leader_only);
}
if (fmt_percent)
@@ -120,7 +121,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, leader_only);
}
int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 7/8] perf,tools: Introduce HPP__SINGLE_PRINT_FNS support
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
` (5 preceding siblings ...)
2015-09-16 14:21 ` [PATCH V10 6/8] perf,tools: only show leader's value in hpp__fmt kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-16 14:21 ` [PATCH V10 8/8] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --perf-freq kan.liang
2015-09-28 20:05 ` [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support Liang, Kan
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
Normally, with group option set, all the events in the same group will
be print one by one. So the group header width is the sum of all events
width. However, for freqi/cpu%/CORE_BUSY% print, group events share the
same value. So only single event width is enough.
Signed-off-by: Kan Liang <kan.liang@intel.com>
---
tools/perf/ui/hist.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
tools/perf/util/hist.h | 3 +++
tools/perf/util/sort.c | 3 +++
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index c37aa6f..ba95ee2 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -235,6 +235,25 @@ 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 __maybe_unused)
+{
+ int len = fmt->user_len ?: 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;
@@ -364,6 +383,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,
@@ -407,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, \
+ }
+
struct perf_hpp_fmt perf_hpp__format[] = {
HPP__COLOR_PRINT_FNS("Overhead", overhead),
HPP__COLOR_PRINT_FNS("sys", overhead_sys),
@@ -415,7 +448,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);
@@ -653,6 +689,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:
@@ -662,6 +701,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 4d6aa1d..664b34d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -241,6 +241,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/sort.c b/tools/perf/util/sort.c
index 6b9556d..1647802 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1326,6 +1326,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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V10 8/8] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --perf-freq
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
` (6 preceding siblings ...)
2015-09-16 14:21 ` [PATCH V10 7/8] perf,tools: Introduce HPP__SINGLE_PRINT_FNS support kan.liang
@ 2015-09-16 14:21 ` kan.liang
2015-09-28 20:05 ` [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support Liang, Kan
8 siblings, 0 replies; 10+ messages in thread
From: kan.liang @ 2015-09-16 14:21 UTC (permalink / raw)
To: acme, jolsa
Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
adrian.hunter, namhyung, linux-kernel, Kan Liang
From: Kan Liang <kan.liang@intel.com>
Show frequency, CPU Utilization and percent performance for each symbol
in perf report by --perf-freq
In sampling group, only group leader do sampling. So only need to print
group leader's freq in --group.
--perf-freq option also implies --group.
Only save and caculate freq/CPU%/CORE_BUSY when --perf-freq option is
set (replace dump_trace)
Here is an example.
$ perf report --stdio --perf-freq
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 | 23 ++++++++++++++++++++++-
tools/perf/ui/hist.c | 14 ++++++++++++++
tools/perf/util/session.c | 2 +-
tools/perf/util/symbol.h | 12 +++++++++++-
5 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index b941d5e..671bac0 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -353,6 +353,18 @@ include::itrace.txt[]
--socket-filter::
Only report the samples on the processor socket that match with this filter
+--perf-freq::
+ 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/ (Use --perf-freq in record)
+ 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.
+
include::callchain-overhead-calculation.txt[]
SEE ALSO
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e2a2fdd..98abe6a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -116,7 +116,7 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
struct mem_info *mi;
struct branch_info *bi;
- if (dump_trace &&
+ if (symbol_conf.perf_freq &&
(iter->ops == &hist_iter_normal) &&
perf_evsel__is_group_leader(evsel))
set_he_perf_freq(rep->session, iter);
@@ -778,12 +778,16 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
"Show callgraph from reference event"),
OPT_INTEGER(0, "socket-filter", &report.socket_filter,
"only show processor socket that match with this filter"),
+ OPT_BOOLEAN(0, "perf-freq", &symbol_conf.perf_freq,
+ "show CPU freqency and performance info"),
OPT_END()
};
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;
@@ -868,6 +872,23 @@ repeat:
symbol_conf.cumulate_callchain = false;
}
+ if (symbol_conf.perf_freq) {
+ symbol_conf.perf_freq_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.perf_freq_type |= 1U << DISPLAY_FREQ;
+ if (perf_freq__has_cpu_util(freq_data_status))
+ symbol_conf.perf_freq_type |= 1U << DISPLAY_CPU_UTIL;
+ if (perf_freq__has_core_busy(freq_data_status))
+ symbol_conf.perf_freq_type |= 1U << DISPLAY_CORE_BUSY;
+
+ /* --perf-freq option imply --group */
+ symbol_conf.event_group = true;
+ }
+
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 ba95ee2..d9082df 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -111,6 +111,11 @@ int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
int len = fmt->user_len ?: fmt->len;
bool leader_only = 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])))
+ leader_only = true;
+
if (symbol_conf.field_sep) {
return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
print_fn, fmt_percent, leader_only);
@@ -522,6 +527,15 @@ void perf_hpp__init(void)
if (symbol_conf.show_total_period)
perf_hpp__column_enable(PERF_HPP__PERIOD);
+ if (symbol_conf.perf_freq) {
+ if (symbol_conf.perf_freq_type & (1U << DISPLAY_FREQ))
+ perf_hpp__column_enable(PERF_HPP__FREQ);
+ if (symbol_conf.perf_freq_type & (1U << DISPLAY_CPU_UTIL))
+ perf_hpp__column_enable(PERF_HPP__CPU_UTIL);
+ if (symbol_conf.perf_freq_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))
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6ba3a68..a2f06cf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1101,7 +1101,7 @@ static int machines__deliver_event(struct machines *machines,
++evlist->stats.nr_unknown_id;
return 0;
}
- if (dump_trace &&
+ if (symbol_conf.perf_freq &&
(evsel->attr.sample_type & PERF_SAMPLE_READ) &&
(evsel->attr.read_format & PERF_FORMAT_GROUP))
perf_caculate_freq(sample, evsel);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 40073c6..95bc239 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 perf_freq_display {
+ 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,
+ perf_freq;
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 perf_freq_type;
};
extern struct symbol_conf symbol_conf;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* RE: [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
` (7 preceding siblings ...)
2015-09-16 14:21 ` [PATCH V10 8/8] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --perf-freq kan.liang
@ 2015-09-28 20:05 ` Liang, Kan
8 siblings, 0 replies; 10+ messages in thread
From: Liang, Kan @ 2015-09-28 20:05 UTC (permalink / raw)
To: acme@kernel.org, jolsa@kernel.org
Cc: a.p.zijlstra@chello.nl, luto@kernel.org, mingo@redhat.com,
eranian@google.com, ak@linux.intel.com, mark.rutland@arm.com,
Hunter, Adrian, namhyung@kernel.org, linux-kernel@vger.kernel.org
Hi Arnaldo and Jirka,
Any comments for the V10 patch set?
Thanks,
Kan
>
> From: Kan Liang <kan.liang@intel.com>
>
> This patch set supports per-sample freq/CPU%/CORE_BUSY% print in perf
> report.
> 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 --perf-freq ~/tchain_edit
>
> $ perf report --stdio --perf-freq
>
> 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
>
> Changes since V8:
> - Rename --show-freq-perf to --freq-perf
> - --freq-perf option imply --group
>
> Changes since V9:
> - Rebase on commit d71b0ad8d309
> - Error handling for CPU attributes header write and process
> - Rewrite the description for --perf-freq in perf record
> - Add perf_freq_t in perf_sample to store frequency and performance
> data.
> - rename --freq-perf to --perf-freq
> - The last patch is split into three patches (6/8 only show leader value in
> hpp__fmt,
> 7/8 HPP__SINGLE_PRINT_FNS support and 8/8 perf report --perf-freq
> support)
>
> Kan Liang (8):
> perf,tools: introduce generic FEAT for CPU attributes
> perf,record: introduce --perf-freq option
> perf,tools: caculate freq per sample
> 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: only show leader's value in hpp__fmt
> perf,tools: Introduce HPP__SINGLE_PRINT_FNS support
> perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --perf-freq
>
> tools/perf/Documentation/perf-record.txt | 8 ++++
> tools/perf/Documentation/perf-report.txt | 12 ++++++
> tools/perf/builtin-record.c | 39 ++++++++++++++++++-
> tools/perf/builtin-report.c | 41 ++++++++++++++++++++
> tools/perf/ui/hist.c | 66 +++++++++++++++++++++++++++++---
> tools/perf/util/env.h | 11 ++++++
> tools/perf/util/event.h | 13 +++++++
> tools/perf/util/header.c | 62
> ++++++++++++++++++++++++++++++
> tools/perf/util/header.h | 1 +
> tools/perf/util/hist.h | 3 ++
> tools/perf/util/session.c | 44 +++++++++++++++++++--
> tools/perf/util/session.h | 52 +++++++++++++++++++++++++
> tools/perf/util/sort.c | 3 ++
> tools/perf/util/sort.h | 3 ++
> tools/perf/util/symbol.h | 12 +++++-
> 15 files changed, 360 insertions(+), 10 deletions(-)
>
> --
> 1.8.3.1
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-09-28 20:05 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-16 14:21 [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support kan.liang
2015-09-16 14:21 ` [PATCH V10 1/8] perf,tools: introduce generic FEAT for CPU attributes kan.liang
2015-09-16 14:21 ` [PATCH V10 2/8] perf, record: introduce --perf-freq option kan.liang
2015-09-16 14:21 ` [PATCH V10 3/8] perf,tools: caculate freq per sample kan.liang
2015-09-16 14:21 ` [PATCH V10 4/8] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
2015-09-16 14:21 ` [PATCH V10 5/8] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang
2015-09-16 14:21 ` [PATCH V10 6/8] perf,tools: only show leader's value in hpp__fmt kan.liang
2015-09-16 14:21 ` [PATCH V10 7/8] perf,tools: Introduce HPP__SINGLE_PRINT_FNS support kan.liang
2015-09-16 14:21 ` [PATCH V10 8/8] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --perf-freq kan.liang
2015-09-28 20:05 ` [PATCH V10 0/8] Freq/CPU%/CORE_BUSY% support Liang, Kan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox