Skip to content

Commit e1c92a7

Browse files
olsajiriacmel
authored andcommitted
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 <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Michael Petlan <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Link: http://lore.kernel.org/lkml/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent e46fc8d commit e1c92a7

File tree

1 file changed

+114
-3
lines changed

1 file changed

+114
-3
lines changed

tools/perf/tests/pmu-events.c

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ static bool is_number(const char *str)
390390
return errno == 0 && end_ptr != str;
391391
}
392392

393-
static int check_parse_id(const char *id, struct parse_events_error *error)
393+
static int check_parse_id(const char *id, struct parse_events_error *error,
394+
struct perf_pmu *fake_pmu)
394395
{
395396
struct evlist *evlist;
396397
int ret;
@@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error)
402403
evlist = evlist__new();
403404
if (!evlist)
404405
return -ENOMEM;
405-
ret = parse_events(evlist, id, error);
406+
ret = __parse_events(evlist, id, error, fake_pmu);
406407
evlist__delete(evlist);
407408
return ret;
408409
}
@@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe)
411412
{
412413
struct parse_events_error error = { .idx = 0, };
413414

414-
int ret = check_parse_id(id, &error);
415+
int ret = check_parse_id(id, &error, NULL);
415416
if (ret && same_cpu) {
416417
pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n",
417418
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)
429430
return ret;
430431
}
431432

433+
static int check_parse_fake(const char *id)
434+
{
435+
struct parse_events_error error = { .idx = 0, };
436+
int ret = check_parse_id(id, &error, &perf_pmu__fake);
437+
438+
free(error.str);
439+
free(error.help);
440+
free(error.first_str);
441+
free(error.first_help);
442+
return ret;
443+
}
444+
432445
static void expr_failure(const char *msg,
433446
const struct pmu_events_map *map,
434447
const struct pmu_event *pe)
@@ -498,6 +511,100 @@ static int test_parsing(void)
498511
return ret == 0 ? TEST_OK : TEST_SKIP;
499512
}
500513

514+
struct test_metric {
515+
const char *str;
516+
};
517+
518+
static struct test_metric metrics[] = {
519+
{ "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." },
520+
{ "imx8_ddr0@read\\-cycles@ * 4 * 4", },
521+
{ "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", },
522+
{ "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", },
523+
{ "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", },
524+
};
525+
526+
static int metric_parse_fake(const char *str)
527+
{
528+
struct expr_parse_ctx ctx;
529+
struct hashmap_entry *cur;
530+
double result;
531+
int ret = -1;
532+
size_t bkt;
533+
int i;
534+
535+
pr_debug("parsing '%s'\n", str);
536+
537+
expr__ctx_init(&ctx);
538+
if (expr__find_other(str, NULL, &ctx, 0) < 0) {
539+
pr_err("expr__find_other failed\n");
540+
return -1;
541+
}
542+
543+
/*
544+
* Add all ids with a made up value. The value may
545+
* trigger divide by zero when subtracted and so try to
546+
* make them unique.
547+
*/
548+
i = 1;
549+
hashmap__for_each_entry((&ctx.ids), cur, bkt)
550+
expr__add_id(&ctx, strdup(cur->key), i++);
551+
552+
hashmap__for_each_entry((&ctx.ids), cur, bkt) {
553+
if (check_parse_fake(cur->key)) {
554+
pr_err("check_parse_fake failed\n");
555+
goto out;
556+
}
557+
}
558+
559+
if (expr__parse(&result, &ctx, str, 1))
560+
pr_err("expr__parse failed\n");
561+
else
562+
ret = 0;
563+
564+
out:
565+
expr__ctx_clear(&ctx);
566+
return ret;
567+
}
568+
569+
/*
570+
* Parse all the metrics for current architecture,
571+
* or all defined cpus via the 'fake_pmu'
572+
* in parse_events.
573+
*/
574+
static int test_parsing_fake(void)
575+
{
576+
struct pmu_events_map *map;
577+
struct pmu_event *pe;
578+
unsigned int i, j;
579+
int err = 0;
580+
581+
for (i = 0; i < ARRAY_SIZE(metrics); i++) {
582+
err = metric_parse_fake(metrics[i].str);
583+
if (err)
584+
return err;
585+
}
586+
587+
i = 0;
588+
for (;;) {
589+
map = &pmu_events_map[i++];
590+
if (!map->table)
591+
break;
592+
j = 0;
593+
for (;;) {
594+
pe = &map->table[j++];
595+
if (!pe->name && !pe->metric_group && !pe->metric_name)
596+
break;
597+
if (!pe->metric_expr)
598+
continue;
599+
err = metric_parse_fake(pe->metric_expr);
600+
if (err)
601+
return err;
602+
}
603+
}
604+
605+
return 0;
606+
}
607+
501608
static const struct {
502609
int (*func)(void);
503610
const char *desc;
@@ -514,6 +621,10 @@ static const struct {
514621
.func = test_parsing,
515622
.desc = "Parsing of PMU event table metrics",
516623
},
624+
{
625+
.func = test_parsing_fake,
626+
.desc = "Parsing of PMU event table metrics with fake PMUs",
627+
},
517628
};
518629

519630
const char *test__pmu_events_subtest_get_desc(int subtest)

0 commit comments

Comments
 (0)