Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1395460 > unrolled thread
| Started by | Andi Kleen <andi@firstfloor.org> |
|---|---|
| First post | 2016-05-06 01:10 +0200 |
| Last post | 2016-05-12 09:50 +0200 |
| Articles | 20 on this page of 25 — 7 participants |
Back to article view | Back to linux.kernel
Add top down metrics to perf stat Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
[PATCH 05/10] x86, perf: Use new topology_max_smt_threads() in HT leak workaround Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
[PATCH 10/10] perf, tools, stat: Add extra output of counter values with -vv Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
Re: [PATCH 10/10] perf, tools, stat: Add extra output of counter values with -vv Jiri Olsa <jolsa@redhat.com> - 2016-05-12 10:10 +0200
[PATCH 07/10] perf, tools, stat: Scale values by unit before metrics Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
Re: [PATCH 07/10] perf, tools, stat: Scale values by unit before metrics Jiri Olsa <jolsa@redhat.com> - 2016-05-07 21:20 +0200
[tip:perf/core] perf stat: Scale values by unit before metrics tip-bot for Andi Kleen <tipbot@zytor.com> - 2016-05-10 22:40 +0200
[PATCH 09/10] perf, tools, stat: Add computation of TopDown formulas Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
[PATCH 04/10] x86, perf: Add Top Down events to Intel Atom Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
[PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales Jiri Olsa <jolsa@redhat.com> - 2016-05-07 21:20 +0200
Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales Andi Kleen <andi@firstfloor.org> - 2016-05-07 21:30 +0200
Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales Jiri Olsa <jolsa@redhat.com> - 2016-05-11 15:10 +0200
Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-05-11 18:50 +0200
[PATCH 02/10] x86, perf: Support sysfs files depending on SMT status Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status Peter Zijlstra <peterz@infradead.org> - 2016-05-09 11:50 +0200
Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status Andi Kleen <ak@linux.intel.com> - 2016-05-09 16:30 +0200
Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status Peter Zijlstra <peterz@infradead.org> - 2016-05-09 16:40 +0200
Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status Ingo Molnar <mingo@kernel.org> - 2016-05-12 10:10 +0200
[PATCH 03/10] x86, perf: Add Top Down events to Intel Core Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
Re: [PATCH 03/10] x86, perf: Add Top Down events to Intel Core Peter Zijlstra <peterz@infradead.org> - 2016-05-11 15:30 +0200
Re: [PATCH 03/10] x86, perf: Add Top Down events to Intel Core Jiri Olsa <jolsa@redhat.com> - 2016-05-11 15:30 +0200
Re: [PATCH 03/10] x86, perf: Add Top Down events to Intel Core Ingo Molnar <mingo@kernel.org> - 2016-05-12 10:20 +0200
[PATCH 08/10] perf, tools, stat: Basic support for TopDown in perf stat Andi Kleen <andi@firstfloor.org> - 2016-05-06 01:10 +0200
Re: Add top down metrics to perf stat Jiri Olsa <jolsa@redhat.com> - 2016-05-12 09:50 +0200
Page 1 of 2 [1] 2 Next page →
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | Add top down metrics to perf stat |
| Message-ID | <rvAz7-1bh-5@gated-at.bofh.it> |
Note to reviewers: includes both tools and kernel patches.
The kernel patches are at the beginning.
[v2: Address review feedback.
Metrics are now always printed, but colored when crossing threshold.
--topdown implies --metric-only.
Various smaller fixes, see individual patches]
[v3: Add --single-thread option and support it with HT off.
Clean up old HT workaround.
Improve documentation.
Various smaller fixes, see individual patches.]
[v4: Rebased on latest tree]
[v5: Rebased on latest tree. Move debug messages to -vv]
[v6: Rebased. Remove .aggr-per-core and --single-thread to not
break old perf binaries. Put SMT enumeration into
generic topology API.]
This patchkit adds support for TopDown measurements to perf stat
It applies on top of my earlier metrics patchkit, posted
separately.
TopDown is intended to replace the frontend cycles idle/
backend cycles idle metrics in standard perf stat output.
These metrics are not reliable in many workloads,
due to out of order effects.
This implements a new --topdown mode in perf stat
(similar to --transaction) that measures the pipe line
bottlenecks using standardized formulas. The measurement
can be all done with 5 counters (one fixed counter)
The result are four metrics:
FrontendBound, BackendBound, BadSpeculation, Retiring
that describe the CPU pipeline behavior on a high level.
FrontendBound and BackendBound
BadSpeculation is a higher
The full top down methology has many hierarchical metrics.
This implementation only supports level 1 which can be
collected without multiplexing. A full implementation
of top down on top of perf is available in pmu-tools toplev.
(http://github.com/andikleen/pmu-tools)
The current version works on Intel Core CPUs starting
with Sandy Bridge, and Atom CPUs starting with Silvermont.
In principle the generic metrics should be also implementable
on other out of order CPUs.
TopDown level 1 uses a set of abstracted metrics which
are generic to out of order CPU cores (although some
CPUs may not implement all of them):
topdown-total-slots Available slots in the pipeline
topdown-slots-issued Slots issued into the pipeline
topdown-slots-retired Slots successfully retired
topdown-fetch-bubbles Pipeline gaps in the frontend
topdown-recovery-bubbles Pipeline gaps during recovery
from misspeculation
These metrics then allow to compute four useful metrics:
FrontendBound, BackendBound, Retiring, BadSpeculation.
The formulas to compute the metrics are generic, they
only change based on the availability on the abstracted
input values.
The kernel declares the events supported by the current
CPU and perf stat then computes the formulas based on the
available metrics.
Example output:
$ perf stat --topdown -I 1000 cmd
1.000735655 frontend bound retiring bad speculation backend bound
1.000735655 S0-C0 2 47.84% 11.69% 8.37% 32.10%
1.000735655 S0-C1 2 45.53% 11.39% 8.52% 34.56%
2.003978563 S0-C0 2 49.47% 12.22% 8.65% 29.66%
2.003978563 S0-C1 2 47.21% 12.98% 8.77% 31.04%
3.004901432 S0-C0 2 49.35% 12.26% 8.68% 29.70%
3.004901432 S0-C1 2 47.23% 12.67% 8.76% 31.35%
4.005766611 S0-C0 2 48.44% 12.14% 8.59% 30.82%
4.005766611 S0-C1 2 46.07% 12.41% 8.67% 32.85%
5.006580592 S0-C0 2 47.91% 12.08% 8.57% 31.44%
5.006580592 S0-C1 2 45.57% 12.27% 8.63% 33.53%
6.007545125 S0-C0 2 47.45% 12.02% 8.57% 31.96%
6.007545125 S0-C1 2 45.13% 12.17% 8.57% 34.14%
7.008539347 S0-C0 2 47.07% 12.03% 8.61% 32.29%
...
For Level 1 Top Down computes metrics per core instead of per logical CPU
on Core CPUs (On Atom CPUs there is no Hyper Threading and TopDown
is per thread)
In this case perf stat automatically enables --per-core mode and also requires
global mode (-a) and avoiding other filters (no cgroup mode)
One side effect is that this may require root rights or a
kernel.perf_event_paranoid=-1 setting.
Full tree available in
git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc perf/top-down-20
[toc] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 05/10] x86, perf: Use new topology_max_smt_threads() in HT leak workaround |
| Message-ID | <rvAz7-1bh-7@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
Now that we have topology_max_smt_threads() use it
to detect the HT workarounds for older CPUs.
v2: Use topology_max_smt_threads()
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/events/intel/core.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 6ea16f705de4..fcc9a010cb0a 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3991,16 +3991,14 @@ __init int intel_pmu_init(void)
*/
static __init int fixup_ht_bug(void)
{
- int cpu = smp_processor_id();
- int w, c;
+ int c;
/*
* problem not present on this CPU model, nothing to do
*/
if (!(x86_pmu.flags & PMU_FL_EXCL_ENABLED))
return 0;
- w = cpumask_weight(topology_sibling_cpumask(cpu));
- if (w > 1) {
+ if (topology_max_smt_threads() > 1) {
pr_info("PMU erratum BJ122, BV98, HSD29 worked around, HT is on\n");
return 0;
}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 10/10] perf, tools, stat: Add extra output of counter values with -vv |
| Message-ID | <rvAz7-1bh-9@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
Add debug output of raw counter values per CPU when
perf stat -v is specified, together with their cpu numbers.
This is very useful to debug problems with per core counters,
where we can normally only see aggregated values.
v2: Make it depend on -vv, not -v
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/builtin-stat.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 707eef9314da..7c5c50b61b28 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -313,6 +313,14 @@ static int read_counter(struct perf_evsel *counter)
return -1;
}
}
+
+ if (verbose > 1) {
+ fprintf(stat_config.output,
+ "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+ perf_evsel__name(counter),
+ cpu,
+ count->val, count->ena, count->run);
+ }
}
}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2016-05-12 10:10 +0200 |
| Subject | Re: [PATCH 10/10] perf, tools, stat: Add extra output of counter values with -vv |
| Message-ID | <rxTQZ-1yW-9@gated-at.bofh.it> |
| In reply to | #1395462 |
On Thu, May 05, 2016 at 04:04:07PM -0700, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> Add debug output of raw counter values per CPU when
> perf stat -v is specified, together with their cpu numbers.
> This is very useful to debug problems with per core counters,
> where we can normally only see aggregated values.
>
> v2: Make it depend on -vv, not -v
> Signed-off-by: Andi Kleen <ak@linux.intel.com>
> ---
> tools/perf/builtin-stat.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index 707eef9314da..7c5c50b61b28 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -313,6 +313,14 @@ static int read_counter(struct perf_evsel *counter)
> return -1;
> }
> }
> +
> + if (verbose > 1) {
> + fprintf(stat_config.output,
> + "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
> + perf_evsel__name(counter),
> + cpu,
> + count->val, count->ena, count->run);
> + }
hi,
we already have similar output for aggregated counters,
could you please consider something like below to clearly
separate them?
[root@ibm-x3650m4-01 perf]# ./perf stat -e cycles -I 1000 -vv -a -C 0,1
...
cycles: CPU 0: 1298783264 1000126956 1000126956
cycles: CPU 1: 1298791660 1000134589 1000134589
cycles: AGGR: 2597574924 2000261545 2000261545
...
thanks,
jirka
---
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7c5c50b61b28..bd0d67ebb757 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -316,7 +316,7 @@ static int read_counter(struct perf_evsel *counter)
if (verbose > 1) {
fprintf(stat_config.output,
- "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+ "%s: CPU %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
perf_evsel__name(counter),
cpu,
count->val, count->ena, count->run);
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index c1ba255f2abe..5ddeea1399ee 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -345,7 +345,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
update_stats(&ps->res_stats[i], count[i]);
if (verbose) {
- fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+ fprintf(config->output, "%s: AGGR: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
perf_evsel__name(counter), count[0], count[1], count[2]);
}
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 07/10] perf, tools, stat: Scale values by unit before metrics |
| Message-ID | <rvAz8-1bh-15@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com> Scale values by unit before passing them to the metrics printing functions. This is needed for TopDown, because it needs to scale the slots correctly by pipeline width / SMTness. For existing metrics it shouldn't make any difference, as those generally use events that don't have any units. Signed-off-by: Andi Kleen <ak@linux.intel.com> --- tools/perf/util/stat.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 4d9b481cf3b6..ffa1d0653861 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, struct perf_counts_values *aggr = &counter->counts->aggr; struct perf_stat_evsel *ps = counter->priv; u64 *count = counter->counts->aggr.values; + u64 val; int i, ret; aggr->val = aggr->ena = aggr->run = 0; @@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, /* * Save the full runtime - to allow normalization during printout: */ - perf_stat__update_shadow_stats(counter, count, 0); + val = counter->scale * *count; + perf_stat__update_shadow_stats(counter, &val, 0); return 0; } -- 2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2016-05-07 21:20 +0200 |
| Subject | Re: [PATCH 07/10] perf, tools, stat: Scale values by unit before metrics |
| Message-ID | <rwfVE-7th-9@gated-at.bofh.it> |
| In reply to | #1395464 |
On Thu, May 05, 2016 at 04:04:04PM -0700, Andi Kleen wrote: > From: Andi Kleen <ak@linux.intel.com> > > Scale values by unit before passing them to the metrics printing functions. > This is needed for TopDown, because it needs to scale the slots correctly > by pipeline width / SMTness. > > For existing metrics it shouldn't make any difference, as those generally > use events that don't have any units. > > Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> thanks, jirka > --- > tools/perf/util/stat.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c > index 4d9b481cf3b6..ffa1d0653861 100644 > --- a/tools/perf/util/stat.c > +++ b/tools/perf/util/stat.c > @@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, > struct perf_counts_values *aggr = &counter->counts->aggr; > struct perf_stat_evsel *ps = counter->priv; > u64 *count = counter->counts->aggr.values; > + u64 val; > int i, ret; > > aggr->val = aggr->ena = aggr->run = 0; > @@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, > /* > * Save the full runtime - to allow normalization during printout: > */ > - perf_stat__update_shadow_stats(counter, count, 0); > + val = counter->scale * *count; > + perf_stat__update_shadow_stats(counter, &val, 0); > > return 0; > } > -- > 2.5.5 >
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Andi Kleen <tipbot@zytor.com> |
|---|---|
| Date | 2016-05-10 22:40 +0200 |
| Subject | [tip:perf/core] perf stat: Scale values by unit before metrics |
| Message-ID | <rxmBI-1xY-21@gated-at.bofh.it> |
| In reply to | #1395464 |
Commit-ID: f340c5fc93bda334efd9f2b5855ef0d3746e1564 Gitweb: http://git.kernel.org/tip/f340c5fc93bda334efd9f2b5855ef0d3746e1564 Author: Andi Kleen <ak@linux.intel.com> AuthorDate: Thu, 5 May 2016 16:04:04 -0700 Committer: Arnaldo Carvalho de Melo <acme@redhat.com> CommitDate: Mon, 9 May 2016 13:42:09 -0300 perf stat: Scale values by unit before metrics Scale values by unit before passing them to the metrics printing functions. This is needed for TopDown, because it needs to scale the slots correctly by pipeline width / SMTness. For existing metrics it shouldn't make any difference, as those generally use events that don't have any units. Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1462489447-31832-8-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/stat.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 4d9b481..ffa1d06 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, struct perf_counts_values *aggr = &counter->counts->aggr; struct perf_stat_evsel *ps = counter->priv; u64 *count = counter->counts->aggr.values; + u64 val; int i, ret; aggr->val = aggr->ena = aggr->run = 0; @@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, /* * Save the full runtime - to allow normalization during printout: */ - perf_stat__update_shadow_stats(counter, count, 0); + val = counter->scale * *count; + perf_stat__update_shadow_stats(counter, &val, 0); return 0; }
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 09/10] perf, tools, stat: Add computation of TopDown formulas |
| Message-ID | <rvAz8-1bh-17@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
Implement the TopDown formulas in perf stat. The topdown basic metrics
reported by the kernel are collected, and the formulas are computed
and output as normal metrics.
See the kernel commit exporting the events for details on the used
metrics.
v2: Always print all metrics, only use thresholds for coloring.
v3: Mark retiring over threshold green, not red.
v4:
Only print one decimal digit
Fix color printing of one metric
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/util/stat-shadow.c | 156 ++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/stat.c | 5 ++
tools/perf/util/stat.h | 5 ++
3 files changed, 166 insertions(+)
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index fdb71961143e..182050f2785a 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -36,6 +36,11 @@ static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];
+static struct stats runtime_topdown_total_slots[NUM_CTX][MAX_NR_CPUS];
+static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
+static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
+static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
+static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
static bool have_frontend_stalled;
struct stats walltime_nsecs_stats;
@@ -82,6 +87,12 @@ void perf_stat__reset_shadow_stats(void)
sizeof(runtime_transaction_stats));
memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
+ memset(runtime_topdown_total_slots, 0, sizeof(runtime_topdown_total_slots));
+ memset(runtime_topdown_slots_retired, 0, sizeof(runtime_topdown_slots_retired));
+ memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued));
+ memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles));
+ memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles));
+ have_frontend_stalled = pmu_have_event("cpu", "stalled-cycles-frontend");
}
/*
@@ -104,6 +115,16 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
else if (perf_stat_evsel__is(counter, ELISION_START))
update_stats(&runtime_elision_stats[ctx][cpu], count[0]);
+ else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS))
+ update_stats(&runtime_topdown_total_slots[ctx][cpu], count[0]);
+ else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED))
+ update_stats(&runtime_topdown_slots_issued[ctx][cpu], count[0]);
+ else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED))
+ update_stats(&runtime_topdown_slots_retired[ctx][cpu], count[0]);
+ else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES))
+ update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu],count[0]);
+ else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES))
+ update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count[0]);
else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
@@ -301,6 +322,100 @@ static void print_ll_cache_misses(int cpu,
out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
}
+/*
+ * High level "TopDown" CPU core pipe line bottleneck break down.
+ *
+ * Basic concept following
+ * Yasin, A Top Down Method for Performance analysis and Counter architecture
+ * ISPASS14
+ *
+ * The CPU pipeline is divided into 4 areas that can be bottlenecks:
+ *
+ * Frontend -> Backend -> Retiring
+ * BadSpeculation in addition means out of order execution that is thrown away
+ * (for example branch mispredictions)
+ * Frontend is instruction decoding.
+ * Backend is execution, like computation and accessing data in memory
+ * Retiring is good execution that is not directly bottlenecked
+ *
+ * The formulas are computed in slots.
+ * A slot is an entry in the pipeline each for the pipeline width
+ * (for example a 4-wide pipeline has 4 slots for each cycle)
+ *
+ * Formulas:
+ * BadSpeculation = ((SlotsIssued - SlotsRetired) + RecoveryBubbles) /
+ * TotalSlots
+ * Retiring = SlotsRetired / TotalSlots
+ * FrontendBound = FetchBubbles / TotalSlots
+ * BackendBound = 1.0 - BadSpeculation - Retiring - FrontendBound
+ *
+ * The kernel provides the mapping to the low level CPU events and any scaling
+ * needed for the CPU pipeline width, for example:
+ *
+ * TotalSlots = Cycles * 4
+ *
+ * The scaling factor is communicated in the sysfs unit.
+ *
+ * In some cases the CPU may not be able to measure all the formulas due to
+ * missing events. In this case multiple formulas are combined, as possible.
+ *
+ * Full TopDown supports more levels to sub-divide each area: for example
+ * BackendBound into computing bound and memory bound. For now we only
+ * support Level 1 TopDown.
+ */
+
+static double td_total_slots(int ctx, int cpu)
+{
+ return avg_stats(&runtime_topdown_total_slots[ctx][cpu]);
+}
+
+static double td_bad_spec(int ctx, int cpu)
+{
+ double bad_spec = 0;
+ double total_slots;
+ double total;
+
+ total = avg_stats(&runtime_topdown_slots_issued[ctx][cpu]) -
+ avg_stats(&runtime_topdown_slots_retired[ctx][cpu]) +
+ avg_stats(&runtime_topdown_recovery_bubbles[ctx][cpu]);
+ total_slots = td_total_slots(ctx, cpu);
+ if (total_slots)
+ bad_spec = total / total_slots;
+ return bad_spec;
+}
+
+static double td_retiring(int ctx, int cpu)
+{
+ double retiring = 0;
+ double total_slots = td_total_slots(ctx, cpu);
+ double ret_slots = avg_stats(&runtime_topdown_slots_retired[ctx][cpu]);
+
+ if (total_slots)
+ retiring = ret_slots / total_slots;
+ return retiring;
+}
+
+static double td_fe_bound(int ctx, int cpu)
+{
+ double fe_bound = 0;
+ double total_slots = td_total_slots(ctx, cpu);
+ double fetch_bub = avg_stats(&runtime_topdown_fetch_bubbles[ctx][cpu]);
+
+ if (total_slots)
+ fe_bound = fetch_bub / total_slots;
+ return fe_bound;
+}
+
+static double td_be_bound(int ctx, int cpu)
+{
+ double sum = (td_fe_bound(ctx, cpu) +
+ td_bad_spec(ctx, cpu) +
+ td_retiring(ctx, cpu));
+ if (sum == 0)
+ return 0;
+ return 1.0 - sum;
+}
+
void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
double avg, int cpu,
struct perf_stat_output_ctx *out)
@@ -308,6 +423,7 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
void *ctxp = out->ctx;
print_metric_t print_metric = out->print_metric;
double total, ratio = 0.0, total2;
+ const char *color = NULL;
int ctx = evsel_context(evsel);
if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
@@ -450,6 +566,46 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
avg / ratio);
else
print_metric(ctxp, NULL, NULL, "CPUs utilized", 0);
+ } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
+ double fe_bound = td_fe_bound(ctx, cpu);
+
+ if (fe_bound > 0.2)
+ color = PERF_COLOR_RED;
+ print_metric(ctxp, color, "%8.1f%%", "frontend bound",
+ fe_bound * 100.);
+ } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
+ double retiring = td_retiring(ctx, cpu);
+
+ if (retiring > 0.7)
+ color = PERF_COLOR_GREEN;
+ print_metric(ctxp, color, "%8.1f%%", "retiring",
+ retiring * 100.);
+ } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
+ double bad_spec = td_bad_spec(ctx, cpu);
+
+ if (bad_spec > 0.1)
+ color = PERF_COLOR_RED;
+ print_metric(ctxp, color, "%8.1f%%", "bad speculation",
+ bad_spec * 100.);
+ } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
+ double be_bound = td_be_bound(ctx, cpu);
+ const char *name = "backend bound";
+ static int have_recovery_bubbles = -1;
+
+ /* In case the CPU does not support topdown-recovery-bubbles */
+ if (have_recovery_bubbles < 0)
+ have_recovery_bubbles = pmu_have_event("cpu",
+ "topdown-recovery-bubbles");
+ if (!have_recovery_bubbles)
+ name = "backend bound/bad spec";
+
+ if (be_bound > 0.2)
+ color = PERF_COLOR_RED;
+ if (td_total_slots(ctx, cpu) > 0)
+ print_metric(ctxp, color, "%8.1f%%", name,
+ be_bound * 100.);
+ else
+ print_metric(ctxp, NULL, NULL, name, 0);
} else if (runtime_nsecs_stats[cpu].n != 0) {
char unit = 'M';
char unit_buf[10];
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index ffa1d0653861..c1ba255f2abe 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -79,6 +79,11 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
ID(TRANSACTION_START, cpu/tx-start/),
ID(ELISION_START, cpu/el-start/),
ID(CYCLES_IN_TX_CP, cpu/cycles-ct/),
+ ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
+ ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
+ ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
+ ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
+ ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
};
#undef ID
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0150e786ccc7..c29bb94c48a4 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -17,6 +17,11 @@ enum perf_stat_evsel_id {
PERF_STAT_EVSEL_ID__TRANSACTION_START,
PERF_STAT_EVSEL_ID__ELISION_START,
PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP,
+ PERF_STAT_EVSEL_ID__TOPDOWN_TOTAL_SLOTS,
+ PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_ISSUED,
+ PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_RETIRED,
+ PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_BUBBLES,
+ PERF_STAT_EVSEL_ID__TOPDOWN_RECOVERY_BUBBLES,
PERF_STAT_EVSEL_ID__MAX,
};
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 04/10] x86, perf: Add Top Down events to Intel Atom |
| Message-ID | <rvAz8-1bh-21@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
Add topdown event declarations to Silvermont / Airmont.
These cores do not support the full Top Down metrics, but an useful
subset (FrontendBound, Retiring, Backend Bound/Bad Speculation).
The perf stat tool automatically handles the missing events
and combines the available metrics.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/events/intel/core.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 8b146007c264..6ea16f705de4 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -1369,6 +1369,29 @@ static __initconst const u64 atom_hw_cache_event_ids
},
};
+EVENT_ATTR_STR(topdown-total-slots, td_total_slots_slm, "event=0x3c");
+EVENT_ATTR_STR(topdown-total-slots.scale, td_total_slots_scale_slm, "2");
+/* no_alloc_cycles.not_delivered */
+EVENT_ATTR_STR(topdown-fetch-bubbles, td_fetch_bubbles_slm,
+ "event=0xca,umask=0x50");
+EVENT_ATTR_STR(topdown-fetch-bubbles.scale, td_fetch_bubbles_scale_slm, "2");
+/* uops_retired.all */
+EVENT_ATTR_STR(topdown-slots-issued, td_slots_issued_slm,
+ "event=0xc2,umask=0x10");
+/* uops_retired.all */
+EVENT_ATTR_STR(topdown-slots-retired, td_slots_retired_slm,
+ "event=0xc2,umask=0x10");
+
+static struct attribute *slm_events_attrs[] = {
+ EVENT_PTR(td_total_slots_slm),
+ EVENT_PTR(td_total_slots_scale_slm),
+ EVENT_PTR(td_fetch_bubbles_slm),
+ EVENT_PTR(td_fetch_bubbles_scale_slm),
+ EVENT_PTR(td_slots_issued_slm),
+ EVENT_PTR(td_slots_retired_slm),
+ NULL
+};
+
static struct extra_reg intel_slm_extra_regs[] __read_mostly =
{
/* must define OFFCORE_RSP_X first, see intel_fixup_er() */
@@ -3631,6 +3654,7 @@ __init int intel_pmu_init(void)
x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
x86_pmu.extra_regs = intel_slm_extra_regs;
x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+ x86_pmu.cpu_events = slm_events_attrs;
pr_cont("Silvermont events, ");
break;
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales |
| Message-ID | <rvAz8-1bh-25@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
When the scaling factor is a full integer don't display fractional
digits. This avoids unnecessary .00 output for topdown metrics
with scale factors.
v2: Remove redundant check.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/builtin-stat.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1f19f2f999c8..b407a11c6e22 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -66,6 +66,7 @@
#include <stdlib.h>
#include <sys/prctl.h>
#include <locale.h>
+#include <math.h>
#define DEFAULT_SEPARATOR " "
#define CNTR_NOT_SUPPORTED "<not supported>"
@@ -978,12 +979,12 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
const char *fmt;
if (csv_output) {
- fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
+ fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
} else {
if (big_num)
- fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
+ fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
else
- fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
+ fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
}
aggr_printout(evsel, id, nr);
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2016-05-07 21:20 +0200 |
| Subject | Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales |
| Message-ID | <rwfVE-7th-15@gated-at.bofh.it> |
| In reply to | #1395469 |
On Thu, May 05, 2016 at 04:04:03PM -0700, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> When the scaling factor is a full integer don't display fractional
> digits. This avoids unnecessary .00 output for topdown metrics
> with scale factors.
>
> v2: Remove redundant check.
> Signed-off-by: Andi Kleen <ak@linux.intel.com>
> ---
> tools/perf/builtin-stat.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index 1f19f2f999c8..b407a11c6e22 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -66,6 +66,7 @@
> #include <stdlib.h>
> #include <sys/prctl.h>
> #include <locale.h>
> +#include <math.h>
>
> #define DEFAULT_SEPARATOR " "
> #define CNTR_NOT_SUPPORTED "<not supported>"
> @@ -978,12 +979,12 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
> const char *fmt;
>
> if (csv_output) {
> - fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
> + fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
> } else {
> if (big_num)
> - fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
> + fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
> else
> - fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
> + fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
how about the rest of the code? we display % also in print_running
and print_noise_pct functions and maybe some place else
would be nice having unified output for %
thanks,
jirka
> }
>
> aggr_printout(evsel, id, nr);
> --
> 2.5.5
>
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-07 21:30 +0200 |
| Subject | Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales |
| Message-ID | <rwg5k-7CS-13@gated-at.bofh.it> |
| In reply to | #1396349 |
> > if (csv_output) {
> > - fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
> > + fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
> > } else {
> > if (big_num)
> > - fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
> > + fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
> > else
> > - fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
> > + fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
>
> how about the rest of the code? we display % also in print_running
> and print_noise_pct functions and maybe some place else
For those it doesn't matter. In fact it's probably better there
to always show the fractions.
It is just confusing for metrics.
-Andi
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2016-05-11 15:10 +0200 |
| Subject | Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales |
| Message-ID | <rxC3N-to-23@gated-at.bofh.it> |
| In reply to | #1396355 |
On Sat, May 07, 2016 at 12:24:25PM -0700, Andi Kleen wrote:
> > > if (csv_output) {
> > > - fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
> > > + fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
> > > } else {
> > > if (big_num)
> > > - fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
> > > + fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
> > > else
> > > - fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
> > > + fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
> >
> > how about the rest of the code? we display % also in print_running
> > and print_noise_pct functions and maybe some place else
>
> For those it doesn't matter. In fact it's probably better there
> to always show the fractions.
>
> It is just confusing for metrics.
ok, let's try and see, we can always follow up
with the rest if there's a need
Acked-by: Jiri Olsa <jolsa@kernel.org>
thanks,
jirka
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-05-11 18:50 +0200 |
| Subject | Re: [PATCH 06/10] perf, tools, stat: Avoid fractional digits for integer scales |
| Message-ID | <rxFuH-3yH-39@gated-at.bofh.it> |
| In reply to | #1399062 |
Em Wed, May 11, 2016 at 03:00:31PM +0200, Jiri Olsa escreveu:
> On Sat, May 07, 2016 at 12:24:25PM -0700, Andi Kleen wrote:
> > > > if (csv_output) {
> > > > - fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
> > > > + fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
> > > > } else {
> > > > if (big_num)
> > > > - fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
> > > > + fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
> > > > else
> > > > - fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
> > > > + fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
> > >
> > > how about the rest of the code? we display % also in print_running
> > > and print_noise_pct functions and maybe some place else
> >
> > For those it doesn't matter. In fact it's probably better there
> > to always show the fractions.
> >
> > It is just confusing for metrics.
>
> ok, let's try and see, we can always follow up
> with the rest if there's a need
>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
Missed this one, applied.
- Arnaldo
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status |
| Message-ID | <rvAz8-1bh-23@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
Add a way to show different sysfs events attributes depending on
HyperThreading is on or off. This is difficult to determine
early at boot, so we just do it dynamically when the sysfs
attribute is read.
v2:
Compute HT status only once in CPU online/offline hooks.
v3: Use topology_max_smt_threads()
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/events/core.c | 24 ++++++++++++++++++++++++
arch/x86/events/perf_event.h | 14 ++++++++++++++
include/linux/perf_event.h | 7 +++++++
3 files changed, 45 insertions(+)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 5e5e76a52f58..ec26d7a6ed40 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1622,6 +1622,30 @@ ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, cha
}
EXPORT_SYMBOL_GPL(events_sysfs_show);
+ssize_t events_ht_sysfs_show(struct device *dev, struct device_attribute *attr,
+ char *page)
+{
+ struct perf_pmu_events_ht_attr *pmu_attr =
+ container_of(attr, struct perf_pmu_events_ht_attr, attr);
+
+ /*
+ * Report conditional events depending on Hyper-Threading.
+ *
+ * This is overly conservative as usually the HT special
+ * handling is not needed if the other CPU thread is idle.
+ *
+ * Note this does not (cannot) handle the case when thread
+ * siblings are invisible, for example with virtualization
+ * if they are owned by some other guest. The user tool
+ * has to re-read when a thread sibling gets onlined later.
+ */
+
+ return sprintf(page, "%s",
+ topology_max_smt_threads() > 1 ?
+ pmu_attr->event_str_ht :
+ pmu_attr->event_str_noht);
+}
+
EVENT_ATTR(cpu-cycles, CPU_CYCLES );
EVENT_ATTR(instructions, INSTRUCTIONS );
EVENT_ATTR(cache-references, CACHE_REFERENCES );
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 8bd764df815d..ad2e870f77d9 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -668,6 +668,14 @@ static struct perf_pmu_events_attr event_attr_##v = { \
.event_str = str, \
};
+#define EVENT_ATTR_STR_HT(_name, v, noht, ht) \
+static struct perf_pmu_events_ht_attr event_attr_##v = { \
+ .attr = __ATTR(_name, 0444, events_ht_sysfs_show, NULL),\
+ .id = 0, \
+ .event_str_noht = noht, \
+ .event_str_ht = ht, \
+}
+
extern struct x86_pmu x86_pmu __read_mostly;
static inline bool x86_pmu_has_lbr_callstack(void)
@@ -938,6 +946,12 @@ int p6_pmu_init(void);
int knc_pmu_init(void);
+ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+ char *page);
+
+ssize_t events_ht_sysfs_show(struct device *dev, struct device_attribute *attr,
+ char *page);
+
static inline int is_ht_workaround_enabled(void)
{
return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 9e1c3ada91c4..b425f2d24b26 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1304,6 +1304,13 @@ struct perf_pmu_events_attr {
const char *event_str;
};
+struct perf_pmu_events_ht_attr {
+ struct device_attribute attr;
+ u64 id;
+ const char *event_str_ht;
+ const char *event_str_noht;
+};
+
ssize_t perf_event_sysfs_show(struct device *dev, struct device_attribute *attr,
char *page);
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2016-05-09 11:50 +0200 |
| Subject | Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status |
| Message-ID | <rwPZ8-2Mv-7@gated-at.bofh.it> |
| In reply to | #1395470 |
On Thu, May 05, 2016 at 04:03:59PM -0700, Andi Kleen wrote: > From: Andi Kleen <ak@linux.intel.com> > > Add a way to show different sysfs events attributes depending on > HyperThreading is on or off. This is difficult to determine > early at boot, so we just do it dynamically when the sysfs > attribute is read. > > v2: > Compute HT status only once in CPU online/offline hooks. > v3: Use topology_max_smt_threads() > Signed-off-by: Andi Kleen <ak@linux.intel.com> > --- > arch/x86/events/core.c | 24 ++++++++++++++++++++++++ > arch/x86/events/perf_event.h | 14 ++++++++++++++ > include/linux/perf_event.h | 7 +++++++ > 3 files changed, 45 insertions(+) > Should this not now live in /sys/devices/system/cpu/ ? Thomas?
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <ak@linux.intel.com> |
|---|---|
| Date | 2016-05-09 16:30 +0200 |
| Subject | Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status |
| Message-ID | <rwUm5-7na-1@gated-at.bofh.it> |
| In reply to | #1396890 |
On Mon, May 09, 2016 at 11:42:19AM +0200, Peter Zijlstra wrote: > On Thu, May 05, 2016 at 04:03:59PM -0700, Andi Kleen wrote: > > From: Andi Kleen <ak@linux.intel.com> > > > > Add a way to show different sysfs events attributes depending on > > HyperThreading is on or off. This is difficult to determine > > early at boot, so we just do it dynamically when the sysfs > > attribute is read. > > > > v2: > > Compute HT status only once in CPU online/offline hooks. > > v3: Use topology_max_smt_threads() > > Signed-off-by: Andi Kleen <ak@linux.intel.com> > > --- > > arch/x86/events/core.c | 24 ++++++++++++++++++++++++ > > arch/x86/events/perf_event.h | 14 ++++++++++++++ > > include/linux/perf_event.h | 7 +++++++ > > 3 files changed, 45 insertions(+) > > > > Should this not now live in /sys/devices/system/cpu/ ? Thomas? This would be incompatible to all previous perf tools. Also not clear why you would want to move such events, just because they depend on SMT. -Andi -- ak@linux.intel.com -- Speaking for myself only
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2016-05-09 16:40 +0200 |
| Subject | Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status |
| Message-ID | <rwUvM-7tx-25@gated-at.bofh.it> |
| In reply to | #1397088 |
On Mon, May 09, 2016 at 07:27:41AM -0700, Andi Kleen wrote: > On Mon, May 09, 2016 at 11:42:19AM +0200, Peter Zijlstra wrote: > > On Thu, May 05, 2016 at 04:03:59PM -0700, Andi Kleen wrote: > > > From: Andi Kleen <ak@linux.intel.com> > > > > > > Add a way to show different sysfs events attributes depending on > > > HyperThreading is on or off. This is difficult to determine > > > early at boot, so we just do it dynamically when the sysfs > > > attribute is read. > > > > > > v2: > > > Compute HT status only once in CPU online/offline hooks. > > > v3: Use topology_max_smt_threads() > > > Signed-off-by: Andi Kleen <ak@linux.intel.com> > > > --- > > > arch/x86/events/core.c | 24 ++++++++++++++++++++++++ > > > arch/x86/events/perf_event.h | 14 ++++++++++++++ > > > include/linux/perf_event.h | 7 +++++++ > > > 3 files changed, 45 insertions(+) > > > > > > > Should this not now live in /sys/devices/system/cpu/ ? Thomas? > > This would be incompatible to all previous perf tools. > > Also not clear why you would want to move such events, just > because they depend on SMT. Durr, my bad; I read the patch wrong. I'll go have another look. Thanks
[toc] | [prev] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2016-05-12 10:10 +0200 |
| Subject | Re: [PATCH 02/10] x86, perf: Support sysfs files depending on SMT status |
| Message-ID | <rxTQZ-1yW-15@gated-at.bofh.it> |
| In reply to | #1395470 |
* Andi Kleen <andi@firstfloor.org> wrote:
> +ssize_t events_ht_sysfs_show(struct device *dev, struct device_attribute *attr,
> + char *page)
> +{
> + struct perf_pmu_events_ht_attr *pmu_attr =
> + container_of(attr, struct perf_pmu_events_ht_attr, attr);
> +
> + /*
> + * Report conditional events depending on Hyper-Threading.
> + *
> + * This is overly conservative as usually the HT special
> + * handling is not needed if the other CPU thread is idle.
> + *
> + * Note this does not (cannot) handle the case when thread
> + * siblings are invisible, for example with virtualization
> + * if they are owned by some other guest. The user tool
> + * has to re-read when a thread sibling gets onlined later.
> + */
> +
> + return sprintf(page, "%s",
> + topology_max_smt_threads() > 1 ?
> + pmu_attr->event_str_ht :
> + pmu_attr->event_str_noht);
> +}
> +
> EVENT_ATTR(cpu-cycles, CPU_CYCLES );
> EVENT_ATTR(instructions, INSTRUCTIONS );
> EVENT_ATTR(cache-references, CACHE_REFERENCES );
> diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
> index 8bd764df815d..ad2e870f77d9 100644
> --- a/arch/x86/events/perf_event.h
> +++ b/arch/x86/events/perf_event.h
> @@ -668,6 +668,14 @@ static struct perf_pmu_events_attr event_attr_##v = { \
> .event_str = str, \
> };
>
> +#define EVENT_ATTR_STR_HT(_name, v, noht, ht) \
> +static struct perf_pmu_events_ht_attr event_attr_##v = { \
> + .attr = __ATTR(_name, 0444, events_ht_sysfs_show, NULL),\
> + .id = 0, \
> + .event_str_noht = noht, \
> + .event_str_ht = ht, \
> +}
> +
> extern struct x86_pmu x86_pmu __read_mostly;
>
> static inline bool x86_pmu_has_lbr_callstack(void)
> @@ -938,6 +946,12 @@ int p6_pmu_init(void);
>
> int knc_pmu_init(void);
>
> +ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
> + char *page);
> +
> +ssize_t events_ht_sysfs_show(struct device *dev, struct device_attribute *attr,
> + char *page);
> +
> static inline int is_ht_workaround_enabled(void)
> {
> return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index 9e1c3ada91c4..b425f2d24b26 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -1304,6 +1304,13 @@ struct perf_pmu_events_attr {
> const char *event_str;
> };
>
> +struct perf_pmu_events_ht_attr {
> + struct device_attribute attr;
> + u64 id;
> + const char *event_str_ht;
> + const char *event_str_noht;
> +};
> +
> ssize_t perf_event_sysfs_show(struct device *dev, struct device_attribute *attr,
> char *page);
>
NAK for the following stylistic reasons:
- structure definition does not follow existing style.
- silly line breaks inserted into random positions that make the code ugly.
Thanks,
Ingo
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-05-06 01:10 +0200 |
| Subject | [PATCH 03/10] x86, perf: Add Top Down events to Intel Core |
| Message-ID | <rvAz8-1bh-33@gated-at.bofh.it> |
| In reply to | #1395460 |
From: Andi Kleen <ak@linux.intel.com>
Add declarations for the events needed for TopDown to the
Intel big core CPUs starting with Sandy Bridge. We need
to report different values if HyperThreading is on or off.
The only thing this patch does is to export some events
in sysfs.
TopDown level 1 uses a set of abstracted metrics which
are generic to out of order CPU cores (although some
CPUs may not implement all of them):
topdown-total-slots Available slots in the pipeline
topdown-slots-issued Slots issued into the pipeline
topdown-slots-retired Slots successfully retired
topdown-fetch-bubbles Pipeline gaps in the frontend
topdown-recovery-bubbles Pipeline gaps during recovery
from misspeculation
A slot is a single operation in the CPU pipe line.
These metrics then allow to compute four useful metrics:
FrontendBound, BackendBound, Retiring, BadSpeculation.
The formulas to compute the metrics are generic, they
only change based on the availability on the abstracted
input values.
The kernel declares the events supported by the current
CPU and their scaling factors (such as the pipeline width)
and perf stat then computes the formulas based on the
available metrics. This is similar how existing
perf metrics, such as TSC metrics or IPC, are implemented.
This abstracts all CPU pipe line specific knowledge in the
kernel driver, but still avoids the need for larger scale perf
interface changes.
For HyperThreading the any bit is needed to get accurate
values when both threads are executing. This implies that
the events can only be collected as root or with
perf_event_paranoid=-1 for now.
The basic scheme is based on the following paper:
Yasin,
A Top Down Method for Performance analysis and Counter architecture
ISPASS14
(pdf available via google)
v2: Rework scaling. Fix formulas for HyperThreading.
v3: Rename agg-per-core to aggr-per-core
Always set aggr-per-core to one to get same output for HT off.
v4: Separate between forced and advisory aggr-per-core
v5: Remove .aggr-per-core attributes
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/events/intel/core.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index cd319400dc10..8b146007c264 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -230,9 +230,46 @@ struct attribute *nhm_events_attrs[] = {
NULL,
};
+/*
+ * TopDown events for Core.
+ *
+ * The events are all in slots, which is a free slot in a 4 wide
+ * pipeline. Some events are already reported in slots, for cycle
+ * events we multiply by the pipeline width (4).
+ *
+ * With Hyper Threading on, TopDown metrics are either summed or averaged
+ * between the threads of a core: (count_t0 + count_t1).
+ *
+ * For the average case the metric is always scaled to pipeline width,
+ * so we use factor 2 ((count_t0 + count_t1) / 2 * 4)
+ */
+
+EVENT_ATTR_STR_HT(topdown-total-slots, td_total_slots,
+ "event=0x3c,umask=0x0", /* cpu_clk_unhalted.thread */
+ "event=0x3c,umask=0x0,any=1"); /* cpu_clk_unhalted.thread_any */
+EVENT_ATTR_STR_HT(topdown-total-slots.scale, td_total_slots_scale, "4", "2");
+EVENT_ATTR_STR(topdown-slots-issued, td_slots_issued,
+ "event=0xe,umask=0x1"); /* uops_issued.any */
+EVENT_ATTR_STR(topdown-slots-retired, td_slots_retired,
+ "event=0xc2,umask=0x2"); /* uops_retired.retire_slots */
+EVENT_ATTR_STR(topdown-fetch-bubbles, td_fetch_bubbles,
+ "event=0x9c,umask=0x1"); /* idq_uops_not_delivered_core */
+EVENT_ATTR_STR_HT(topdown-recovery-bubbles, td_recovery_bubbles,
+ "event=0xd,umask=0x3,cmask=1", /* int_misc.recovery_cycles */
+ "event=0xd,umask=0x3,cmask=1,any=1"); /* int_misc.recovery_cycles_any */
+EVENT_ATTR_STR_HT(topdown-recovery-bubbles.scale, td_recovery_bubbles_scale,
+ "4", "2");
+
struct attribute *snb_events_attrs[] = {
EVENT_PTR(mem_ld_snb),
EVENT_PTR(mem_st_snb),
+ EVENT_PTR(td_slots_issued),
+ EVENT_PTR(td_slots_retired),
+ EVENT_PTR(td_fetch_bubbles),
+ EVENT_PTR(td_total_slots),
+ EVENT_PTR(td_total_slots_scale),
+ EVENT_PTR(td_recovery_bubbles),
+ EVENT_PTR(td_recovery_bubbles_scale),
NULL,
};
@@ -3437,6 +3474,13 @@ static struct attribute *hsw_events_attrs[] = {
EVENT_PTR(cycles_ct),
EVENT_PTR(mem_ld_hsw),
EVENT_PTR(mem_st_hsw),
+ EVENT_PTR(td_slots_issued),
+ EVENT_PTR(td_slots_retired),
+ EVENT_PTR(td_fetch_bubbles),
+ EVENT_PTR(td_total_slots),
+ EVENT_PTR(td_total_slots_scale),
+ EVENT_PTR(td_recovery_bubbles),
+ EVENT_PTR(td_recovery_bubbles_scale),
NULL
};
@@ -3805,6 +3849,12 @@ __init int intel_pmu_init(void)
memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
intel_pmu_lbr_init_skl();
+ /* INT_MISC.RECOVERY_CYCLES has umask 1 in Skylake */
+ event_attr_td_recovery_bubbles.event_str_noht =
+ "event=0xd,umask=0x1,cmask=1";
+ event_attr_td_recovery_bubbles.event_str_ht =
+ "event=0xd,umask=0x1,cmask=1,any=1";
+
x86_pmu.event_constraints = intel_skl_event_constraints;
x86_pmu.pebs_constraints = intel_skl_pebs_event_constraints;
x86_pmu.extra_regs = intel_skl_extra_regs;
--
2.5.5
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web