From dea2b3c00efdf79860b3e8892d63f0631a7534e3 Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Mon, 25 May 2026 22:35:43 -0700 Subject: [PATCH 1/7] Skip perf counter tests when counters are unavailable --- test/perf_counters_gtest.cc | 60 +++++++++++++++++++++++++++++++++++-- test/perf_counters_test.cc | 29 ++++++++++++++---- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/test/perf_counters_gtest.cc b/test/perf_counters_gtest.cc index c4f287921a..a1f8d0b0bd 100644 --- a/test/perf_counters_gtest.cc +++ b/test/perf_counters_gtest.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include "../src/perf_counters.h" @@ -37,13 +38,27 @@ static std::set UniqueCounterNames(const PerfCounters& pc) { return names; } +static bool HasUniqueCounterNames(const PerfCounters& pc, + const std::set& names) { + auto actual = UniqueCounterNames(pc); + for (const auto& name : names) { + if (actual.find(name) == actual.end()) { + return false; + } + } + return true; +} + TEST(PerfCountersTest, OneCounter) { if (!PerfCounters::kSupported) { GTEST_SKIP() << "Performance counters not supported.\n"; } EXPECT_TRUE(PerfCounters::Initialize()); - EXPECT_EQ( - UniqueCounterNames(PerfCounters::Create({kGenericPerfEvent1})).size(), 1); + auto counter = PerfCounters::Create({kGenericPerfEvent1}); + if (!HasUniqueCounterNames(counter, {kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } + EXPECT_EQ(UniqueCounterNames(counter).size(), 1); } TEST(PerfCountersTest, NegativeTest) { @@ -59,6 +74,14 @@ TEST(PerfCountersTest, NegativeTest) { EXPECT_EQ(PerfCounters::Create({}).num_counters(), 0); EXPECT_EQ(PerfCounters::Create({""}).num_counters(), 0); EXPECT_EQ(PerfCounters::Create({"not a counter name"}).num_counters(), 0); + { + auto counter = + PerfCounters::Create({kGenericPerfEvent2, kGenericPerfEvent1}); + if (!HasUniqueCounterNames(counter, + {kGenericPerfEvent2, kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } + } { // Try sneaking in a bad egg to see if it is filtered out. The // number of counters has to be two, not zero @@ -115,6 +138,9 @@ TEST(PerfCountersTest, Read1Counter) { } EXPECT_TRUE(PerfCounters::Initialize()); auto counters = PerfCounters::Create({kGenericPerfEvent1}); + if (!HasUniqueCounterNames(counters, {kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } auto values1 = SnapshotAndCombine(counters); EXPECT_EQ(values1.size(), 1); EXPECT_GT(values1.begin()->second, 0); @@ -130,6 +156,12 @@ TEST(PerfCountersTest, Read1CounterEachCPU) { } #ifdef __linux__ EXPECT_TRUE(PerfCounters::Initialize()); + { + auto counter = PerfCounters::Create({kGenericPerfEvent1}); + if (!HasUniqueCounterNames(counter, {kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } + } cpu_set_t saved_set; if (sched_getaffinity(0, sizeof(saved_set), &saved_set) != 0) { @@ -168,6 +200,10 @@ TEST(PerfCountersTest, Read2Counters) { EXPECT_TRUE(PerfCounters::Initialize()); auto counters = PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2}); + if (!HasUniqueCounterNames(counters, + {kGenericPerfEvent1, kGenericPerfEvent2})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } auto values1 = SnapshotAndCombine(counters); EXPECT_EQ(values1.size(), 2); for (auto& kv : values1) { @@ -189,6 +225,12 @@ TEST(PerfCountersTest, ReopenExistingCounters) { } EXPECT_TRUE(PerfCounters::Initialize()); std::vector kMetrics({kGenericPerfEvent1}); + { + auto counter = PerfCounters::Create(kMetrics); + if (!HasUniqueCounterNames(counter, {kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } + } std::vector counters(2); for (auto& counter : counters) { counter = PerfCounters::Create(kMetrics); @@ -218,6 +260,12 @@ TEST(PerfCountersTest, CreateExistingMeasurements) { // Let's use a ubiquitous counter that is guaranteed to work // on all platforms const std::vector kMetrics{"cycles"}; + { + auto counter = PerfCounters::Create(kMetrics); + if (!HasUniqueCounterNames(counter, {"cycles"})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } + } // Cannot create a vector of actual objects because the // copy constructor of PerfCounters is deleted - and so is @@ -319,6 +367,14 @@ TEST(PerfCountersTest, MultiThreaded) { GTEST_SKIP() << "Test skipped because libpfm is not supported."; } EXPECT_TRUE(PerfCounters::Initialize()); + { + auto counters = + PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2}); + if (!HasUniqueCounterNames(counters, + {kGenericPerfEvent1, kGenericPerfEvent2})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } + } std::map before, after; // Notice that this test will work even if we taskset it to a single CPU diff --git a/test/perf_counters_test.cc b/test/perf_counters_test.cc index d97fa37ec9..3bc1b819a8 100644 --- a/test/perf_counters_test.cc +++ b/test/perf_counters_test.cc @@ -1,4 +1,6 @@ #include +#include +#include #undef NDEBUG #include "../src/commandlineflags.h" @@ -15,6 +17,22 @@ BM_DECLARE_string(benchmark_perf_counters); } // namespace benchmark namespace { +const char kGenericPerfEvent1[] = "CYCLES"; +const char kGenericPerfEvent2[] = "INSTRUCTIONS"; + +bool HasRequiredPerfCounters() { + if (!benchmark::internal::PerfCounters::kSupported) { + return false; + } + benchmark::internal::PerfCounters::Initialize(); + auto counters = + benchmark::internal::PerfCounters::Create({kGenericPerfEvent1, + kGenericPerfEvent2}); + std::set names{counters.names().begin(), + counters.names().end()}; + return names.find(kGenericPerfEvent1) != names.end() && + names.find(kGenericPerfEvent2) != names.end(); +} void BM_Simple(benchmark::State& state) { for (auto _ : state) { @@ -64,18 +82,18 @@ BENCHMARK(BM_WithPauseResume); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_WithPauseResume\",$"}}); static void CheckSimple(Results const& e) { - CHECK_COUNTER_VALUE(e, double, "CYCLES", GT, 0); + CHECK_COUNTER_VALUE(e, double, kGenericPerfEvent1, GT, 0); } double withoutPauseResumeInstrCount = 0.0; double withPauseResumeInstrCount = 0.0; void SaveInstrCountWithoutResume(Results const& e) { - withoutPauseResumeInstrCount = e.GetAs("INSTRUCTIONS"); + withoutPauseResumeInstrCount = e.GetAs(kGenericPerfEvent2); } void SaveInstrCountWithResume(Results const& e) { - withPauseResumeInstrCount = e.GetAs("INSTRUCTIONS"); + withPauseResumeInstrCount = e.GetAs(kGenericPerfEvent2); } CHECK_BENCHMARK_RESULTS("BM_Simple", &CheckSimple); @@ -85,10 +103,11 @@ CHECK_BENCHMARK_RESULTS("BM_WithPauseResume", &SaveInstrCountWithResume); int main(int argc, char* argv[]) { benchmark::MaybeReenterWithoutASLR(argc, argv); - if (!benchmark::internal::PerfCounters::kSupported) { + if (!HasRequiredPerfCounters()) { return 0; } - benchmark::FLAGS_benchmark_perf_counters = "CYCLES,INSTRUCTIONS"; + benchmark::FLAGS_benchmark_perf_counters = + std::string(kGenericPerfEvent1) + "," + kGenericPerfEvent2; benchmark::internal::PerfCounters::Initialize(); RunOutputTests(argc, argv); From 47fb7f356b80ec9254028edfe436c7552183f34b Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Tue, 26 May 2026 10:08:18 -0700 Subject: [PATCH 2/7] Apply clang-format to perf counter test --- test/perf_counters_test.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/perf_counters_test.cc b/test/perf_counters_test.cc index 3bc1b819a8..308703c7d9 100644 --- a/test/perf_counters_test.cc +++ b/test/perf_counters_test.cc @@ -25,11 +25,9 @@ bool HasRequiredPerfCounters() { return false; } benchmark::internal::PerfCounters::Initialize(); - auto counters = - benchmark::internal::PerfCounters::Create({kGenericPerfEvent1, - kGenericPerfEvent2}); - std::set names{counters.names().begin(), - counters.names().end()}; + auto counters = benchmark::internal::PerfCounters::Create( + {kGenericPerfEvent1, kGenericPerfEvent2}); + std::set names{counters.names().begin(), counters.names().end()}; return names.find(kGenericPerfEvent1) != names.end() && names.find(kGenericPerfEvent2) != names.end(); } From 315b6dbe99f42bb2922ef8c1ea4a60c070e20a38 Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Tue, 26 May 2026 12:02:28 -0700 Subject: [PATCH 3/7] Remove redundant perf counter initialization --- test/perf_counters_test.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/test/perf_counters_test.cc b/test/perf_counters_test.cc index 308703c7d9..d58f83f4f1 100644 --- a/test/perf_counters_test.cc +++ b/test/perf_counters_test.cc @@ -24,7 +24,6 @@ bool HasRequiredPerfCounters() { if (!benchmark::internal::PerfCounters::kSupported) { return false; } - benchmark::internal::PerfCounters::Initialize(); auto counters = benchmark::internal::PerfCounters::Create( {kGenericPerfEvent1, kGenericPerfEvent2}); std::set names{counters.names().begin(), counters.names().end()}; From de12d46d8add59d172e46bedc1f41d12bc49ac68 Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Tue, 26 May 2026 12:04:53 -0700 Subject: [PATCH 4/7] Share perf counter availability preflight --- test/perf_counters_gtest.cc | 89 +++++++++++-------------------------- 1 file changed, 26 insertions(+), 63 deletions(-) diff --git a/test/perf_counters_gtest.cc b/test/perf_counters_gtest.cc index a1f8d0b0bd..bd65a04575 100644 --- a/test/perf_counters_gtest.cc +++ b/test/perf_counters_gtest.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include "../src/perf_counters.h" #include "gmock/gmock.h" @@ -49,15 +50,20 @@ static bool HasUniqueCounterNames(const PerfCounters& pc, return true; } -TEST(PerfCountersTest, OneCounter) { +static bool HasRequiredPerfCounters(const std::vector& names) { if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Performance counters not supported.\n"; + return false; } - EXPECT_TRUE(PerfCounters::Initialize()); - auto counter = PerfCounters::Create({kGenericPerfEvent1}); - if (!HasUniqueCounterNames(counter, {kGenericPerfEvent1})) { + auto counters = PerfCounters::Create(names); + const std::set required_names(names.begin(), names.end()); + return HasUniqueCounterNames(counters, required_names); +} + +TEST(PerfCountersTest, OneCounter) { + if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { GTEST_SKIP() << "Requested performance counters are not available.\n"; } + auto counter = PerfCounters::Create({kGenericPerfEvent1}); EXPECT_EQ(UniqueCounterNames(counter).size(), 1); } @@ -66,7 +72,9 @@ TEST(PerfCountersTest, NegativeTest) { EXPECT_FALSE(PerfCounters::Initialize()); return; } - EXPECT_TRUE(PerfCounters::Initialize()); + if (!HasRequiredPerfCounters({kGenericPerfEvent2, kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; + } // Safety checks // Create() will always create a valid object, even if passed no or // wrong arguments as the new behavior is to warn and drop unsupported @@ -74,14 +82,6 @@ TEST(PerfCountersTest, NegativeTest) { EXPECT_EQ(PerfCounters::Create({}).num_counters(), 0); EXPECT_EQ(PerfCounters::Create({""}).num_counters(), 0); EXPECT_EQ(PerfCounters::Create({"not a counter name"}).num_counters(), 0); - { - auto counter = - PerfCounters::Create({kGenericPerfEvent2, kGenericPerfEvent1}); - if (!HasUniqueCounterNames(counter, - {kGenericPerfEvent2, kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; - } - } { // Try sneaking in a bad egg to see if it is filtered out. The // number of counters has to be two, not zero @@ -133,14 +133,10 @@ static std::map SnapshotAndCombine( } TEST(PerfCountersTest, Read1Counter) { - if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; - } - EXPECT_TRUE(PerfCounters::Initialize()); - auto counters = PerfCounters::Create({kGenericPerfEvent1}); - if (!HasUniqueCounterNames(counters, {kGenericPerfEvent1})) { + if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { GTEST_SKIP() << "Requested performance counters are not available.\n"; } + auto counters = PerfCounters::Create({kGenericPerfEvent1}); auto values1 = SnapshotAndCombine(counters); EXPECT_EQ(values1.size(), 1); EXPECT_GT(values1.begin()->second, 0); @@ -151,18 +147,10 @@ TEST(PerfCountersTest, Read1Counter) { } TEST(PerfCountersTest, Read1CounterEachCPU) { - if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; } #ifdef __linux__ - EXPECT_TRUE(PerfCounters::Initialize()); - { - auto counter = PerfCounters::Create({kGenericPerfEvent1}); - if (!HasUniqueCounterNames(counter, {kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; - } - } - cpu_set_t saved_set; if (sched_getaffinity(0, sizeof(saved_set), &saved_set) != 0) { // This can happen e.g. if there are more than CPU_SETSIZE CPUs. @@ -194,16 +182,11 @@ TEST(PerfCountersTest, Read1CounterEachCPU) { } TEST(PerfCountersTest, Read2Counters) { - if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + if (!HasRequiredPerfCounters({kGenericPerfEvent1, kGenericPerfEvent2})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; } - EXPECT_TRUE(PerfCounters::Initialize()); auto counters = PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2}); - if (!HasUniqueCounterNames(counters, - {kGenericPerfEvent1, kGenericPerfEvent2})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; - } auto values1 = SnapshotAndCombine(counters); EXPECT_EQ(values1.size(), 2); for (auto& kv : values1) { @@ -220,17 +203,10 @@ TEST(PerfCountersTest, Read2Counters) { TEST(PerfCountersTest, ReopenExistingCounters) { // This test works in recent and old Intel hardware, Pixel 3, and Pixel 6. // However we cannot make assumptions beyond 2 HW counters due to Pixel 6. - if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; } - EXPECT_TRUE(PerfCounters::Initialize()); std::vector kMetrics({kGenericPerfEvent1}); - { - auto counter = PerfCounters::Create(kMetrics); - if (!HasUniqueCounterNames(counter, {kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; - } - } std::vector counters(2); for (auto& counter : counters) { counter = PerfCounters::Create(kMetrics); @@ -248,7 +224,6 @@ TEST(PerfCountersTest, CreateExistingMeasurements) { if (!PerfCounters::kSupported) { GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; } - EXPECT_TRUE(PerfCounters::Initialize()); // This means we will try 10 counters but we can only guarantee // for sure at this time that only 3 will work. Perhaps in the future @@ -260,11 +235,8 @@ TEST(PerfCountersTest, CreateExistingMeasurements) { // Let's use a ubiquitous counter that is guaranteed to work // on all platforms const std::vector kMetrics{"cycles"}; - { - auto counter = PerfCounters::Create(kMetrics); - if (!HasUniqueCounterNames(counter, {"cycles"})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; - } + if (!HasRequiredPerfCounters(kMetrics)) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; } // Cannot create a vector of actual objects because the @@ -363,17 +335,8 @@ void measure(size_t threadcount, std::map* before, } TEST(PerfCountersTest, MultiThreaded) { - if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported."; - } - EXPECT_TRUE(PerfCounters::Initialize()); - { - auto counters = - PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2}); - if (!HasUniqueCounterNames(counters, - {kGenericPerfEvent1, kGenericPerfEvent2})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; - } + if (!HasRequiredPerfCounters({kGenericPerfEvent1, kGenericPerfEvent2})) { + GTEST_SKIP() << "Requested performance counters are not available.\n"; } std::map before, after; From b4c1ba341513b363641c22ce87670dc0e374f408 Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Tue, 26 May 2026 12:47:59 -0700 Subject: [PATCH 5/7] Share perf counter test availability helper --- test/perf_counters_gtest.cc | 56 +++++++++------------------------ test/perf_counters_test.cc | 16 ++-------- test/perf_counters_test_utils.h | 36 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 54 deletions(-) create mode 100644 test/perf_counters_test_utils.h diff --git a/test/perf_counters_gtest.cc b/test/perf_counters_gtest.cc index bd65a04575..7c86aad204 100644 --- a/test/perf_counters_gtest.cc +++ b/test/perf_counters_gtest.cc @@ -7,6 +7,7 @@ #include "../src/perf_counters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "perf_counters_test_utils.h" #ifndef GTEST_SKIP struct MsgHandler { @@ -18,6 +19,8 @@ struct MsgHandler { using benchmark::internal::PerfCounters; using benchmark::internal::PerfCountersMeasurement; using benchmark::internal::PerfCounterValues; +using benchmark::internal::test::HasRequiredPerfCounters; +using benchmark::internal::test::UniqueCounterNames; using ::testing::AllOf; using ::testing::Gt; using ::testing::Lt; @@ -30,38 +33,9 @@ TEST(PerfCountersTest, Init) { EXPECT_EQ(PerfCounters::Initialize(), PerfCounters::kSupported); } -// Generic events will have as many counters as there are CPU PMUs, and each -// will have the same name. In order to make these tests independent of the -// number of CPU PMUs in the system, we uniquify the counter names before -// testing them. -static std::set UniqueCounterNames(const PerfCounters& pc) { - std::set names{pc.names().begin(), pc.names().end()}; - return names; -} - -static bool HasUniqueCounterNames(const PerfCounters& pc, - const std::set& names) { - auto actual = UniqueCounterNames(pc); - for (const auto& name : names) { - if (actual.find(name) == actual.end()) { - return false; - } - } - return true; -} - -static bool HasRequiredPerfCounters(const std::vector& names) { - if (!PerfCounters::kSupported) { - return false; - } - auto counters = PerfCounters::Create(names); - const std::set required_names(names.begin(), names.end()); - return HasUniqueCounterNames(counters, required_names); -} - TEST(PerfCountersTest, OneCounter) { if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } auto counter = PerfCounters::Create({kGenericPerfEvent1}); EXPECT_EQ(UniqueCounterNames(counter).size(), 1); @@ -73,7 +47,7 @@ TEST(PerfCountersTest, NegativeTest) { return; } if (!HasRequiredPerfCounters({kGenericPerfEvent2, kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } // Safety checks // Create() will always create a valid object, even if passed no or @@ -134,7 +108,7 @@ static std::map SnapshotAndCombine( TEST(PerfCountersTest, Read1Counter) { if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } auto counters = PerfCounters::Create({kGenericPerfEvent1}); auto values1 = SnapshotAndCombine(counters); @@ -148,13 +122,13 @@ TEST(PerfCountersTest, Read1Counter) { TEST(PerfCountersTest, Read1CounterEachCPU) { if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } #ifdef __linux__ cpu_set_t saved_set; if (sched_getaffinity(0, sizeof(saved_set), &saved_set) != 0) { // This can happen e.g. if there are more than CPU_SETSIZE CPUs. - GTEST_SKIP() << "Could not save CPU affinity mask.\n"; + GTEST_SKIP() << "Could not save CPU affinity mask."; } for (size_t cpu = 0; cpu != CPU_SETSIZE; ++cpu) { @@ -177,13 +151,13 @@ TEST(PerfCountersTest, Read1CounterEachCPU) { EXPECT_EQ(sched_setaffinity(0, sizeof(saved_set), &saved_set), 0); #else - GTEST_SKIP() << "Test skipped on non-Linux.\n"; + GTEST_SKIP() << "Test skipped on non-Linux."; #endif } TEST(PerfCountersTest, Read2Counters) { if (!HasRequiredPerfCounters({kGenericPerfEvent1, kGenericPerfEvent2})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } auto counters = PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2}); @@ -204,7 +178,7 @@ TEST(PerfCountersTest, ReopenExistingCounters) { // This test works in recent and old Intel hardware, Pixel 3, and Pixel 6. // However we cannot make assumptions beyond 2 HW counters due to Pixel 6. if (!HasRequiredPerfCounters({kGenericPerfEvent1})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } std::vector kMetrics({kGenericPerfEvent1}); std::vector counters(2); @@ -222,7 +196,7 @@ TEST(PerfCountersTest, CreateExistingMeasurements) { // counters) at this date, // the same as previous test ReopenExistingCounters. if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + GTEST_SKIP() << "Test skipped because libpfm is not supported."; } // This means we will try 10 counters but we can only guarantee @@ -236,7 +210,7 @@ TEST(PerfCountersTest, CreateExistingMeasurements) { // on all platforms const std::vector kMetrics{"cycles"}; if (!HasRequiredPerfCounters(kMetrics)) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } // Cannot create a vector of actual objects because the @@ -336,7 +310,7 @@ void measure(size_t threadcount, std::map* before, TEST(PerfCountersTest, MultiThreaded) { if (!HasRequiredPerfCounters({kGenericPerfEvent1, kGenericPerfEvent2})) { - GTEST_SKIP() << "Requested performance counters are not available.\n"; + GTEST_SKIP() << "Requested performance counters are not available."; } std::map before, after; @@ -376,7 +350,7 @@ TEST(PerfCountersTest, HardwareLimits) { // counters) at this date, // the same as previous test ReopenExistingCounters. if (!PerfCounters::kSupported) { - GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + GTEST_SKIP() << "Test skipped because libpfm is not supported."; } EXPECT_TRUE(PerfCounters::Initialize()); diff --git a/test/perf_counters_test.cc b/test/perf_counters_test.cc index d58f83f4f1..5502e90437 100644 --- a/test/perf_counters_test.cc +++ b/test/perf_counters_test.cc @@ -1,5 +1,4 @@ #include -#include #include #undef NDEBUG @@ -10,6 +9,7 @@ #include "benchmark/state.h" #include "benchmark/utils.h" #include "output_test.h" +#include "perf_counters_test_utils.h" namespace benchmark { @@ -20,17 +20,6 @@ namespace { const char kGenericPerfEvent1[] = "CYCLES"; const char kGenericPerfEvent2[] = "INSTRUCTIONS"; -bool HasRequiredPerfCounters() { - if (!benchmark::internal::PerfCounters::kSupported) { - return false; - } - auto counters = benchmark::internal::PerfCounters::Create( - {kGenericPerfEvent1, kGenericPerfEvent2}); - std::set names{counters.names().begin(), counters.names().end()}; - return names.find(kGenericPerfEvent1) != names.end() && - names.find(kGenericPerfEvent2) != names.end(); -} - void BM_Simple(benchmark::State& state) { for (auto _ : state) { auto iterations = double(state.iterations()) * double(state.iterations()); @@ -100,7 +89,8 @@ CHECK_BENCHMARK_RESULTS("BM_WithPauseResume", &SaveInstrCountWithResume); int main(int argc, char* argv[]) { benchmark::MaybeReenterWithoutASLR(argc, argv); - if (!HasRequiredPerfCounters()) { + if (!benchmark::internal::test::HasRequiredPerfCounters( + {kGenericPerfEvent1, kGenericPerfEvent2})) { return 0; } benchmark::FLAGS_benchmark_perf_counters = diff --git a/test/perf_counters_test_utils.h b/test/perf_counters_test_utils.h new file mode 100644 index 0000000000..1649570a50 --- /dev/null +++ b/test/perf_counters_test_utils.h @@ -0,0 +1,36 @@ +#ifndef PERF_COUNTERS_TEST_UTILS_H_ +#define PERF_COUNTERS_TEST_UTILS_H_ + +#include +#include +#include + +#include "../src/perf_counters.h" + +namespace benchmark { +namespace internal { +namespace test { + +inline std::set UniqueCounterNames(const PerfCounters& counters) { + return {counters.names().begin(), counters.names().end()}; +} + +inline bool HasRequiredPerfCounters(const std::vector& names) { + if (!PerfCounters::kSupported) { + return false; + } + auto counters = PerfCounters::Create(names); + auto actual_names = UniqueCounterNames(counters); + for (const auto& name : names) { + if (actual_names.find(name) == actual_names.end()) { + return false; + } + } + return true; +} + +} // namespace test +} // namespace internal +} // namespace benchmark + +#endif // PERF_COUNTERS_TEST_UTILS_H_ From f4f68e6ae672bc06303fcd197eb29d8d67b1b4a2 Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Tue, 26 May 2026 14:20:30 -0700 Subject: [PATCH 6/7] Remove stray perf counter test includes --- test/perf_counters_gtest.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/perf_counters_gtest.cc b/test/perf_counters_gtest.cc index 7c86aad204..b753859514 100644 --- a/test/perf_counters_gtest.cc +++ b/test/perf_counters_gtest.cc @@ -1,8 +1,6 @@ #include #include -#include #include -#include #include "../src/perf_counters.h" #include "gmock/gmock.h" From 23b83d06d52b6b92c5ef7676fbcb904762dfd612 Mon Sep 17 00:00:00 2001 From: Haihan Jiang Date: Tue, 26 May 2026 18:26:57 -0700 Subject: [PATCH 7/7] Keep perf counter test helpers local --- test/perf_counters_gtest.cc | 24 +++++++++++++++++++--- test/perf_counters_test.cc | 25 ++++++++++++++++++++--- test/perf_counters_test_utils.h | 36 --------------------------------- 3 files changed, 43 insertions(+), 42 deletions(-) delete mode 100644 test/perf_counters_test_utils.h diff --git a/test/perf_counters_gtest.cc b/test/perf_counters_gtest.cc index b753859514..f3fd10bc95 100644 --- a/test/perf_counters_gtest.cc +++ b/test/perf_counters_gtest.cc @@ -1,11 +1,13 @@ #include #include +#include +#include #include +#include #include "../src/perf_counters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "perf_counters_test_utils.h" #ifndef GTEST_SKIP struct MsgHandler { @@ -17,8 +19,6 @@ struct MsgHandler { using benchmark::internal::PerfCounters; using benchmark::internal::PerfCountersMeasurement; using benchmark::internal::PerfCounterValues; -using benchmark::internal::test::HasRequiredPerfCounters; -using benchmark::internal::test::UniqueCounterNames; using ::testing::AllOf; using ::testing::Gt; using ::testing::Lt; @@ -27,6 +27,24 @@ namespace { const char kGenericPerfEvent1[] = "CYCLES"; const char kGenericPerfEvent2[] = "INSTRUCTIONS"; +std::set UniqueCounterNames(const PerfCounters& counters) { + return {counters.names().begin(), counters.names().end()}; +} + +bool HasRequiredPerfCounters(const std::vector& names) { + if (!PerfCounters::kSupported) { + return false; + } + auto counters = PerfCounters::Create(names); + auto actual_names = UniqueCounterNames(counters); + for (const auto& name : names) { + if (actual_names.find(name) == actual_names.end()) { + return false; + } + } + return true; +} + TEST(PerfCountersTest, Init) { EXPECT_EQ(PerfCounters::Initialize(), PerfCounters::kSupported); } diff --git a/test/perf_counters_test.cc b/test/perf_counters_test.cc index 5502e90437..d88f6bfd5b 100644 --- a/test/perf_counters_test.cc +++ b/test/perf_counters_test.cc @@ -1,5 +1,7 @@ #include +#include #include +#include #undef NDEBUG #include "../src/commandlineflags.h" @@ -9,7 +11,6 @@ #include "benchmark/state.h" #include "benchmark/utils.h" #include "output_test.h" -#include "perf_counters_test_utils.h" namespace benchmark { @@ -20,6 +21,25 @@ namespace { const char kGenericPerfEvent1[] = "CYCLES"; const char kGenericPerfEvent2[] = "INSTRUCTIONS"; +std::set UniqueCounterNames( + const benchmark::internal::PerfCounters& counters) { + return {counters.names().begin(), counters.names().end()}; +} + +bool HasRequiredPerfCounters(const std::vector& names) { + if (!benchmark::internal::PerfCounters::kSupported) { + return false; + } + auto counters = benchmark::internal::PerfCounters::Create(names); + auto actual_names = UniqueCounterNames(counters); + for (const auto& name : names) { + if (actual_names.find(name) == actual_names.end()) { + return false; + } + } + return true; +} + void BM_Simple(benchmark::State& state) { for (auto _ : state) { auto iterations = double(state.iterations()) * double(state.iterations()); @@ -89,8 +109,7 @@ CHECK_BENCHMARK_RESULTS("BM_WithPauseResume", &SaveInstrCountWithResume); int main(int argc, char* argv[]) { benchmark::MaybeReenterWithoutASLR(argc, argv); - if (!benchmark::internal::test::HasRequiredPerfCounters( - {kGenericPerfEvent1, kGenericPerfEvent2})) { + if (!HasRequiredPerfCounters({kGenericPerfEvent1, kGenericPerfEvent2})) { return 0; } benchmark::FLAGS_benchmark_perf_counters = diff --git a/test/perf_counters_test_utils.h b/test/perf_counters_test_utils.h deleted file mode 100644 index 1649570a50..0000000000 --- a/test/perf_counters_test_utils.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef PERF_COUNTERS_TEST_UTILS_H_ -#define PERF_COUNTERS_TEST_UTILS_H_ - -#include -#include -#include - -#include "../src/perf_counters.h" - -namespace benchmark { -namespace internal { -namespace test { - -inline std::set UniqueCounterNames(const PerfCounters& counters) { - return {counters.names().begin(), counters.names().end()}; -} - -inline bool HasRequiredPerfCounters(const std::vector& names) { - if (!PerfCounters::kSupported) { - return false; - } - auto counters = PerfCounters::Create(names); - auto actual_names = UniqueCounterNames(counters); - for (const auto& name : names) { - if (actual_names.find(name) == actual_names.end()) { - return false; - } - } - return true; -} - -} // namespace test -} // namespace internal -} // namespace benchmark - -#endif // PERF_COUNTERS_TEST_UTILS_H_