mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
perf tests: Add another metric parsing test
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>
This commit is contained in:
parent
e46fc8d9dd
commit
e1c92a7fbb
1 changed files with 114 additions and 3 deletions
|
@ -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 evlist *evlist;
|
||||
int ret;
|
||||
|
@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error)
|
|||
evlist = evlist__new();
|
||||
if (!evlist)
|
||||
return -ENOMEM;
|
||||
ret = parse_events(evlist, id, error);
|
||||
ret = __parse_events(evlist, id, error, fake_pmu);
|
||||
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);
|
||||
|
@ -429,6 +430,18 @@ 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);
|
||||
free(error.first_str);
|
||||
free(error.first_help);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void expr_failure(const char *msg,
|
||||
const struct pmu_events_map *map,
|
||||
const struct pmu_event *pe)
|
||||
|
@ -498,6 +511,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;
|
||||
|
@ -514,6 +621,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)
|
||||
|
|
Loading…
Reference in a new issue