-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf test: Add expand cgroup event test
It'll expand given events for cgroups A, B and C. $ perf test -v expansion 69: Event expansion for cgroups : --- start --- test child forked, pid 983140 metric expr 1 / IPC for CPI metric expr instructions / cycles for IPC found event instructions found event cycles adding {instructions,cycles}:W copying metric event for cgroup 'A': instructions (idx=0) copying metric event for cgroup 'B': instructions (idx=0) copying metric event for cgroup 'C': instructions (idx=0) test child finished with 0 ---- end ---- Event expansion for cgroups: Ok Signed-off-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Jiri Olsa <jolsa@redhat.com> 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: John Garry <john.garry@huawei.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200924124455.336326-6-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
- Loading branch information
Namhyung Kim
authored and
Arnaldo Carvalho de Melo
committed
Sep 28, 2020
1 parent
89fb1ca
commit 40b74c3
Showing
4 changed files
with
247 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
#include "tests.h" | ||
#include "debug.h" | ||
#include "evlist.h" | ||
#include "cgroup.h" | ||
#include "rblist.h" | ||
#include "metricgroup.h" | ||
#include "parse-events.h" | ||
#include "pmu-events/pmu-events.h" | ||
#include "pfm.h" | ||
#include <subcmd/parse-options.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
static int test_expand_events(struct evlist *evlist, | ||
struct rblist *metric_events) | ||
{ | ||
int i, ret = TEST_FAIL; | ||
int nr_events; | ||
bool was_group_event; | ||
int nr_members; /* for the first evsel only */ | ||
const char cgrp_str[] = "A,B,C"; | ||
const char *cgrp_name[] = { "A", "B", "C" }; | ||
int nr_cgrps = ARRAY_SIZE(cgrp_name); | ||
char **ev_name; | ||
struct evsel *evsel; | ||
|
||
TEST_ASSERT_VAL("evlist is empty", !perf_evlist__empty(evlist)); | ||
|
||
nr_events = evlist->core.nr_entries; | ||
ev_name = calloc(nr_events, sizeof(*ev_name)); | ||
if (ev_name == NULL) { | ||
pr_debug("memory allocation failure\n"); | ||
return TEST_FAIL; | ||
} | ||
i = 0; | ||
evlist__for_each_entry(evlist, evsel) { | ||
ev_name[i] = strdup(evsel->name); | ||
if (ev_name[i] == NULL) { | ||
pr_debug("memory allocation failure\n"); | ||
goto out; | ||
} | ||
i++; | ||
} | ||
/* remember grouping info */ | ||
was_group_event = evsel__is_group_event(evlist__first(evlist)); | ||
nr_members = evlist__first(evlist)->core.nr_members; | ||
|
||
ret = evlist__expand_cgroup(evlist, cgrp_str, metric_events, false); | ||
if (ret < 0) { | ||
pr_debug("failed to expand events for cgroups\n"); | ||
goto out; | ||
} | ||
|
||
ret = TEST_FAIL; | ||
if (evlist->core.nr_entries != nr_events * nr_cgrps) { | ||
pr_debug("event count doesn't match\n"); | ||
goto out; | ||
} | ||
|
||
i = 0; | ||
evlist__for_each_entry(evlist, evsel) { | ||
if (strcmp(evsel->name, ev_name[i % nr_events])) { | ||
pr_debug("event name doesn't match:\n"); | ||
pr_debug(" evsel[%d]: %s\n expected: %s\n", | ||
i, evsel->name, ev_name[i % nr_events]); | ||
goto out; | ||
} | ||
if (strcmp(evsel->cgrp->name, cgrp_name[i / nr_events])) { | ||
pr_debug("cgroup name doesn't match:\n"); | ||
pr_debug(" evsel[%d]: %s\n expected: %s\n", | ||
i, evsel->cgrp->name, cgrp_name[i / nr_events]); | ||
goto out; | ||
} | ||
|
||
if ((i % nr_events) == 0) { | ||
if (evsel__is_group_event(evsel) != was_group_event) { | ||
pr_debug("event group doesn't match: got %s, expect %s\n", | ||
evsel__is_group_event(evsel) ? "true" : "false", | ||
was_group_event ? "true" : "false"); | ||
goto out; | ||
} | ||
if (evsel->core.nr_members != nr_members) { | ||
pr_debug("event group member doesn't match: %d vs %d\n", | ||
evsel->core.nr_members, nr_members); | ||
goto out; | ||
} | ||
} | ||
i++; | ||
} | ||
ret = TEST_OK; | ||
|
||
out: for (i = 0; i < nr_events; i++) | ||
free(ev_name[i]); | ||
free(ev_name); | ||
return ret; | ||
} | ||
|
||
static int expand_default_events(void) | ||
{ | ||
int ret; | ||
struct evlist *evlist; | ||
struct rblist metric_events; | ||
|
||
evlist = perf_evlist__new_default(); | ||
TEST_ASSERT_VAL("failed to get evlist", evlist); | ||
|
||
rblist__init(&metric_events); | ||
ret = test_expand_events(evlist, &metric_events); | ||
evlist__delete(evlist); | ||
return ret; | ||
} | ||
|
||
static int expand_group_events(void) | ||
{ | ||
int ret; | ||
struct evlist *evlist; | ||
struct rblist metric_events; | ||
struct parse_events_error err; | ||
const char event_str[] = "{cycles,instructions}"; | ||
|
||
symbol_conf.event_group = true; | ||
|
||
evlist = evlist__new(); | ||
TEST_ASSERT_VAL("failed to get evlist", evlist); | ||
|
||
ret = parse_events(evlist, event_str, &err); | ||
if (ret < 0) { | ||
pr_debug("failed to parse event '%s', err %d, str '%s'\n", | ||
event_str, ret, err.str); | ||
parse_events_print_error(&err, event_str); | ||
goto out; | ||
} | ||
|
||
rblist__init(&metric_events); | ||
ret = test_expand_events(evlist, &metric_events); | ||
out: | ||
evlist__delete(evlist); | ||
return ret; | ||
} | ||
|
||
static int expand_libpfm_events(void) | ||
{ | ||
int ret; | ||
struct evlist *evlist; | ||
struct rblist metric_events; | ||
const char event_str[] = "UNHALTED_CORE_CYCLES"; | ||
struct option opt = { | ||
.value = &evlist, | ||
}; | ||
|
||
symbol_conf.event_group = true; | ||
|
||
evlist = evlist__new(); | ||
TEST_ASSERT_VAL("failed to get evlist", evlist); | ||
|
||
ret = parse_libpfm_events_option(&opt, event_str, 0); | ||
if (ret < 0) { | ||
pr_debug("failed to parse libpfm event '%s', err %d\n", | ||
event_str, ret); | ||
goto out; | ||
} | ||
if (perf_evlist__empty(evlist)) { | ||
pr_debug("libpfm was not enabled\n"); | ||
goto out; | ||
} | ||
|
||
rblist__init(&metric_events); | ||
ret = test_expand_events(evlist, &metric_events); | ||
out: | ||
evlist__delete(evlist); | ||
return ret; | ||
} | ||
|
||
static int expand_metric_events(void) | ||
{ | ||
int ret; | ||
struct evlist *evlist; | ||
struct rblist metric_events; | ||
const char metric_str[] = "CPI"; | ||
|
||
struct pmu_event pme_test[] = { | ||
{ | ||
.metric_expr = "instructions / cycles", | ||
.metric_name = "IPC", | ||
}, | ||
{ | ||
.metric_expr = "1 / IPC", | ||
.metric_name = "CPI", | ||
}, | ||
{ | ||
.metric_expr = NULL, | ||
.metric_name = NULL, | ||
}, | ||
}; | ||
struct pmu_events_map ev_map = { | ||
.cpuid = "test", | ||
.version = "1", | ||
.type = "core", | ||
.table = pme_test, | ||
}; | ||
|
||
evlist = evlist__new(); | ||
TEST_ASSERT_VAL("failed to get evlist", evlist); | ||
|
||
rblist__init(&metric_events); | ||
ret = metricgroup__parse_groups_test(evlist, &ev_map, metric_str, | ||
false, false, &metric_events); | ||
if (ret < 0) { | ||
pr_debug("failed to parse '%s' metric\n", metric_str); | ||
goto out; | ||
} | ||
|
||
ret = test_expand_events(evlist, &metric_events); | ||
|
||
out: | ||
metricgroup__rblist_exit(&metric_events); | ||
evlist__delete(evlist); | ||
return ret; | ||
} | ||
|
||
int test__expand_cgroup_events(struct test *test __maybe_unused, | ||
int subtest __maybe_unused) | ||
{ | ||
int ret; | ||
|
||
ret = expand_default_events(); | ||
TEST_ASSERT_EQUAL("failed to expand default events", ret, 0); | ||
|
||
ret = expand_group_events(); | ||
TEST_ASSERT_EQUAL("failed to expand event group", ret, 0); | ||
|
||
ret = expand_libpfm_events(); | ||
TEST_ASSERT_EQUAL("failed to expand event group", ret, 0); | ||
|
||
ret = expand_metric_events(); | ||
TEST_ASSERT_EQUAL("failed to expand metric events", ret, 0); | ||
|
||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters