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


Groups > linux.kernel > #1695284 > unrolled thread

Support standalone metrics and metric groups for perf

Started byAndi Kleen <andi@firstfloor.org>
First post2017-07-25 01:50 +0200
Last post2017-07-28 10:50 +0200
Articles 8 — 2 participants

Back to article view | Back to linux.kernel


Contents

  Support standalone metrics and metric groups for perf Andi Kleen <andi@firstfloor.org> - 2017-07-25 01:50 +0200
    [PATCH v1 11/15] perf, tools, stat: Factor out generic metric printing Andi Kleen <andi@firstfloor.org> - 2017-07-25 01:50 +0200
    [PATCH v1 03/15] perf, tools, stat: Fix saved values rbtree lookup Andi Kleen <andi@firstfloor.org> - 2017-07-25 01:50 +0200
    [PATCH v1 15/15] perf, tools: Support duration_time Andi Kleen <andi@firstfloor.org> - 2017-07-25 01:50 +0200
    [PATCH v1 01/15] perf, tools, stat: Fix buffer overflow while freeing events Andi Kleen <andi@firstfloor.org> - 2017-07-25 01:50 +0200
    Re: Support standalone metrics and metric groups for perf Jiri Olsa <jolsa@redhat.com> - 2017-07-26 16:20 +0200
      Re: Support standalone metrics and metric groups for perf Andi Kleen <andi@firstfloor.org> - 2017-07-26 17:40 +0200
        Re: Support standalone metrics and metric groups for perf Jiri Olsa <jolsa@redhat.com> - 2017-07-28 10:50 +0200

#1695284 — Support standalone metrics and metric groups for perf

FromAndi Kleen <andi@firstfloor.org>
Date2017-07-25 01:50 +0200
SubjectSupport standalone metrics and metric groups for perf
Message-ID<u6VgR-3zh-3@gated-at.bofh.it>
Add generic support for standalone metrics specified in JSON files
to perf stat. A metric is a formula that uses multiple events
to compute a higher level result (e.g. IPC). 

For more complex metrics we need to have micro architecture
specific knowledge, so it makes sense to tie metrics to
JSON event lists.
    
Previously metrics were always tied to an event and automatically
enabled with that event. But now change it that we can have
standalone metrics. They are in the same JSON data structure
as events, but don't have an event name, only a metric name.
    
We also allow to organize the metrics in metric groups, which
allows a short cut to select several related metrics at once.

This patch kit adds the code to perf to manage metric groups

The first few patches are generic bug fixes and can be applied
directly. Then there is a 'weak group' feature that is useful
independently from metrics. After there are metrics specific
patches.

The patches are available in

   git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git perf/metric-group-4

The actual Intel JSON metrics are available in git as a separate pull
request in 

   git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git perf/intel-json-metrics-2

Some example output:

   % perf list metricgroup
    ..
    Metric Groups:
    
    DSB:
      DSB_Coverage
            [Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)]
    FLOPS:
      GFLOPs
            [Giga Floating Point Operations Per Second]
    Frontend:
      IFetch_Line_Utilization
            [Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions]
    Frontend_Bandwidth:
      DSB_Coverage
            [Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)]
    Memory_BW:
      MLP
            [Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)]

   % perf stat -M Summary --metric-only -a sleep 1
    
     Performance counter stats for 'system wide':
    
    Instructions                              CLKS                 CPU_Utilization      GFLOPs               SMT_2T_Utilization   Kernel_Utilization
    317614222.0                              1392930775.0             0.0                 0.0                 0.2                 0.1
    
           1.001497549 seconds time elapsed
    
   % perf stat -M GFLOPs flops
    
     Performance counter stats for 'flops':
    
         3,999,541,471      fp_comp_ops_exe.sse_scalar_single #      1.2 GFLOPs                   (66.65%)
                    14      fp_comp_ops_exe.sse_scalar_double                                     (66.65%)
                     0      fp_comp_ops_exe.sse_packed_double                                     (66.67%)
                     0      fp_comp_ops_exe.sse_packed_single                                     (66.70%)
                     0      simd_fp_256.packed_double                                     (66.70%)
                     0      simd_fp_256.packed_single                                     (66.67%)
                     0      duration_time
    
           3.238372845 seconds time elapsed

v1: Initial post

[toc] | [next] | [standalone]


#1695285 — [PATCH v1 11/15] perf, tools, stat: Factor out generic metric printing

FromAndi Kleen <andi@firstfloor.org>
Date2017-07-25 01:50 +0200
Subject[PATCH v1 11/15] perf, tools, stat: Factor out generic metric printing
Message-ID<u6VgT-3zh-39@gated-at.bofh.it>
In reply to#1695284
From: Andi Kleen <ak@linux.intel.com>

The perf stat shadow metric printing already supports generic metrics.
Factor out the code doing that into a separate function that can be re-used
in a later patch.

No behavior changes.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/util/stat-shadow.c | 69 ++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 27 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index a04cf56d3517..b6cbb6e67167 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -627,6 +627,46 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
 	out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num);
 }
 
+static void generic_metric(const char *metric_expr,
+			   struct perf_evsel **metric_events,
+			   char *name,
+			   const char *metric_name,
+			   double avg,
+			   int cpu,
+			   int ctx,
+			   struct perf_stat_output_ctx *out)
+{
+	print_metric_t print_metric = out->print_metric;
+	struct parse_ctx pctx;
+	double ratio;
+	int i;
+	void *ctxp = out->ctx;
+
+	expr__ctx_init(&pctx);
+	expr__add_id(&pctx, name, avg);
+	for (i = 0; metric_events[i]; i++) {
+		struct saved_value *v;
+
+		v = saved_value_lookup(metric_events[i], cpu, ctx, false);
+		if (!v)
+			break;
+		expr__add_id(&pctx, metric_events[i]->name, avg_stats(&v->stats));
+	}
+	if (!metric_events[i]) {
+		const char *p = metric_expr;
+
+		if (expr__parse(&ratio, &pctx, &p) == 0)
+			print_metric(ctxp, NULL, "%8.1f",
+				metric_name ?
+				metric_name :
+			out->force_header ?  name : "",
+				ratio);
+		else
+			print_metric(ctxp, NULL, NULL, "", 0);
+	} else
+		print_metric(ctxp, NULL, NULL, "", 0);
+}
+
 void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 				   double avg, int cpu,
 				   struct perf_stat_output_ctx *out)
@@ -819,33 +859,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		else
 			print_metric(ctxp, NULL, NULL, name, 0);
 	} else if (evsel->metric_expr) {
-		struct parse_ctx pctx;
-		int i;
-
-		expr__ctx_init(&pctx);
-		expr__add_id(&pctx, evsel->name, avg);
-		for (i = 0; evsel->metric_events[i]; i++) {
-			struct saved_value *v;
-
-			v = saved_value_lookup(evsel->metric_events[i], cpu, ctx, false);
-			if (!v)
-				break;
-			expr__add_id(&pctx, evsel->metric_events[i]->name,
-					     avg_stats(&v->stats));
-		}
-		if (!evsel->metric_events[i]) {
-			const char *p = evsel->metric_expr;
-
-			if (expr__parse(&ratio, &pctx, &p) == 0)
-				print_metric(ctxp, NULL, "%8.1f",
-					evsel->metric_name ?
-					evsel->metric_name :
-					out->force_header ?  evsel->name : "",
-					ratio);
-			else
-				print_metric(ctxp, NULL, NULL, "", 0);
-		} else
-			print_metric(ctxp, NULL, NULL, "", 0);
+		generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name,
+				evsel->metric_name, avg, cpu, ctx, out);
 	} else if (runtime_nsecs_stats[cpu].n != 0) {
 		char unit = 'M';
 		char unit_buf[10];
-- 
2.9.4

[toc] | [prev] | [next] | [standalone]


#1695286 — [PATCH v1 03/15] perf, tools, stat: Fix saved values rbtree lookup

FromAndi Kleen <andi@firstfloor.org>
Date2017-07-25 01:50 +0200
Subject[PATCH v1 03/15] perf, tools, stat: Fix saved values rbtree lookup
Message-ID<u6VgT-3zh-43@gated-at.bofh.it>
In reply to#1695284
From: Andi Kleen <ak@linux.intel.com>

The stat shadow saved values rbtree is indexed by a pointer.
Fix the comparison function:

- We cannot return a pointer delta as an int because
that loses bits on 64bit.
- Doing pointer arithmetic on the struct pointer
only works if the objects are spaced by the multiple
of the object size, which is not guaranteed for individual
malloc'ed object

Replace it with a proper comparison.

This fixes various problems with values not being found.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/util/stat-shadow.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 719d6cb86952..a04cf56d3517 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -70,7 +70,11 @@ static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
 		return a->ctx - b->ctx;
 	if (a->cpu != b->cpu)
 		return a->cpu - b->cpu;
-	return a->evsel - b->evsel;
+	if (a->evsel == b->evsel)
+		return 0;
+	if ((char *)a->evsel < (char *)b->evsel)
+		return -1;
+	return +1;
 }
 
 static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused,
-- 
2.9.4

[toc] | [prev] | [next] | [standalone]


#1695287 — [PATCH v1 15/15] perf, tools: Support duration_time

FromAndi Kleen <andi@firstfloor.org>
Date2017-07-25 01:50 +0200
Subject[PATCH v1 15/15] perf, tools: Support duration_time
Message-ID<u6VgT-3zh-45@gated-at.bofh.it>
In reply to#1695284
From: Andi Kleen <ak@linux.intel.com>

Some of the metrics formulas (like GFLOPs) need to know how long
the measurement period is. Support an internal event called duration_time, which
reports time in second. It maps to the dummy event, but is
special cased for statistics to report the walltime duration.

So far it is not printed, but only used internally for metrics.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/util/parse-events.l |  1 +
 tools/perf/util/stat-shadow.c  | 17 +++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 07ee5bb3a8b0..f7bc74f8a615 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -277,6 +277,7 @@ cpu-migrations|migrations			{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU
 alignment-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
 emulation-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
 dummy						{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
+duration_time					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
 bpf-output					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
 
 	/*
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 122f37b38a65..34ae2960730b 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -641,11 +641,20 @@ static void generic_metric(const char *metric_expr,
 	expr__add_id(&pctx, name, avg);
 	for (i = 0; metric_events[i]; i++) {
 		struct saved_value *v;
+		struct stats *stats;
+		double scale;
 
-		v = saved_value_lookup(metric_events[i], cpu, false);
-		if (!v)
-			break;
-		expr__add_id(&pctx, metric_events[i]->name, avg_stats(&v->stats));
+		if (!strcmp(metric_events[i]->name, "duration_time")) {
+			stats = &walltime_nsecs_stats;
+			scale = 1e-9;
+		} else {
+			v = saved_value_lookup(metric_events[i], cpu, false);
+			if (!v)
+				break;
+			stats = &v->stats;
+			scale = 1.0;
+		}
+		expr__add_id(&pctx, metric_events[i]->name, avg_stats(stats)*scale);
 	}
 	if (!metric_events[i]) {
 		const char *p = metric_expr;
-- 
2.9.4

[toc] | [prev] | [next] | [standalone]


#1695288 — [PATCH v1 01/15] perf, tools, stat: Fix buffer overflow while freeing events

FromAndi Kleen <andi@firstfloor.org>
Date2017-07-25 01:50 +0200
Subject[PATCH v1 01/15] perf, tools, stat: Fix buffer overflow while freeing events
Message-ID<u6VgT-3zh-41@gated-at.bofh.it>
In reply to#1695284
From: Andi Kleen <ak@linux.intel.com>

Fix buffer overflow for

% perf stat -e msr/tsc/,cstate_core/c7-residency/ true

that causes glibc free list corruption. For some reason
it doesn't trigger in valgrind, but it is visible in AS:

=================================================================
==32681==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000003f5c at pc 0x0000005671ef bp 0x7ffdaaac9ac0 sp 0x7ffdaaac9ab0
READ of size 4 at 0x603000003f5c thread T0
    #0 0x5671ee in perf_evsel__close_fd util/evsel.c:1196
    #1 0x56c57a in perf_evsel__close util/evsel.c:1717
    #2 0x55ed5f in perf_evlist__close util/evlist.c:1631
    #3 0x4647e1 in __run_perf_stat /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:749
    #4 0x4648e3 in run_perf_stat /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:767
    #5 0x46e1bc in cmd_stat /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:2785
    #6 0x52f83d in run_builtin /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:296
    #7 0x52fd49 in handle_internal_command /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:348
    #8 0x5300de in run_argv /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:392
    #9 0x5308f3 in main /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:530
    #10 0x7f0672d13400 in __libc_start_main (/lib64/libc.so.6+0x20400)
    #11 0x428419 in _start (/home/ak/hle/obj-perf/perf+0x428419)

0x603000003f5c is located 0 bytes to the right of 28-byte region [0x603000003f40,0x603000003f5c)
allocated by thread T0 here:
    #0 0x7f0675139020 in calloc (/lib64/libasan.so.3+0xc7020)
    #1 0x648a2d in zalloc util/util.h:23
    #2 0x648a88 in xyarray__new util/xyarray.c:9
    #3 0x566419 in perf_evsel__alloc_fd util/evsel.c:1039
    #4 0x56b427 in perf_evsel__open util/evsel.c:1529
    #5 0x56c620 in perf_evsel__open_per_thread util/evsel.c:1730
    #6 0x461dea in create_perf_stat_counter /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:263
    #7 0x4637d7 in __run_perf_stat /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:600
    #8 0x4648e3 in run_perf_stat /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:767
    #9 0x46e1bc in cmd_stat /home/ak/hle/linux-hle-2.6/tools/perf/builtin-stat.c:2785
    #10 0x52f83d in run_builtin /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:296
    #11 0x52fd49 in handle_internal_command /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:348
    #12 0x5300de in run_argv /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:392
    #13 0x5308f3 in main /home/ak/hle/linux-hle-2.6/tools/perf/perf.c:530
    #14 0x7f0672d13400 in __libc_start_main (/lib64/libc.so.6+0x20400)

The event is allocated with cpus == 1, but freed with cpus == real number
When the evsel close function walks the file descriptors it exceeds the
fd xyarray boundaries and reads random memory.

Just make sure to always use the same dummy cpu map following
the same logic as the open call.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/builtin-stat.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48ac53b199fc..97d6b6c42014 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -715,6 +715,8 @@ static int __run_perf_stat(int argc, const char **argv)
 	 * group leaders.
 	 */
 	read_counters();
+	if (!target__has_cpu(&target))
+		evsel_list->cpus = cpu_map__dummy_new();
 	perf_evlist__close(evsel_list);
 
 	return WEXITSTATUS(status);
-- 
2.9.4

[toc] | [prev] | [next] | [standalone]


#1697155

FromJiri Olsa <jolsa@redhat.com>
Date2017-07-26 16:20 +0200
Message-ID<u7vko-1ob-45@gated-at.bofh.it>
In reply to#1695284
On Mon, Jul 24, 2017 at 04:40:00PM -0700, Andi Kleen wrote:
> Add generic support for standalone metrics specified in JSON files
> to perf stat. A metric is a formula that uses multiple events
> to compute a higher level result (e.g. IPC). 
> 
> For more complex metrics we need to have micro architecture
> specific knowledge, so it makes sense to tie metrics to
> JSON event lists.
>     
> Previously metrics were always tied to an event and automatically
> enabled with that event. But now change it that we can have
> standalone metrics. They are in the same JSON data structure
> as events, but don't have an event name, only a metric name.
>     
> We also allow to organize the metrics in metric groups, which
> allows a short cut to select several related metrics at once.
> 
> This patch kit adds the code to perf to manage metric groups
> 
> The first few patches are generic bug fixes and can be applied
> directly. Then there is a 'weak group' feature that is useful
> independently from metrics. After there are metrics specific
> patches.
> 
> The patches are available in
> 
>    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git perf/metric-group-4
> 
> The actual Intel JSON metrics are available in git as a separate pull
> request in 
> 
>    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git perf/intel-json-metrics-2

hi,
looks like it's not pushed out?

[jolsa@krava perf]$ git remote -v | grep andi
andi    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git (fetch)
andi    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git (push)
[jolsa@krava perf]$ git remote update andi
Fetching andi
[jolsa@krava perf]$ git branch -r | grep metric-group
[jolsa@krava perf]$ git branch -r | grep intel-json-metrics-2
[jolsa@krava perf]$ 


thanks,
jirka

[toc] | [prev] | [next] | [standalone]


#1697314

FromAndi Kleen <andi@firstfloor.org>
Date2017-07-26 17:40 +0200
Message-ID<u7wzM-26U-19@gated-at.bofh.it>
In reply to#1697155
> [jolsa@krava perf]$ git remote -v | grep andi
> andi    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git (fetch)
> andi    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git (push)
> [jolsa@krava perf]$ git remote update andi
> Fetching andi
> [jolsa@krava perf]$ git branch -r | grep metric-group
> [jolsa@krava perf]$ git branch -r | grep intel-json-metrics-2
> [jolsa@krava perf]$ 

Pushed now.

-Andi

[toc] | [prev] | [next] | [standalone]


#1698597

FromJiri Olsa <jolsa@redhat.com>
Date2017-07-28 10:50 +0200
Message-ID<u8986-1mx-17@gated-at.bofh.it>
In reply to#1697314
On Wed, Jul 26, 2017 at 08:38:41AM -0700, Andi Kleen wrote:
> > [jolsa@krava perf]$ git remote -v | grep andi
> > andi    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git (fetch)
> > andi    git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc.git (push)
> > [jolsa@krava perf]$ git remote update andi
> > Fetching andi
> > [jolsa@krava perf]$ git branch -r | grep metric-group
> > [jolsa@krava perf]$ git branch -r | grep intel-json-metrics-2
> > [jolsa@krava perf]$ 
> 
> Pushed now.

  CC       util/metricgroup.o
util/metricgroup.c: In function ‘metricgroup__print’:
util/metricgroup.c:347:6: error: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Werror=unused-result]
      asprintf(&s, "%s\n\t[%s]",
      ^~~~~~~~~~~~~~~~~~~~~~~~~~
        pe->metric_name, pe->desc);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors


jirka

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web