Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1221195 > unrolled thread

[PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support

Started bykan.liang@intel.com
First post2015-09-09 04:50 +0200
Last post2015-09-09 16:40 +0200
Articles 13 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang@intel.com - 2015-09-09 04:50 +0200
    [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang@intel.com - 2015-09-09 04:50 +0200
      Re: [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY%  in report -D Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-10 16:30 +0200
    [PATCH V9 2/6] perf,tools: read msr pmu type from header. kan.liang@intel.com - 2015-09-09 04:50 +0200
      Re: [PATCH V9 2/6] perf,tools: read msr pmu type from header. Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-10 16:00 +0200
      Re: [PATCH V9 2/6] perf,tools: read msr pmu type from header. Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-14 23:20 +0200
    [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf kan.liang@intel.com - 2015-09-09 04:50 +0200
      Re: [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf  report by --freq-perf Jiri Olsa <jolsa@redhat.com> - 2015-09-09 16:40 +0200
    [PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang@intel.com - 2015-09-09 04:50 +0200
    [PATCH V9 3/6] perf, record: introduce --freq-perf option kan.liang@intel.com - 2015-09-09 04:50 +0200
      Re: [PATCH V9 3/6] perf, record: introduce --freq-perf option Jiri Olsa <jolsa@redhat.com> - 2015-09-09 16:40 +0200
      Re: [PATCH V9 3/6] perf, record: introduce --freq-perf option Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-14 23:20 +0200
    Re: [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support Jiri Olsa <jolsa@redhat.com> - 2015-09-09 16:40 +0200

#1221195 — [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support

Fromkan.liang@intel.com
Date2015-09-09 04:50 +0200
Subject[PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support
Message-ID<q6DCq-6DS-9@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.
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 --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

Changes since V8:
 - Rename --show-freq-perf to --freq-perf 
 - --freq-perf option imply --group

Kan Liang (6):
  perf,tools: introduce generic FEAT for CPU attributes
  perf,tools: read msr pmu type from header.
  perf, record: introduce --freq-perf option
  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 by --freq-perf

 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              | 59 ++++++++++++++++++++++++++
 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                | 31 ++++++++++++--
 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, 399 insertions(+), 10 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]


#1221196 — [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D

Fromkan.liang@intel.com
Date2015-09-09 04:50 +0200
Subject[PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
Message-ID<q6DCq-6DS-11@gated-at.bofh.it>
In reply to#1221195
From: Kan Liang <kan.liang@intel.com>

The group read results from cycles/ref-cycles/TSC/ASTATE/MSTATE event
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 --freq-perf  ~/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>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 28 +++++++++++++++++++++---
 tools/perf/util/session.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 23fed17..ba763f7 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"
@@ -878,8 +877,15 @@ 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;
+	struct perf_evlist *evlist = evsel->evlist;
+	struct perf_sample_id *sid;
+	perf_freq_t data = { 0 };
+	u64 cpu_max_freq = evlist->env->cpuattr.max_freq;
+
 	printf("... sample_read:\n");
 
 	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
@@ -902,10 +908,26 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
 			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);
 		}
 	} 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));
 }
 
 static void dump_event(struct perf_evlist *evlist, union perf_event *event,
@@ -965,7 +987,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 3915be7..83bf4a9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -11,6 +11,7 @@
 #include "ordered-events.h"
 #include <linux/rbtree.h>
 #include <linux/perf_event.h>
+#include "evsel.h"
 
 struct ip_callchain;
 struct thread;
@@ -42,6 +43,10 @@ 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
+
 enum perf_freq_perf_index {
 	FREQ_PERF_TSC		= 0,
 	FREQ_PERF_APERF		= 1,
@@ -52,6 +57,55 @@ enum perf_freq_perf_index {
 	FREQ_PERF_MAX
 };
 
+typedef u64 perf_freq_t[FREQ_PERF_MAX];
+
+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[FREQ_PERF_TSC] = value;
+		if (evsel->attr.config == PERF_MSR_APERF)
+			array[FREQ_PERF_APERF] = value;
+		if (evsel->attr.config == PERF_MSR_MPERF)
+			array[FREQ_PERF_MPERF] = value;
+	}
+	if (evsel->attr.type == PERF_TYPE_HARDWARE) {
+		if (evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES)
+			array[FREQ_PERF_CYCLES] = value;
+		if (evsel->attr.config == PERF_COUNT_HW_REF_CPU_CYCLES)
+			array[FREQ_PERF_REF_CYCLES] = value;
+	}
+}
+
+static inline bool perf_freq__has_freq(perf_freq_t array)
+{
+	return ((array[FREQ_PERF_CYCLES] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
+}
+static inline u64 perf_freq__get_freq(perf_freq_t array, u64 cpu_max_freq)
+{
+	return ((array[FREQ_PERF_CYCLES] * cpu_max_freq) / array[FREQ_PERF_REF_CYCLES]);
+}
+static inline bool perf_freq__has_cpu_util(perf_freq_t array)
+{
+	return ((array[FREQ_PERF_TSC] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
+}
+static inline u64 perf_freq__get_cpu_util(perf_freq_t array)
+{
+	return ((100 * array[FREQ_PERF_REF_CYCLES]) / array[FREQ_PERF_TSC]);
+}
+
+static inline bool perf_freq__has_core_busy(perf_freq_t array)
+{
+	return ((array[FREQ_PERF_APERF] > 0) && (array[FREQ_PERF_MPERF] > 0));
+}
+static inline u64 perf_freq__get_core_busy(perf_freq_t array)
+{
+	return ((100 * array[FREQ_PERF_APERF]) / array[FREQ_PERF_MPERF]);
+}
+
 struct perf_tool;
 
 struct perf_session *perf_session__new(struct perf_data_file *file,
-- 
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]


#1222235 — Re: [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-09-10 16:30 +0200
SubjectRe: [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
Message-ID<q7b1p-43t-33@gated-at.bofh.it>
In reply to#1221196
Em Tue, Sep 08, 2015 at 03:32:47PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> The group read results from cycles/ref-cycles/TSC/ASTATE/MSTATE event
> 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 --freq-perf  ~/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>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/session.c | 28 +++++++++++++++++++++---
>  tools/perf/util/session.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 79 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index 23fed17..ba763f7 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"
> @@ -878,8 +877,15 @@ 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)

Hey, this is a _printf_ function, i.e. one thinks about functions with
such name it doing just that, printing whatever is _already_ in the data
structures, at maximum messing with _output_ related internal state.

This probably needs setting up at some other place, so that when it
comes here it is already all worked out.

- Arnaldo

>  {
> +	u64 read_format = evsel->attr.read_format;
> +	struct perf_evlist *evlist = evsel->evlist;
> +	struct perf_sample_id *sid;
> +	perf_freq_t data = { 0 };
> +	u64 cpu_max_freq = evlist->env->cpuattr.max_freq;
> +
>  	printf("... sample_read:\n");
>  
>  	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
> @@ -902,10 +908,26 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
>  			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);
>  		}
>  	} 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));
>  }
>  
>  static void dump_event(struct perf_evlist *evlist, union perf_event *event,
> @@ -965,7 +987,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 3915be7..83bf4a9 100644
> --- a/tools/perf/util/session.h
> +++ b/tools/perf/util/session.h
> @@ -11,6 +11,7 @@
>  #include "ordered-events.h"
>  #include <linux/rbtree.h>
>  #include <linux/perf_event.h>
> +#include "evsel.h"
>  
>  struct ip_callchain;
>  struct thread;
> @@ -42,6 +43,10 @@ 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
> +
>  enum perf_freq_perf_index {
>  	FREQ_PERF_TSC		= 0,
>  	FREQ_PERF_APERF		= 1,
> @@ -52,6 +57,55 @@ enum perf_freq_perf_index {
>  	FREQ_PERF_MAX
>  };
>  
> +typedef u64 perf_freq_t[FREQ_PERF_MAX];
> +
> +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[FREQ_PERF_TSC] = value;
> +		if (evsel->attr.config == PERF_MSR_APERF)
> +			array[FREQ_PERF_APERF] = value;
> +		if (evsel->attr.config == PERF_MSR_MPERF)
> +			array[FREQ_PERF_MPERF] = value;
> +	}
> +	if (evsel->attr.type == PERF_TYPE_HARDWARE) {
> +		if (evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES)
> +			array[FREQ_PERF_CYCLES] = value;
> +		if (evsel->attr.config == PERF_COUNT_HW_REF_CPU_CYCLES)
> +			array[FREQ_PERF_REF_CYCLES] = value;
> +	}
> +}
> +
> +static inline bool perf_freq__has_freq(perf_freq_t array)
> +{
> +	return ((array[FREQ_PERF_CYCLES] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
> +}
> +static inline u64 perf_freq__get_freq(perf_freq_t array, u64 cpu_max_freq)
> +{
> +	return ((array[FREQ_PERF_CYCLES] * cpu_max_freq) / array[FREQ_PERF_REF_CYCLES]);
> +}
> +static inline bool perf_freq__has_cpu_util(perf_freq_t array)
> +{
> +	return ((array[FREQ_PERF_TSC] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
> +}
> +static inline u64 perf_freq__get_cpu_util(perf_freq_t array)
> +{
> +	return ((100 * array[FREQ_PERF_REF_CYCLES]) / array[FREQ_PERF_TSC]);
> +}
> +
> +static inline bool perf_freq__has_core_busy(perf_freq_t array)
> +{
> +	return ((array[FREQ_PERF_APERF] > 0) && (array[FREQ_PERF_MPERF] > 0));
> +}
> +static inline u64 perf_freq__get_core_busy(perf_freq_t array)
> +{
> +	return ((100 * array[FREQ_PERF_APERF]) / array[FREQ_PERF_MPERF]);
> +}
> +
>  struct perf_tool;
>  
>  struct perf_session *perf_session__new(struct perf_data_file *file,
> -- 
> 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]


#1221197 — [PATCH V9 2/6] perf,tools: read msr pmu type from header.

Fromkan.liang@intel.com
Date2015-09-09 04:50 +0200
Subject[PATCH V9 2/6] perf,tools: read msr pmu type from header.
Message-ID<q6DCq-6DS-13@gated-at.bofh.it>
In reply to#1221195
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]


#1222217 — Re: [PATCH V9 2/6] perf,tools: read msr pmu type from header.

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-09-10 16:00 +0200
SubjectRe: [PATCH V9 2/6] perf,tools: read msr pmu type from header.
Message-ID<q7aym-3dh-27@gated-at.bofh.it>
In reply to#1221197
Em Tue, Sep 08, 2015 at 03:32:45PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> Get msr pmu type when processing pmu_mappings

This one looks ok, I am porting it to my current perf/core, that
includes that perf/env branch, will fix up things as we discuss it.

- Arnaldo
 
> 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]


#1224456 — Re: [PATCH V9 2/6] perf,tools: read msr pmu type from header.

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-09-14 23:20 +0200
SubjectRe: [PATCH V9 2/6] perf,tools: read msr pmu type from header.
Message-ID<q8Jkm-1e5-11@gated-at.bofh.it>
In reply to#1221197
Em Tue, Sep 08, 2015 at 03:32:45PM -0400, kan.liang@intel.com escreveu:
> 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>

This one is simple enough, merged already.

- Arnaldo

> ---
>  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]


#1221198 — [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf

Fromkan.liang@intel.com
Date2015-09-09 04:50 +0200
Subject[PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf
Message-ID<q6DCq-6DS-15@gated-at.bofh.it>
In reply to#1221195
From: Kan Liang <kan.liang@intel.com>

Show frequency, CPU Utilization and percent performance for each symbol
in perf report by --freq-perf

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

--freq-perf option also implies --group.

Here is an example.

$ perf report --stdio --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              | 25 ++++++++++-
 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, 137 insertions(+), 22 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index b941d5e..9804e63 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -307,6 +307,18 @@ OPTIONS
 	special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
 	'perf mem' for simpler access.
 
+--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 d6e5203..bd466d8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -134,7 +134,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.freq_perf)
 		set_he_freq_perf(rep->session, iter);
 
 	if (!ui__has_annotation())
@@ -785,6 +786,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, "freq-perf", &symbol_conf.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",
@@ -803,7 +806,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;
@@ -888,6 +893,24 @@ repeat:
 		symbol_conf.cumulate_callchain = false;
 	}
 
+
+	if (symbol_conf.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;
+
+		/* --freq-perf 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 25d6083..059d3e3 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.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.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 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/session.c b/tools/perf/util/session.c
index ba763f7..fc1b451 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.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.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 5e4ed17..89ef407 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1325,6 +1325,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 40073c6..40d2044 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,
+			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]


#1221502 — Re: [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf

FromJiri Olsa <jolsa@redhat.com>
Date2015-09-09 16:40 +0200
SubjectRe: [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf
Message-ID<q6OHw-5QY-15@gated-at.bofh.it>
In reply to#1221198
On Tue, Sep 08, 2015 at 03:32:49PM -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 --freq-perf
> 
> In sampling group, only group leader do sampling. So only need to print
> group leader's freq in --group.
> 
> --freq-perf option also implies --group.
> 
> Here is an example.
> 
> $ perf report --stdio --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>

it seems ok to me, though I think it could be split
into HPP__SINGLE_PRINT_FNS support and the rest..

but I prefer if Arnaldo or Namhyung could review this one

thanks,
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] | [next] | [standalone]


#1221199 — [PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat

Fromkan.liang@intel.com
Date2015-09-09 04:50 +0200
Subject[PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat
Message-ID<q6DCq-6DS-17@gated-at.bofh.it>
In reply to#1221195
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 | 36 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/sort.h      |  3 +++
 2 files changed, 39 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4b43245..d6e5203 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -90,6 +90,38 @@ static int report__config(const char *var, const char *value, void *cb)
 	return perf_default_config(var, value, cb);
 }
 
+static void set_he_freq_perf(struct perf_session *session,
+			     struct hist_entry_iter *iter)
+{
+	struct hist_entry *he = iter->he;
+	struct perf_evsel *evsel = iter->evsel;
+	struct perf_evsel *leader = evsel;
+	struct perf_sample *sample = iter->sample;
+	struct perf_evlist *evlist = session->evlist;
+	u64 cpu_max_freq = session->header.env.cpuattr.max_freq;
+	perf_freq_t data = { 0 };
+	u64 nr = 0;
+
+	perf_freq__init(session->header.env.msr_pmu_type,
+			evsel, data,
+			sample->read.group.values[nr].value);
+	evlist__for_each_continue(evlist, evsel) {
+		if ((evsel->leader != leader) ||
+		     (++nr >= sample->read.group.nr))
+			break;
+		perf_freq__init(session->header.env.msr_pmu_type,
+				evsel, data,
+				sample->read.group.values[nr].value);
+	}
+
+	if (perf_freq__has_freq(data))
+		he->stat.freq = perf_freq__get_freq(data, cpu_max_freq/1000);
+	if (perf_freq__has_cpu_util(data))
+		he->stat.cpu_util = perf_freq__get_cpu_util(data);
+	if (perf_freq__has_core_busy(data))
+		he->stat.core_busy = perf_freq__get_core_busy(data);
+}
+
 static int hist_iter__report_callback(struct hist_entry_iter *iter,
 				      struct addr_location *al, bool single,
 				      void *arg)
@@ -101,6 +133,10 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
 	struct mem_info *mi;
 	struct branch_info *bi;
 
+	if ((iter->ops == &hist_iter_normal) &&
+	    perf_evsel__is_group_leader(evsel))
+		set_he_freq_perf(rep->session, iter);
+
 	if (!ui__has_annotation())
 		return 0;
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 654ac8a..f39e287 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -54,6 +54,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

--
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]


#1221200 — [PATCH V9 3/6] perf, record: introduce --freq-perf option

Fromkan.liang@intel.com
Date2015-09-09 04:50 +0200
Subject[PATCH V9 3/6] perf, record: introduce --freq-perf option
Message-ID<q6DCq-6DS-21@gated-at.bofh.it>
In reply to#1221195
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 --freq-perf option, perf record can automatically check and add
those event into evlist for sampling read.

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 tools/perf/Documentation/perf-record.txt |  4 ++++
 tools/perf/builtin-record.c              | 39 +++++++++++++++++++++++++++++++-
 tools/perf/util/session.h                | 10 ++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2e9ce77..3f40712 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -308,6 +308,10 @@ 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.
 
+--freq-perf::
+Add frequency and performance related events to do sample read.
+These events include cycles, ref-cycles, msr/tsc/, msr/aperf/ and msr/mperf/.
+
 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..e87dda3 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			freq_perf;
 };
 
 static int record__write(struct record *rec, void *bf, size_t size)
@@ -948,6 +949,35 @@ out_free:
 	return ret;
 }
 
+const char *freq_perf_events[FREQ_PERF_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_freq_perf_events(struct perf_evlist *evlist)
+{
+	int i;
+	char freq_perf_attrs[100];
+
+	strcpy(freq_perf_attrs, "{cycles,ref-cycles");
+	for (i = 0; i < FREQ_PERF_MAX; i++) {
+		if ((i == FREQ_PERF_CYCLES) ||
+		    (i == FREQ_PERF_REF_CYCLES))
+			continue;
+		if (pmu_have_event(freq_perf_events[i][0], freq_perf_events[i][1])) {
+			strcat(freq_perf_attrs, ",");
+			strcat(freq_perf_attrs, freq_perf_events[i][2]);
+		}
+	}
+	strcat(freq_perf_attrs, "}:S");
+
+	return parse_events(evlist, freq_perf_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, "freq-perf", &record.freq_perf,
+		    "Add frequency and performance related events to do sample read."),
 	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->freq_perf && record_add_freq_perf_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/session.h b/tools/perf/util/session.h
index b44afc7..3915be7 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -42,6 +42,16 @@ struct perf_session {
 #define PRINT_IP_OPT_ONELINE	(1<<4)
 #define PRINT_IP_OPT_SRCLINE	(1<<5)
 
+enum perf_freq_perf_index {
+	FREQ_PERF_TSC		= 0,
+	FREQ_PERF_APERF		= 1,
+	FREQ_PERF_MPERF		= 2,
+	FREQ_PERF_CYCLES	= 3,
+	FREQ_PERF_REF_CYCLES	= 4,
+
+	FREQ_PERF_MAX
+};
+
 struct perf_tool;
 
 struct perf_session *perf_session__new(struct perf_data_file *file,
-- 
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]


#1221498 — Re: [PATCH V9 3/6] perf, record: introduce --freq-perf option

FromJiri Olsa <jolsa@redhat.com>
Date2015-09-09 16:40 +0200
SubjectRe: [PATCH V9 3/6] perf, record: introduce --freq-perf option
Message-ID<q6OHw-5QY-5@gated-at.bofh.it>
In reply to#1221200
On Tue, Sep 08, 2015 at 03:32:46PM -0400, kan.liang@intel.com wrote:
> 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 --freq-perf option, perf record can automatically check and add
> those event into evlist for sampling read.
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
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] | [next] | [standalone]


#1224458 — Re: [PATCH V9 3/6] perf, record: introduce --freq-perf option

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-09-14 23:20 +0200
SubjectRe: [PATCH V9 3/6] perf, record: introduce --freq-perf option
Message-ID<q8Jkm-1e5-17@gated-at.bofh.it>
In reply to#1221200
Em Tue, Sep 08, 2015 at 03:32:46PM -0400, kan.liang@intel.com escreveu:
> 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 --freq-perf option, perf record can automatically check and add
> those event into evlist for sampling read.
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> ---
>  tools/perf/Documentation/perf-record.txt |  4 ++++
>  tools/perf/builtin-record.c              | 39 +++++++++++++++++++++++++++++++-
>  tools/perf/util/session.h                | 10 ++++++++
>  3 files changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
> index 2e9ce77..3f40712 100644
> --- a/tools/perf/Documentation/perf-record.txt
> +++ b/tools/perf/Documentation/perf-record.txt
> @@ -308,6 +308,10 @@ 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.
>  
> +--freq-perf::
> +Add frequency and performance related events to do sample read.
> +These events include cycles, ref-cycles, msr/tsc/, msr/aperf/ and msr/mperf/.
> +
>  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..e87dda3 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			freq_perf;
>  };
>  
>  static int record__write(struct record *rec, void *bf, size_t size)
> @@ -948,6 +949,35 @@ out_free:
>  	return ret;
>  }
>  
> +const char *freq_perf_events[FREQ_PERF_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_freq_perf_events(struct perf_evlist *evlist)
> +{
> +	int i;
> +	char freq_perf_attrs[100];
> +
> +	strcpy(freq_perf_attrs, "{cycles,ref-cycles");
> +	for (i = 0; i < FREQ_PERF_MAX; i++) {
> +		if ((i == FREQ_PERF_CYCLES) ||
> +		    (i == FREQ_PERF_REF_CYCLES))
> +			continue;
> +		if (pmu_have_event(freq_perf_events[i][0], freq_perf_events[i][1])) {
> +			strcat(freq_perf_attrs, ",");
> +			strcat(freq_perf_attrs, freq_perf_events[i][2]);
> +		}
> +	}
> +	strcat(freq_perf_attrs, "}:S");
> +
> +	return parse_events(evlist, freq_perf_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, "freq-perf", &record.freq_perf,
> +		    "Add frequency and performance related events to do sample read."),

	Isn't this too vague? Can you try rewriting it? what do you mean
with "performance related events"?

	You forgot to add the entry to
tools/perf/Documentation/perf-record.txt, where a less terse explanation
could have helped me understand the part above, oops, sorry, you added
it, but it was really terse! Can you elaborate a bit? Why would one want
to use this? To achieve what? Don't assume everybody knows :-)

>  	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->freq_perf && record_add_freq_perf_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/session.h b/tools/perf/util/session.h
> index b44afc7..3915be7 100644
> --- a/tools/perf/util/session.h
> +++ b/tools/perf/util/session.h
> @@ -42,6 +42,16 @@ struct perf_session {
>  #define PRINT_IP_OPT_ONELINE	(1<<4)
>  #define PRINT_IP_OPT_SRCLINE	(1<<5)
>  
> +enum perf_freq_perf_index {

That is really an overly long enum name! What about:

	enum perf_freqs {
		PERF_FREQ_TSC,
		...
	}

> +	FREQ_PERF_TSC		= 0,
> +	FREQ_PERF_APERF		= 1,
> +	FREQ_PERF_MPERF		= 2,
> +	FREQ_PERF_CYCLES	= 3,
> +	FREQ_PERF_REF_CYCLES	= 4,
> +
> +	FREQ_PERF_MAX
> +};
> +
>  struct perf_tool;
>  
>  struct perf_session *perf_session__new(struct perf_data_file *file,
> -- 
> 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]


#1221499

FromJiri Olsa <jolsa@redhat.com>
Date2015-09-09 16:40 +0200
Message-ID<q6OHw-5QY-3@gated-at.bofh.it>
In reply to#1221195
On Tue, Sep 08, 2015 at 03:32:43PM -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.
> 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 --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
> 
> Changes since V8:
>  - Rename --show-freq-perf to --freq-perf 
>  - --freq-perf option imply --group

I believe I just acked all of it but the last one,
otherwise I'm ok with it

thanks,
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