[PATCH RFC 3/9] perf metrics: Pass cpu and sys tables to metricgroup__add_metric()
John Garry
john.g.garry at oracle.com
Mon Jul 3 08:20:34 PDT 2023
On 30/06/2023 19:39, Ian Rogers wrote:
> On Wed, Jun 28, 2023 at 3:30 AM John Garry <john.g.garry at oracle.com> wrote:
>>
>> The current @table arg may be a CPU metric table or a sys metric table.
>> There is no point in searching the CPU metric table for a sys metric, and
>> vice versa, so pass separate pointers
>>
>> When sys metric table is passed, this would mean that we are in self-test
>> mode. In this mode, the host system cannot match events in the metric
>> expression as the associated PMUs may not be present. As such, just try
>> add the metric, see metricgroup__add_metric_sys_event_iter().
>
> Thanks John, I'm not opposed to this change. My understanding is it
> will give greater testing coverage. As previously mentioned I'd like
> longer term we have a sysfs like abstraction for the json events. For
> CPUs this could be like:
>
> <cpuid>/cpu/events/inst_retired.any
> <cpuid>/cpu/events/inst_retired.any.scale
> <cpuid>/cpu/events/inst_retired.any.unit
> <cpuid>/cpu/events/inst_retired.any.desc
> ...
> <cpuid>/cpu/metrics/ipc
> <cpuid>/cpu/metrics/ipc.scale
> <cpuid>/cpu/metrics/ipc.unit
> ...
> <cpuid>/uncore_imc_free_running_0/events/unc_mc0_rdcas_count_freerun
> ...
>
> Where <cpuid> comes from mapfile.csv. I'd like to union the in memory
> json event generated sysfs, with the kernel sysfs. There needs to be
> some kind of wildcard mechanism for all the uncore counters. Such a
> union-ing could allow on an disk sysfs, and this could be a route for
> testing.
>
> For sys metrics I guess we'd so something like:
>
> sys/hisi_sicl/events/cpa_cycles
> sys/hisi_sicl/events/cpa_cycles.desc
> ...
> sys/cpa/events/cpa_cycles
> sys/cpa/cpa_cycles.desc
> ...
>
> or perhaps have some kind of wildcard matching syntax:
>
> sys/(hisi_sicl|cpa)/events/cpa_cycles
> sys/(hisi_sicl|cpa)/events/cpa_cycles.desc
> ...
>
> So ultimately I can imagine the distinction of sys and cpu are going
> to become less, and we just test properties of PMUs. The ideas of
> tables should be hidden, but we could have a boolean on a PMU to say
> whether it is a sys or cpu type.
Hi Ian,
I am not too hung up on my change in this patch really. It was more a
prep change for better test coverage, but the test coverage was not
added yet.
Ideas on testing would be helpful, but that can be once the changes in
patches 4-6 are agreed.
Thanks,
John
>
>> Signed-off-by: John Garry <john.g.garry at oracle.com>
>> ---
>> tools/perf/tests/expand-cgroup.c | 2 +-
>> tools/perf/tests/parse-metric.c | 2 +-
>> tools/perf/tests/pmu-events.c | 29 +++++++++++++++-----
>> tools/perf/util/metricgroup.c | 45 +++++++++++++++++++++++---------
>> tools/perf/util/metricgroup.h | 3 ++-
>> 5 files changed, 59 insertions(+), 22 deletions(-)
>>
>> diff --git a/tools/perf/tests/expand-cgroup.c b/tools/perf/tests/expand-cgroup.c
>> index 9c1a1f18db75..50e128ddb474 100644
>> --- a/tools/perf/tests/expand-cgroup.c
>> +++ b/tools/perf/tests/expand-cgroup.c
>> @@ -187,7 +187,7 @@ static int expand_metric_events(void)
>>
>> rblist__init(&metric_events);
>> pme_test = find_core_metrics_table("testarch", "testcpu");
>> - ret = metricgroup__parse_groups_test(evlist, pme_test, metric_str, &metric_events);
>> + ret = metricgroup__parse_groups_test(evlist, pme_test, NULL, metric_str, &metric_events);
>
> nit: Here and below. Could we name the argument here, so:
> ret = metricgroup__parse_groups_test(evlist, pme_test,
> /*sys_table=*/NULL, metric_str, &metric_events);
> for clarity it would be nice if pme_test were cpu_table.
>
> Thanks,
> Ian
>
>
>> if (ret < 0) {
>> pr_debug("failed to parse '%s' metric\n", metric_str);
>> goto out;
>> diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c
>> index 2c28fb50dc24..e146f1193294 100644
>> --- a/tools/perf/tests/parse-metric.c
>> +++ b/tools/perf/tests/parse-metric.c
>> @@ -95,7 +95,7 @@ static int __compute_metric(const char *name, struct value *vals,
>>
>> /* Parse the metric into metric_events list. */
>> pme_test = find_core_metrics_table("testarch", "testcpu");
>> - err = metricgroup__parse_groups_test(evlist, pme_test, name,
>> + err = metricgroup__parse_groups_test(evlist, pme_test, NULL, name,
>> &metric_events);
>> if (err)
>> goto out;
>> diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
>> index 64383fc34ef1..de571fd11cd7 100644
>> --- a/tools/perf/tests/pmu-events.c
>> +++ b/tools/perf/tests/pmu-events.c
>> @@ -798,9 +798,9 @@ struct metric {
>> struct metric_ref metric_ref;
>> };
>>
>> -static int test__parsing_callback(const struct pmu_metric *pm,
>> +static int _test__parsing_callback(const struct pmu_metric *pm,
>> const struct pmu_metrics_table *table,
>> - void *data)
>> + void *data, bool is_cpu_table)
>> {
>> int *failures = data;
>> int k;
>> @@ -811,6 +811,8 @@ static int test__parsing_callback(const struct pmu_metric *pm,
>> .nr_entries = 0,
>> };
>> int err = 0;
>> + const struct pmu_metrics_table *cpu_table = is_cpu_table ? table : NULL;
>> + const struct pmu_metrics_table *sys_table = is_cpu_table ? NULL : table;
>>
>> if (!pm->metric_expr)
>> return 0;
>> @@ -834,7 +836,8 @@ static int test__parsing_callback(const struct pmu_metric *pm,
>>
>> perf_evlist__set_maps(&evlist->core, cpus, NULL);
>>
>> - err = metricgroup__parse_groups_test(evlist, table, pm->metric_name, &metric_events);
>> + err = metricgroup__parse_groups_test(evlist, cpu_table, sys_table,
>> + pm->metric_name, &metric_events);
>> if (err) {
>> if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") ||
>> !strcmp(pm->metric_name, "M3")) {
>> @@ -890,13 +893,27 @@ static int test__parsing_callback(const struct pmu_metric *pm,
>> return err;
>> }
>>
>> -static int test__parsing(struct test_suite *test __maybe_unused,
>> +static int test__parsing_callback_cpu(const struct pmu_metric *pm,
>> + const struct pmu_metrics_table *table,
>> + void *data)
>> +{
>> + return _test__parsing_callback(pm, table, data, true);
>> +}
>> +
>> +static int test__parsing_callback_sys(const struct pmu_metric *pm,
>> + const struct pmu_metrics_table *table,
>> + void *data)
>> +{
>> + return _test__parsing_callback(pm, table, data, false);
>> +}
>> +
>> +static __maybe_unused int test__parsing(struct test_suite *test __maybe_unused,
>> int subtest __maybe_unused)
>> {
>> int failures = 0;
>>
>> - pmu_for_each_core_metric(test__parsing_callback, &failures);
>> - pmu_for_each_sys_metric(test__parsing_callback, &failures);
>> + pmu_for_each_core_metric(test__parsing_callback_cpu, &failures);
>> + pmu_for_each_sys_metric(test__parsing_callback_sys, &failures);
>>
>> return failures == 0 ? TEST_OK : TEST_FAIL;
>> }
>> diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
>> index 8d2ac2513530..520436fbe99d 100644
>> --- a/tools/perf/util/metricgroup.c
>> +++ b/tools/perf/util/metricgroup.c
>> @@ -1232,13 +1232,14 @@ static int metricgroup__add_metric(const char *pmu, const char *metric_name, con
>> const char *user_requested_cpu_list,
>> bool system_wide,
>> struct list_head *metric_list,
>> - const struct pmu_metrics_table *table)
>> + const struct pmu_metrics_table *cpu_table,
>> + const struct pmu_metrics_table *sys_table)
>> {
>> LIST_HEAD(list);
>> int ret;
>> bool has_match = false;
>>
>> - {
>> + if (cpu_table) {
>> struct metricgroup__add_metric_data data = {
>> .list = &list,
>> .pmu = pmu,
>> @@ -1254,7 +1255,7 @@ static int metricgroup__add_metric(const char *pmu, const char *metric_name, con
>> * Iterate over all metrics seeing if metric matches either the
>> * name or group. When it does add the metric to the list.
>> */
>> - ret = pmu_metrics_table_for_each_metric(table, metricgroup__add_metric_callback,
>> + ret = pmu_metrics_table_for_each_metric(cpu_table, metricgroup__add_metric_callback,
>> &data);
>> if (ret)
>> goto out;
>> @@ -1267,7 +1268,21 @@ static int metricgroup__add_metric(const char *pmu, const char *metric_name, con
>> goto out;
>> }
>>
>> - {
>> + if (sys_table) {
>> + struct metricgroup_add_iter_data data = {
>> + .metric_list = &list,
>> + .pmu = pmu,
>> + .metric_name = metric_name,
>> + .modifier = modifier,
>> + .metric_no_group = metric_no_group,
>> + .user_requested_cpu_list = user_requested_cpu_list,
>> + .system_wide = system_wide,
>> + .has_match = &has_match,
>> + .ret = &ret,
>> + };
>> + pmu_metrics_table_for_each_metric(sys_table,
>> + metricgroup__add_metric_sys_event_iter, &data);
>> + } else {
>> struct metricgroup_iter_data data = {
>> .fn = metricgroup__add_metric_sys_event_iter,
>> .data = (void *) &(struct metricgroup_add_iter_data) {
>> @@ -1320,7 +1335,8 @@ static int metricgroup__add_metric_list(const char *pmu, const char *list,
>> bool metric_no_threshold,
>> const char *user_requested_cpu_list,
>> bool system_wide, struct list_head *metric_list,
>> - const struct pmu_metrics_table *table)
>> + const struct pmu_metrics_table *cpu_table,
>> + const struct pmu_metrics_table *sys_table)
>> {
>> char *list_itr, *list_copy, *metric_name, *modifier;
>> int ret, count = 0;
>> @@ -1338,7 +1354,8 @@ static int metricgroup__add_metric_list(const char *pmu, const char *list,
>> ret = metricgroup__add_metric(pmu, metric_name, modifier,
>> metric_no_group, metric_no_threshold,
>> user_requested_cpu_list,
>> - system_wide, metric_list, table);
>> + system_wide, metric_list, cpu_table,
>> + sys_table);
>> if (ret == -EINVAL)
>> pr_err("Cannot find metric or group `%s'\n", metric_name);
>>
>> @@ -1534,7 +1551,8 @@ static int parse_groups(struct evlist *perf_evlist,
>> bool system_wide,
>> struct perf_pmu *fake_pmu,
>> struct rblist *metric_events_list,
>> - const struct pmu_metrics_table *table)
>> + const struct pmu_metrics_table *cpu_table,
>> + const struct pmu_metrics_table *sys_table)
>> {
>> struct evlist *combined_evlist = NULL;
>> LIST_HEAD(metric_list);
>> @@ -1547,7 +1565,7 @@ static int parse_groups(struct evlist *perf_evlist,
>> metricgroup__rblist_init(metric_events_list);
>> ret = metricgroup__add_metric_list(pmu, str, metric_no_group, metric_no_threshold,
>> user_requested_cpu_list,
>> - system_wide, &metric_list, table);
>> + system_wide, &metric_list, cpu_table, sys_table);
>> if (ret)
>> goto out;
>>
>> @@ -1697,18 +1715,19 @@ int metricgroup__parse_groups(struct evlist *perf_evlist,
>> bool system_wide,
>> struct rblist *metric_events)
>> {
>> - const struct pmu_metrics_table *table = pmu_metrics_table__find();
>> + const struct pmu_metrics_table *cpu_table = pmu_metrics_table__find();
>>
>> - if (!table)
>> + if (!cpu_table)
>> return -EINVAL;
>>
>> return parse_groups(perf_evlist, pmu, str, metric_no_group, metric_no_merge,
>> metric_no_threshold, user_requested_cpu_list, system_wide,
>> - /*fake_pmu=*/NULL, metric_events, table);
>> + /*fake_pmu=*/NULL, metric_events, cpu_table, NULL);
>> }
>>
>> int metricgroup__parse_groups_test(struct evlist *evlist,
>> - const struct pmu_metrics_table *table,
>> + const struct pmu_metrics_table *cpu_table,
>> + const struct pmu_metrics_table *sys_table,
>> const char *str,
>> struct rblist *metric_events)
>> {
>> @@ -1718,7 +1737,7 @@ int metricgroup__parse_groups_test(struct evlist *evlist,
>> /*metric_no_threshold=*/false,
>> /*user_requested_cpu_list=*/NULL,
>> /*system_wide=*/false,
>> - &perf_pmu__fake, metric_events, table);
>> + &perf_pmu__fake, metric_events, cpu_table, sys_table);
>> }
>>
>> struct metricgroup__has_metric_data {
>> diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h
>> index d5325c6ec8e1..b5f0d598eaec 100644
>> --- a/tools/perf/util/metricgroup.h
>> +++ b/tools/perf/util/metricgroup.h
>> @@ -79,7 +79,8 @@ int metricgroup__parse_groups(struct evlist *perf_evlist,
>> bool system_wide,
>> struct rblist *metric_events);
>> int metricgroup__parse_groups_test(struct evlist *evlist,
>> - const struct pmu_metrics_table *table,
>> + const struct pmu_metrics_table *cpu_table,
>> + const struct pmu_metrics_table *sys_table,
>> const char *str,
>> struct rblist *metric_events);
>>
>> --
>> 2.35.3
>>
More information about the linux-arm-kernel
mailing list