From nobody Mon Jun 8 04:15:54 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C21923A6B6F for ; Tue, 2 Jun 2026 07:31:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780385517; cv=none; b=V1KgcUX+j+f0bLd6oxfzK57iVQBanFXulMoK12xWEknISWmRKMRPBkKCVB/bTFeDGSRMOoMR1/wOiQx67QdBjoXWXlwDdmkJSx40+30bTNH+QAYv59kVZPhBjJgGiVaSkDihzL7SfCkh/SVKmGjuO0Sl+xYM7R2XhaLK3x8dK5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780385517; c=relaxed/simple; bh=1/I53jY/7I6pPt+AGU1upSQLrhjSPCZ2ESZocYEg9To=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=qbUSZdLBVWhxplfJv4SR9x05S2ZlsTFYk2aOhp39Nw7SyANscGAJKA5YpzNKkhrriOfYv3UAOBhShXLUWba9bk97aLMHBm3BWyILhUnhOOW3FvcJoTE7vMCKeJK0XbACIXAYxSYJ11lIdGvXYqeoMvtBcN7U8gQNH6wFb+0LRxU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=CtIkA4hf; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CtIkA4hf" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-304ea42b025so1859981eec.0 for ; Tue, 02 Jun 2026 00:31:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780385512; x=1780990312; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=RvC9h9RbmYQlkKM7/QQl/kAzyp/xvLFhaNUjlyAPRXg=; b=CtIkA4hfr+UN/x7fLVBYWJERE6hQK6lp1yEHFaOwsV6vWD3My0zhjYbY+DIoJ8OtYQ kr3yK8ySJxKiVCTo3nBkUWLLVSUD1S93xcQLG41C+Fghc9ZLRsAne8seoh8o+fnySV52 z5OxuRjwWqQoZWEW+XjBYPtv0S5MUdpB6Fmm1sZmAHtVDp1TuoegedKKc6mgTws9x05J Myi6FfuVmxJJf/9DubKbTImmvzoBRe1I+0lJMRKbJ6IJMqevBc8awAGiyMPS/YPfKOee NGlS1yhFQCZh89Bqh9D1T+8837uKl1uAccIjI6U0082SfJPTxnr/iy8yH6enmbARx22o QCcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780385512; x=1780990312; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=RvC9h9RbmYQlkKM7/QQl/kAzyp/xvLFhaNUjlyAPRXg=; b=YOz4LlzP2fRmE9S40p1haCxj8H8nDMxkiqJm+Ww1rdpWBbaTRhL6FuO3+WuaF+T96P l8SlzqNjePJJNPcE4FNkqLLrVunLttWtK3WJDJbsAiQkz3aOR05XyWhBtSkGXzAdyOm6 YuIVv/9o8s7Xgouq5GMjEpIdj9Ydg7tBvwS5LgEnS8waqQAuwD6dYn/I5/ALRxlBP+x3 HE7qCE06ykb8VGod6vuwfoZRhh9QEvbqH0YqTPGeCOGopcSvV7ovd3osfdXSTncxrEdM ix84WciT1NYfRVCaHRQ3LUd1wHpEL65Yt80uYihvpUtkBM9lOwl6u06w12B7N0cmQxEY HFyw== X-Forwarded-Encrypted: i=1; AFNElJ+qQIS2hOXMgiPKJkAI8SKZFhBr2pygRcP2UGVxFp90Btc4IDfA/7h2fuUGiSfTJGJuCc5vOhvPW5z6IDg=@vger.kernel.org X-Gm-Message-State: AOJu0Yz5q3MLH2tVhJv9TW2VH+TgbIE8p2C3ZteYM6B0xIYXS+kSaPIk n8hHSGpMuXiB8iRAMz7FFZD1CsRykivpWqvQ7b3RM8mcnSuBosgbfGMCkgd55N/Jz1Ak8+nbkqD fCtXI8VFbUQ== X-Received: from dybts2.prod.google.com ([2002:a05:7300:f582:b0:303:c170:9611]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:9f0a:b0:2f3:b7b2:cbd3 with SMTP id 5a478bee46e88-30734a7b8a2mr1365585eec.5.1780385511473; Tue, 02 Jun 2026 00:31:51 -0700 (PDT) Date: Tue, 2 Jun 2026 00:31:21 -0700 In-Reply-To: <20260602073132.2653307-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260601061401.1541457-1-irogers@google.com> <20260602073132.2653307-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.929.g9b7fa37559-goog Message-ID: <20260602073132.2653307-7-irogers@google.com> Subject: [PATCH v7] perf test pmu-events: A sub-test per metric table From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: adrian.hunter@intel.com, alexander.shishkin@linux.intel.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Break apart the slow "Parsing of PMU event table metrics" tests into one pair of tests (real and fake PMU) per metric table found, storing the specific table pointer in priv data. Implement setup_pmu_events_suite() to dynamically allocate and populate these test cases. Split static parser tests out into a separate test__parsing_fake_static() test case. Update test__parsing() and test__parsing_fake() to retrieve the specific table from priv data and test only that table, maintaining fallback compatibility if priv is NULL. Running these individual tests in parallel significantly reduces overall test execution time. Signed-off-by: Ian Rogers --- tools/perf/tests/pmu-events.c | 156 ++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 8 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index b1609a7e1d8c..fd5630f0a13c 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -923,13 +923,20 @@ static int test__parsing_callback(const struct pmu_me= tric *pm, return err; } =20 -static int test__parsing(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +static int test__parsing(struct test_suite *test, int subtest) { int failures =3D 0; + const struct pmu_metrics_table *table =3D NULL; =20 - pmu_for_each_core_metric(test__parsing_callback, &failures); - pmu_for_each_sys_metric(test__parsing_callback, &failures); + if (test->test_cases) + table =3D test->test_cases[subtest].priv; + + if (table) { + pmu_metrics_table__for_each_metric(table, test__parsing_callback, &failu= res); + } else { + pmu_for_each_core_metric(test__parsing_callback, &failures); + pmu_for_each_sys_metric(test__parsing_callback, &failures); + } =20 return failures =3D=3D 0 ? TEST_OK : TEST_FAIL; } @@ -1020,8 +1027,8 @@ static int test__parsing_fake_callback(const struct p= mu_metric *pm, * Parse all the metrics for current architecture, or all defined cpus via= the * 'fake_pmu' in parse_events. */ -static int test__parsing_fake(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +static int test__parsing_fake_static(struct test_suite *test __maybe_unuse= d, + int subtest __maybe_unused) { int err =3D 0; =20 @@ -1031,6 +1038,26 @@ static int test__parsing_fake(struct test_suite *tes= t __maybe_unused, return err; } =20 + return 0; +} + +static int test__parsing_fake(struct test_suite *test, int subtest) +{ + int err =3D 0; + const struct pmu_metrics_table *table =3D NULL; + + if (test->test_cases) + table =3D test->test_cases[subtest].priv; + + if (table) + return pmu_metrics_table__for_each_metric(table, test__parsing_fake_call= back, NULL); + + for (size_t i =3D 0; i < ARRAY_SIZE(metrics); i++) { + err =3D metric_parse_fake("", metrics[i].str); + if (err) + return err; + } + err =3D pmu_for_each_core_metric(test__parsing_fake_callback, NULL); if (err) return err; @@ -1059,17 +1086,130 @@ static int test__parsing_threshold(struct test_sui= te *test __maybe_unused, return pmu_for_each_sys_metric(test__parsing_threshold_callback, NULL); } =20 +struct populate_cb_data { + struct test_case *test_cases; + size_t curr; +}; + +static int count_metrics_tables_cb(const struct pmu_metrics_table *table _= _maybe_unused, void *data) +{ + size_t *count =3D data; + (*count)++; + return 0; +} + +static int populate_metrics_tables_cb(const struct pmu_metrics_table *tabl= e, void *data) +{ + struct populate_cb_data *cb_data =3D data; + const char *table_name =3D pmu_metrics_table__name(table); + char *desc_real, *desc_fake; + + if (!table_name) + table_name =3D "unknown"; + + if (asprintf(&desc_real, "PMU metric parsing: %s", table_name) < 0) + return -ENOMEM; + if (asprintf(&desc_fake, "PMU metric parsing with fake PMU: %s", table_na= me) < 0) { + free(desc_real); + return -ENOMEM; + } + + cb_data->test_cases[cb_data->curr++] =3D (struct test_case){ + .name =3D "parsing", + .desc =3D desc_real, + .run_case =3D test__parsing, + .priv =3D (void *)table, + .skip_reason =3D "some metrics failed", + }; + + cb_data->test_cases[cb_data->curr++] =3D (struct test_case){ + .name =3D "parsing_fake", + .desc =3D desc_fake, + .run_case =3D test__parsing_fake, + .priv =3D (void *)table, + }; + + return 0; +} + +static struct test_case pmu_events_tests[]; + +static int setup_pmu_events_suite(struct test_suite *suite) +{ + size_t num_tables =3D 0; + size_t num_fixed_tests =3D 4; + size_t tests_per_table =3D 2; + size_t total_tests; + struct test_case *test_cases; + size_t curr =3D 0; + struct populate_cb_data cb_data; + int ret; + + if (suite->test_cases !=3D pmu_events_tests) + return 0; + + ret =3D pmu_metrics_table__iterate_tables(count_metrics_tables_cb, &num_t= ables); + if (ret) + return ret; + + total_tests =3D num_fixed_tests + (num_tables * tests_per_table) + 1; + + test_cases =3D calloc(total_tests, sizeof(*test_cases)); + if (!test_cases) + return -ENOMEM; + + test_cases[curr++] =3D (struct test_case){ + .name =3D "pmu_event_table", + .desc =3D "PMU event table sanity", + .run_case =3D test__pmu_event_table, + }; + test_cases[curr++] =3D (struct test_case){ + .name =3D "aliases", + .desc =3D "PMU event map aliases", + .run_case =3D test__aliases, + }; + test_cases[curr++] =3D (struct test_case){ + .name =3D "parsing_fake_static", + .desc =3D "Parsing of static metrics with fake PMU", + .run_case =3D test__parsing_fake_static, + }; + test_cases[curr++] =3D (struct test_case){ + .name =3D "parsing_threshold", + .desc =3D "Parsing of metric thresholds with fake PMU", + .run_case =3D test__parsing_threshold, + }; + + cb_data =3D (struct populate_cb_data){ + .test_cases =3D test_cases, + .curr =3D curr, + }; + + ret =3D pmu_metrics_table__iterate_tables(populate_metrics_tables_cb, &cb= _data); + if (ret) { + size_t i; + + for (i =3D num_fixed_tests; i < cb_data.curr; i++) + free((char *)test_cases[i].desc); + free(test_cases); + return ret; + } + + suite->test_cases =3D test_cases; + return 0; +} + static struct test_case pmu_events_tests[] =3D { TEST_CASE("PMU event table sanity", pmu_event_table), TEST_CASE("PMU event map aliases", aliases), TEST_CASE_REASON("Parsing of PMU event table metrics", parsing, "some metrics failed"), - TEST_CASE("Parsing of PMU event table metrics with fake PMUs", parsing_fa= ke), - TEST_CASE("Parsing of metric thresholds with fake PMUs", parsing_threshol= d), + TEST_CASE("Parsing of PMU event table metrics with fake PMU", parsing_fak= e), + TEST_CASE("Parsing of metric thresholds with fake PMU", parsing_threshold= ), { .name =3D NULL, } }; =20 struct test_suite suite__pmu_events =3D { .desc =3D "PMU JSON event tests", .test_cases =3D pmu_events_tests, + .setup =3D setup_pmu_events_suite, }; --=20 2.54.0.929.g9b7fa37559-goog