From patchwork Thu Jul 28 22:28:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 12931818 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 95AB1C04A68 for ; Thu, 28 Jul 2022 23:45:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=mLLfxGZ1XU4+IwdlsNcAT48378ADXgh/8GasfskLyBA=; b=08hvLQMZmtVoX4ctFJlYzQFMsp JcXBOPke5+BRPrwlpr/5vy3/XK0kdNQHMk/Fe+C6HSAwAkIuVwFI6ajM07wpT5jHOtA8RTOLbI3e1 a/IBnd2TbMwuAOHGdfkIgTOBFQXEAObpA/mU5scQJu6dcwzDuWaVARrvqHvhsYg2GqRj3oH3nhg0T Bc+2sTFpw5jdyQ8tsz8V3gr02UOTyhhSG5rQkiFlGtcCeJgHjtsVrkXqyzYGUktpTVsUwE4OxlGFj Q7Py1sJPOl7+fK9kakGAyyjcyL5nEP5WqZvOhezc0B0HP3+jVdCZWANzxx9Hdzy8tkKJu0tNvhKaq rrHww0lA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oHDB2-00Foiu-Hd; Thu, 28 Jul 2022 23:44:24 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oHDAU-00FoMq-02 for linux-arm-kernel@bombadil.infradead.org; Thu, 28 Jul 2022 23:43:50 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:Cc:To:From:Subject: References:Mime-Version:Message-Id:In-Reply-To:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=qKMuTgZyBMjnNbHnrNnTfnZV0TLakEyEiZz0dtiihIo=; b=OXCmlXqvpiFt9e5wH0TaUQ9+ve UlB1NOCFd0ZMvMKXi+CszQ1Ejmy1gC/5wv15f0lOuffbJeSmgo+06bi4in3iln0A2Y9oXsIUqGatZ dO8Na6AGN/Yp7Zv0RjT/ykClYZiaKlsSmsK4tE5Mc4gRwZ40NzWZPcQK2K/FIOx8e3BQUuxwl4sRe LqLLMLIo3tHLR+yys8WOIOQOBSjLxgus2SqpvIqSzvjXOKOn/vXp11xwcFgG2QABoD4VWRUJXHLx6 AUA6QT+5L+TagfiwzgR65WSZZi0UEUSZz5SbJmcf534PhUInmcBc66CZL75Kx4WrCQNwWbHwhSiho Uz/IX8Lg==; Received: from mail-yw1-x114a.google.com ([2607:f8b0:4864:20::114a]) by desiato.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oHC0E-001BoR-N8 for linux-arm-kernel@lists.infradead.org; Thu, 28 Jul 2022 22:29:14 +0000 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-3231401769dso19523457b3.10 for ; Thu, 28 Jul 2022 15:29:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=qKMuTgZyBMjnNbHnrNnTfnZV0TLakEyEiZz0dtiihIo=; b=DdNn9fS3GZJauMu7LlYjP7FWDKqS6dBksuXBe7yd7/mFUHPK29iUmX2kr3W2bGELvp 2Ceh5EqB7dY1BGfG69fAcax1LGwTRzrPzGmANUcSdtbtFMPeCpR9p6LTaqZNum224IrP kCyJyGVPRE3TgWs9wtecLeK9deCzRJJvIquh0Z9PAXkItJZ1c4lrquUX3EhFmKxie3iN 3+NPb19AQ0ed0fokKckGdy0pKEIwUzs1+9Shw1ptZw6+eBmGkB1jgumGsQ0uoWsRVzzM yoDDx2gBNWxeRgg4UpDg9aSAsiP9zCKPmYMJ9jhkWhq1GyfgNIeI9domN0LDIQGTjHgC KCsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=qKMuTgZyBMjnNbHnrNnTfnZV0TLakEyEiZz0dtiihIo=; b=hUSrNjoRDTMxTlO7XsW2r8h35bbKiC4DQ2/RAsjdZ36Uh/rJ1P5s1wcRmBjPSyXLp9 EP8d8uBVWvrSEXC1te4Eb1eN2zEyld+wAbXogl/h/S6LK7uheCsIDMA2Jy/mdwuImr1W O9ZYYVuYcTPFdgxLPdwLc32mWdwhGlZgMX7iwSKA3DScfFmS6uN12VQ5UJc2wECkJ/U9 Wj87ueo5r9KHAONJ/VkyBmQ1m5y+GPzpzp21Odr06PATxzwUyxSh4XFFlbo38455gOQ1 Av4NNTKtWN8d1OlnvELP/6vxXzBwmUBTZCxjjr6b2PP8eCuIGGRQDh8tQHiijm+nns+m mNxw== X-Gm-Message-State: ACgBeo0WWplNw5cUvWYYa3pVO4BMGHNjzQNe5axzeS+8yaNHP0mBbpMw jZWKt8E7++mq7Lokwp42ZCR3AYZi1dNd X-Google-Smtp-Source: AA6agR5ZqN2WPnOzSMy6kf0CyCm7GPk3h+qsG0wkHA2s+yXrbb/1JIYOtpGxEIFL+QbyFWZnkM4zs3tki2Pm X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:fd09:96c3:28af:b08f]) (user=irogers job=sendgmr) by 2002:a25:46d7:0:b0:673:c2ac:1f9d with SMTP id t206-20020a2546d7000000b00673c2ac1f9dmr637385yba.344.1659047345280; Thu, 28 Jul 2022 15:29:05 -0700 (PDT) Date: Thu, 28 Jul 2022 15:28:29 -0700 In-Reply-To: <20220728222835.3254224-1-irogers@google.com> Message-Id: <20220728222835.3254224-11-irogers@google.com> Mime-Version: 1.0 References: <20220728222835.3254224-1-irogers@google.com> X-Mailer: git-send-email 2.37.1.455.g008518b4e5-goog Subject: [PATCH v2 10/16] perf test: Use full metric resolution From: Ian Rogers To: John Garry , Will Deacon , James Clark , Mike Leach , Leo Yan , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Zhengjun Xing , Ravi Bangoria , Kan Liang , Adrian Hunter , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220728_232910_876320_6944A94E X-CRM114-Status: GOOD ( 25.16 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The simple metric resolution doesn't handle recursion properly, switch to use the full resolution as with the parse-metric tests which also increases coverage. Don't set the values for the metric backward as failures to generate a result are ignored. Signed-off-by: Ian Rogers --- tools/perf/tests/pmu-events.c | 222 ++++++++++++---------------------- 1 file changed, 77 insertions(+), 145 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ea8b41b5c4e3..e8df6bc26ebd 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -9,10 +9,12 @@ #include #include "debug.h" #include "../pmu-events/pmu-events.h" +#include #include "util/evlist.h" #include "util/expr.h" #include "util/parse-events.h" #include "metricgroup.h" +#include "stat.h" struct perf_pmu_test_event { /* used for matching against events from generated pmu-events.c */ @@ -801,27 +803,6 @@ static int check_parse_id(const char *id, struct parse_events_error *error, return ret; } -static int check_parse_cpu(const char *id, bool same_cpu, const struct pmu_event *pe) -{ - struct parse_events_error error; - int ret; - - parse_events_error__init(&error); - 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); - pr_warning("Error string '%s' help '%s'\n", error.str, - error.help); - } else if (ret) { - pr_debug3("Parse event failed, but for an event that may not be supported by this CPU.\nid '%s' metric '%s' expr '%s'\n", - id, pe->metric_name, pe->metric_expr); - ret = 0; - } - parse_events_error__exit(&error); - return ret; -} - static int check_parse_fake(const char *id) { struct parse_events_error error; @@ -838,160 +819,111 @@ struct metric { struct metric_ref metric_ref; }; -static int resolve_metric_simple(struct expr_parse_ctx *pctx, - struct list_head *compound_list, - const struct pmu_event *map, - const char *metric_name) -{ - struct hashmap_entry *cur, *cur_tmp; - struct metric *metric, *tmp; - size_t bkt; - bool all; - int rc; - - do { - all = true; - hashmap__for_each_entry_safe(pctx->ids, cur, cur_tmp, bkt) { - struct metric_ref *ref; - const struct pmu_event *pe; - - pe = metricgroup__find_metric(cur->key, map); - if (!pe) - continue; - - if (!strcmp(metric_name, (char *)cur->key)) { - pr_warning("Recursion detected for metric %s\n", metric_name); - rc = -1; - goto out_err; - } - - all = false; - - /* The metric key itself needs to go out.. */ - expr__del_id(pctx, cur->key); - - metric = malloc(sizeof(*metric)); - if (!metric) { - rc = -ENOMEM; - goto out_err; - } - - ref = &metric->metric_ref; - ref->metric_name = pe->metric_name; - ref->metric_expr = pe->metric_expr; - list_add_tail(&metric->list, compound_list); - - rc = expr__find_ids(pe->metric_expr, NULL, pctx); - if (rc) - goto out_err; - break; /* The hashmap has been modified, so restart */ - } - } while (!all); - - return 0; - -out_err: - list_for_each_entry_safe(metric, tmp, compound_list, list) - free(metric); - - return rc; - -} - -static void expr_failure(const char *msg, const struct pmu_event *pe) -{ - pr_debug("%s\nOn metric %s\nOn expression %s\n", msg, pe->metric_name, pe->metric_expr); -} - - -struct test__parsing_data { - const struct pmu_event *cpus_table; - struct expr_parse_ctx *ctx; - int failures; -}; - static int test__parsing_callback(const struct pmu_event *pe, const struct pmu_event *table, - void *vdata) + void *data) { - struct test__parsing_data *data = vdata; - struct metric *metric, *tmp; - struct hashmap_entry *cur; - LIST_HEAD(compound_list); - size_t bkt; + int *failures = data; int k; - double result; + struct evlist *evlist; + struct perf_cpu_map *cpus; + struct runtime_stat st; + struct evsel *evsel; + struct rblist metric_events = { + .nr_entries = 0, + }; + int err = 0; if (!pe->metric_expr) return 0; pr_debug("Found metric '%s'\n", pe->metric_name); + (*failures)++; - expr__ctx_clear(data->ctx); - if (expr__find_ids(pe->metric_expr, NULL, data->ctx) < 0) { - expr_failure("Parse find ids failed", pe); - data->failures++; - return 0; + /* + * We need to prepare evlist for stat mode running on CPU 0 + * because that's where all the stats are going to be created. + */ + evlist = evlist__new(); + if (!evlist) + return -ENOMEM; + + cpus = perf_cpu_map__new("0"); + if (!cpus) { + evlist__delete(evlist); + return -ENOMEM; } - if (resolve_metric_simple(data->ctx, &compound_list, table, - pe->metric_name)) { - expr_failure("Could not resolve metrics", pe); - data->failures++; - return TEST_FAIL; /* Don't tolerate errors due to severity */ + perf_evlist__set_maps(&evlist->core, cpus, NULL); + runtime_stat__init(&st); + + err = metricgroup__parse_groups_test(evlist, table, pe->metric_name, + false, false, + &metric_events); + if (err) { + if (!strcmp(pe->metric_name, "M1") || !strcmp(pe->metric_name, "M2") || + !strcmp(pe->metric_name, "M3")) { + (*failures)--; + pr_debug("Expected broken metric %s skipping\n", pe->metric_name); + err = 0; + } + goto out_err; } + err = evlist__alloc_stats(evlist, false); + if (err) + goto out_err; /* * Add all ids with a made up value. The value may trigger divide by * zero when subtracted and so try to make them unique. */ k = 1; - hashmap__for_each_entry(data->ctx->ids, cur, bkt) - expr__add_id_val(data->ctx, strdup(cur->key), k++); - - hashmap__for_each_entry(data->ctx->ids, cur, bkt) { - if (check_parse_cpu(cur->key, table == data->cpus_table, pe)) - data->failures++; + perf_stat__reset_shadow_stats(); + evlist__for_each_entry(evlist, evsel) { + perf_stat__update_shadow_stats(evsel, k, 0, &st); + if (!strcmp(evsel->name, "duration_time")) + update_stats(&walltime_nsecs_stats, k); + k++; } + evlist__for_each_entry(evlist, evsel) { + struct metric_event *me = metricgroup__lookup(&metric_events, evsel, false); - list_for_each_entry_safe(metric, tmp, &compound_list, list) { - expr__add_ref(data->ctx, &metric->metric_ref); - free(metric); - } + if (me != NULL) { + struct metric_expr *mexp; - if (expr__parse(&result, data->ctx, pe->metric_expr)) { - /* - * Parsing failed, make numbers go from large to small which can - * resolve divide by zero issues. - */ - k = 1024; - hashmap__for_each_entry(data->ctx->ids, cur, bkt) - expr__add_id_val(data->ctx, strdup(cur->key), k--); - if (expr__parse(&result, data->ctx, pe->metric_expr)) { - expr_failure("Parse failed", pe); - data->failures++; + list_for_each_entry (mexp, &me->head, nd) { + if (strcmp(mexp->metric_name, pe->metric_name)) + continue; + pr_debug("Result %f\n", test_generic_metric(mexp, 0, &st)); + err = 0; + (*failures)--; + goto out_err; + } } } - return 0; + pr_debug("Didn't find parsed metric %s", pe->metric_name); + err = 1; +out_err: + if (err) + pr_debug("Broken metric %s\n", pe->metric_name); + + /* ... cleanup. */ + metricgroup__rblist_exit(&metric_events); + runtime_stat__exit(&st); + evlist__free_stats(evlist); + perf_cpu_map__put(cpus); + evlist__delete(evlist); + return err; } static int test__parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - struct test__parsing_data data = { - .cpus_table = pmu_events_map__find(), - .ctx = expr__ctx_new(), - .failures = 0, - }; + int failures = 0; - if (!data.ctx) { - pr_debug("expr__ctx_new failed"); - return TEST_FAIL; - } - pmu_for_each_core_event(test__parsing_callback, &data); - pmu_for_each_sys_event(test__parsing_callback, &data); + pmu_for_each_core_event(test__parsing_callback, &failures); + pmu_for_each_sys_event(test__parsing_callback, &failures); - expr__ctx_free(data.ctx); - return data.failures == 0 ? TEST_OK : TEST_FAIL; + return failures == 0 ? TEST_OK : TEST_FAIL; } struct test_metric {