253 lines
7.2 KiB
Diff
253 lines
7.2 KiB
Diff
From a19b089ceb882c3e227f45080a2047c2b1744acd Mon Sep 17 00:00:00 2001
|
|
From: Jiri Olsa <jolsa@kernel.org>
|
|
Date: Wed, 3 Jun 2020 12:51:15 -0300
|
|
Subject: [PATCH 095/201] perf tests: Add another metric parsing test
|
|
|
|
mainline inclusion
|
|
from mainline-v5.9-rc1
|
|
commit e1c92a7fbbc5668510736624df3028accd6af0ea
|
|
category: feature
|
|
bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e1c92a7fbbc5668510736624df3028accd6af0ea
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
The test goes through all metrics compiled for arch within pmu events
|
|
and try to parse them.
|
|
|
|
This test is different from 'test_parsing' in that we go through all the
|
|
events in the current arch, not just one defined for current CPU model.
|
|
Using 'fake_pmu' to parse events which do not have PMUs defined in the
|
|
system.
|
|
|
|
Say there's bad change in ivybridge metrics file, like:
|
|
|
|
- a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
|
|
+ b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
|
|
@@ -8,7 +8,7 @@
|
|
- "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ((
|
|
+ "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / / (4 *
|
|
|
|
the test fails with (on my kabylake laptop):
|
|
|
|
$ perf test 'Parsing of PMU event table metrics with fake PMUs' -v
|
|
parsing 'idq_uops_not_delivered.core / / (4 * (( ( cpu_clk_unh...
|
|
syntax error, line 1
|
|
expr__parse failed
|
|
test child finished with -1
|
|
...
|
|
|
|
The test also defines its own list of metrics and tries to parse them.
|
|
It's handy for developing.
|
|
|
|
Committer notes:
|
|
|
|
Testing it:
|
|
|
|
$ perf test fake
|
|
10: PMU events :
|
|
10.4: Parsing of PMU event table metrics with fake PMUs : FAILED!
|
|
$ perf test -v fake |& tail
|
|
parsing '(unc_p_freq_trans_cycles / unc_p_clockticks) * 100.'
|
|
parsing '(unc_m_power_channel_ppd / unc_m_clockticks) * 100.'
|
|
parsing '(unc_m_power_critical_throttle_cycles / unc_m_clockticks) * 100.'
|
|
parsing '(unc_m_power_self_refresh / unc_m_clockticks) * 100.'
|
|
parsing 'idq_uops_not_delivered.core / * (4 * cycles)'
|
|
syntax error
|
|
expr__parse failed
|
|
test child finished with -1
|
|
---- end ----
|
|
PMU events subtest 4: FAILED!
|
|
$
|
|
|
|
And fix this error:
|
|
|
|
tests/pmu-events.c:437:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers]
|
|
struct parse_events_error error = { 0 };
|
|
|
|
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
|
|
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
|
Cc: Andi Kleen <ak@linux.intel.com>
|
|
Cc: Ian Rogers <irogers@google.com>
|
|
Cc: Ingo Molnar <mingo@kernel.org>
|
|
Cc: Michael Petlan <mpetlan@redhat.com>
|
|
Cc: Namhyung Kim <namhyung@kernel.org>
|
|
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
|
Cc: Stephane Eranian <eranian@google.com>
|
|
Link: http://lore.kernel.org/lkml/20200602214741.1218986-5-jolsa@kernel.org
|
|
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
|
|
|
|
Conflicts:
|
|
tools/perf/tests/pmu-events.c
|
|
---
|
|
tools/perf/tests/pmu-events.c | 115 +++++++++++++++++++++++++++++++++-
|
|
1 file changed, 112 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
|
|
index 7269bdeeda2c..0a6611d8ec32 100644
|
|
--- a/tools/perf/tests/pmu-events.c
|
|
+++ b/tools/perf/tests/pmu-events.c
|
|
@@ -390,7 +390,8 @@ static bool is_number(const char *str)
|
|
return errno == 0 && end_ptr != str;
|
|
}
|
|
|
|
-static int check_parse_id(const char *id, struct parse_events_error *error)
|
|
+static int check_parse_id(const char *id, struct parse_events_error *error,
|
|
+ struct perf_pmu *fake_pmu)
|
|
{
|
|
struct perf_evlist *evlist;
|
|
int ret;
|
|
@@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error)
|
|
evlist = perf_evlist__new();
|
|
if (!evlist)
|
|
return -ENOMEM;
|
|
- ret = parse_events(evlist, id, error);
|
|
+ ret = __parse_events(evlist, id, error, fake_pmu);
|
|
perf_evlist__delete(evlist);
|
|
return ret;
|
|
}
|
|
@@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe)
|
|
{
|
|
struct parse_events_error error = { .idx = 0, };
|
|
|
|
- int ret = check_parse_id(id, &error);
|
|
+ int ret = check_parse_id(id, &error, NULL);
|
|
if (ret && same_cpu) {
|
|
pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n",
|
|
pe->metric_name, id, pe->metric_expr);
|
|
@@ -427,6 +428,16 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe)
|
|
return ret;
|
|
}
|
|
|
|
+static int check_parse_fake(const char *id)
|
|
+{
|
|
+ struct parse_events_error error = { .idx = 0, };
|
|
+ int ret = check_parse_id(id, &error, &perf_pmu__fake);
|
|
+
|
|
+ free(error.str);
|
|
+ free(error.help);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static void expr_failure(const char *msg,
|
|
const struct pmu_events_map *map,
|
|
const struct pmu_event *pe)
|
|
@@ -496,6 +507,100 @@ static int test_parsing(void)
|
|
return ret == 0 ? TEST_OK : TEST_SKIP;
|
|
}
|
|
|
|
+struct test_metric {
|
|
+ const char *str;
|
|
+};
|
|
+
|
|
+static struct test_metric metrics[] = {
|
|
+ { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." },
|
|
+ { "imx8_ddr0@read\\-cycles@ * 4 * 4", },
|
|
+ { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", },
|
|
+ { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", },
|
|
+ { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", },
|
|
+};
|
|
+
|
|
+static int metric_parse_fake(const char *str)
|
|
+{
|
|
+ struct expr_parse_ctx ctx;
|
|
+ struct hashmap_entry *cur;
|
|
+ double result;
|
|
+ int ret = -1;
|
|
+ size_t bkt;
|
|
+ int i;
|
|
+
|
|
+ pr_debug("parsing '%s'\n", str);
|
|
+
|
|
+ expr__ctx_init(&ctx);
|
|
+ if (expr__find_other(str, NULL, &ctx, 0) < 0) {
|
|
+ pr_err("expr__find_other failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Add all ids with a made up value. The value may
|
|
+ * trigger divide by zero when subtracted and so try to
|
|
+ * make them unique.
|
|
+ */
|
|
+ i = 1;
|
|
+ hashmap__for_each_entry((&ctx.ids), cur, bkt)
|
|
+ expr__add_id(&ctx, strdup(cur->key), i++);
|
|
+
|
|
+ hashmap__for_each_entry((&ctx.ids), cur, bkt) {
|
|
+ if (check_parse_fake(cur->key)) {
|
|
+ pr_err("check_parse_fake failed\n");
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (expr__parse(&result, &ctx, str, 1))
|
|
+ pr_err("expr__parse failed\n");
|
|
+ else
|
|
+ ret = 0;
|
|
+
|
|
+out:
|
|
+ expr__ctx_clear(&ctx);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Parse all the metrics for current architecture,
|
|
+ * or all defined cpus via the 'fake_pmu'
|
|
+ * in parse_events.
|
|
+ */
|
|
+static int test_parsing_fake(void)
|
|
+{
|
|
+ struct pmu_events_map *map;
|
|
+ struct pmu_event *pe;
|
|
+ unsigned int i, j;
|
|
+ int err = 0;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(metrics); i++) {
|
|
+ err = metric_parse_fake(metrics[i].str);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ i = 0;
|
|
+ for (;;) {
|
|
+ map = &pmu_events_map[i++];
|
|
+ if (!map->table)
|
|
+ break;
|
|
+ j = 0;
|
|
+ for (;;) {
|
|
+ pe = &map->table[j++];
|
|
+ if (!pe->name && !pe->metric_group && !pe->metric_name)
|
|
+ break;
|
|
+ if (!pe->metric_expr)
|
|
+ continue;
|
|
+ err = metric_parse_fake(pe->metric_expr);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct {
|
|
int (*func)(void);
|
|
const char *desc;
|
|
@@ -512,6 +617,10 @@ static const struct {
|
|
.func = test_parsing,
|
|
.desc = "Parsing of PMU event table metrics",
|
|
},
|
|
+ {
|
|
+ .func = test_parsing_fake,
|
|
+ .desc = "Parsing of PMU event table metrics with fake PMUs",
|
|
+ },
|
|
};
|
|
|
|
const char *test__pmu_events_subtest_get_desc(int subtest)
|
|
--
|
|
2.27.0
|
|
|