1*dbb99499SAndroid Build Coastguard Worker #include <random>
2*dbb99499SAndroid Build Coastguard Worker #include <thread>
3*dbb99499SAndroid Build Coastguard Worker
4*dbb99499SAndroid Build Coastguard Worker #include "../src/perf_counters.h"
5*dbb99499SAndroid Build Coastguard Worker #include "gmock/gmock.h"
6*dbb99499SAndroid Build Coastguard Worker #include "gtest/gtest.h"
7*dbb99499SAndroid Build Coastguard Worker
8*dbb99499SAndroid Build Coastguard Worker #ifndef GTEST_SKIP
9*dbb99499SAndroid Build Coastguard Worker struct MsgHandler {
operator =MsgHandler10*dbb99499SAndroid Build Coastguard Worker void operator=(std::ostream&) {}
11*dbb99499SAndroid Build Coastguard Worker };
12*dbb99499SAndroid Build Coastguard Worker #define GTEST_SKIP() return MsgHandler() = std::cout
13*dbb99499SAndroid Build Coastguard Worker #endif
14*dbb99499SAndroid Build Coastguard Worker
15*dbb99499SAndroid Build Coastguard Worker using benchmark::internal::PerfCounters;
16*dbb99499SAndroid Build Coastguard Worker using benchmark::internal::PerfCountersMeasurement;
17*dbb99499SAndroid Build Coastguard Worker using benchmark::internal::PerfCounterValues;
18*dbb99499SAndroid Build Coastguard Worker using ::testing::AllOf;
19*dbb99499SAndroid Build Coastguard Worker using ::testing::Gt;
20*dbb99499SAndroid Build Coastguard Worker using ::testing::Lt;
21*dbb99499SAndroid Build Coastguard Worker
22*dbb99499SAndroid Build Coastguard Worker namespace {
23*dbb99499SAndroid Build Coastguard Worker const char kGenericPerfEvent1[] = "CYCLES";
24*dbb99499SAndroid Build Coastguard Worker const char kGenericPerfEvent2[] = "INSTRUCTIONS";
25*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,Init)26*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, Init) {
27*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(PerfCounters::Initialize(), PerfCounters::kSupported);
28*dbb99499SAndroid Build Coastguard Worker }
29*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,OneCounter)30*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, OneCounter) {
31*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
32*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Performance counters not supported.\n";
33*dbb99499SAndroid Build Coastguard Worker }
34*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
35*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(PerfCounters::Create({kGenericPerfEvent1}).num_counters(), 1);
36*dbb99499SAndroid Build Coastguard Worker }
37*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,NegativeTest)38*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, NegativeTest) {
39*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
40*dbb99499SAndroid Build Coastguard Worker EXPECT_FALSE(PerfCounters::Initialize());
41*dbb99499SAndroid Build Coastguard Worker return;
42*dbb99499SAndroid Build Coastguard Worker }
43*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
44*dbb99499SAndroid Build Coastguard Worker // Safety checks
45*dbb99499SAndroid Build Coastguard Worker // Create() will always create a valid object, even if passed no or
46*dbb99499SAndroid Build Coastguard Worker // wrong arguments as the new behavior is to warn and drop unsupported
47*dbb99499SAndroid Build Coastguard Worker // counters
48*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(PerfCounters::Create({}).num_counters(), 0);
49*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(PerfCounters::Create({""}).num_counters(), 0);
50*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(PerfCounters::Create({"not a counter name"}).num_counters(), 0);
51*dbb99499SAndroid Build Coastguard Worker {
52*dbb99499SAndroid Build Coastguard Worker // Try sneaking in a bad egg to see if it is filtered out. The
53*dbb99499SAndroid Build Coastguard Worker // number of counters has to be two, not zero
54*dbb99499SAndroid Build Coastguard Worker auto counter =
55*dbb99499SAndroid Build Coastguard Worker PerfCounters::Create({kGenericPerfEvent2, "", kGenericPerfEvent1});
56*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.num_counters(), 2);
57*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.names(), std::vector<std::string>(
58*dbb99499SAndroid Build Coastguard Worker {kGenericPerfEvent2, kGenericPerfEvent1}));
59*dbb99499SAndroid Build Coastguard Worker }
60*dbb99499SAndroid Build Coastguard Worker {
61*dbb99499SAndroid Build Coastguard Worker // Try sneaking in an outrageous counter, like a fat finger mistake
62*dbb99499SAndroid Build Coastguard Worker auto counter = PerfCounters::Create(
63*dbb99499SAndroid Build Coastguard Worker {kGenericPerfEvent2, "not a counter name", kGenericPerfEvent1});
64*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.num_counters(), 2);
65*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.names(), std::vector<std::string>(
66*dbb99499SAndroid Build Coastguard Worker {kGenericPerfEvent2, kGenericPerfEvent1}));
67*dbb99499SAndroid Build Coastguard Worker }
68*dbb99499SAndroid Build Coastguard Worker {
69*dbb99499SAndroid Build Coastguard Worker // Finally try a golden input - it should like both of them
70*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2})
71*dbb99499SAndroid Build Coastguard Worker .num_counters(),
72*dbb99499SAndroid Build Coastguard Worker 2);
73*dbb99499SAndroid Build Coastguard Worker }
74*dbb99499SAndroid Build Coastguard Worker {
75*dbb99499SAndroid Build Coastguard Worker // Add a bad apple in the end of the chain to check the edges
76*dbb99499SAndroid Build Coastguard Worker auto counter = PerfCounters::Create(
77*dbb99499SAndroid Build Coastguard Worker {kGenericPerfEvent1, kGenericPerfEvent2, "bad event name"});
78*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.num_counters(), 2);
79*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.names(), std::vector<std::string>(
80*dbb99499SAndroid Build Coastguard Worker {kGenericPerfEvent1, kGenericPerfEvent2}));
81*dbb99499SAndroid Build Coastguard Worker }
82*dbb99499SAndroid Build Coastguard Worker }
83*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,Read1Counter)84*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, Read1Counter) {
85*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
86*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Test skipped because libpfm is not supported.\n";
87*dbb99499SAndroid Build Coastguard Worker }
88*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
89*dbb99499SAndroid Build Coastguard Worker auto counters = PerfCounters::Create({kGenericPerfEvent1});
90*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counters.num_counters(), 1);
91*dbb99499SAndroid Build Coastguard Worker PerfCounterValues values1(1);
92*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counters.Snapshot(&values1));
93*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values1[0], 0);
94*dbb99499SAndroid Build Coastguard Worker PerfCounterValues values2(1);
95*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counters.Snapshot(&values2));
96*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values2[0], 0);
97*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values2[0], values1[0]);
98*dbb99499SAndroid Build Coastguard Worker }
99*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,Read2Counters)100*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, Read2Counters) {
101*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
102*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Test skipped because libpfm is not supported.\n";
103*dbb99499SAndroid Build Coastguard Worker }
104*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
105*dbb99499SAndroid Build Coastguard Worker auto counters =
106*dbb99499SAndroid Build Coastguard Worker PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2});
107*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counters.num_counters(), 2);
108*dbb99499SAndroid Build Coastguard Worker PerfCounterValues values1(2);
109*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counters.Snapshot(&values1));
110*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values1[0], 0);
111*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values1[1], 0);
112*dbb99499SAndroid Build Coastguard Worker PerfCounterValues values2(2);
113*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counters.Snapshot(&values2));
114*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values2[0], 0);
115*dbb99499SAndroid Build Coastguard Worker EXPECT_GT(values2[1], 0);
116*dbb99499SAndroid Build Coastguard Worker }
117*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,ReopenExistingCounters)118*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, ReopenExistingCounters) {
119*dbb99499SAndroid Build Coastguard Worker // This test works in recent and old Intel hardware, Pixel 3, and Pixel 6.
120*dbb99499SAndroid Build Coastguard Worker // However we cannot make assumptions beyond 2 HW counters due to Pixel 6.
121*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
122*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Test skipped because libpfm is not supported.\n";
123*dbb99499SAndroid Build Coastguard Worker }
124*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
125*dbb99499SAndroid Build Coastguard Worker std::vector<std::string> kMetrics({kGenericPerfEvent1});
126*dbb99499SAndroid Build Coastguard Worker std::vector<PerfCounters> counters(2);
127*dbb99499SAndroid Build Coastguard Worker for (auto& counter : counters) {
128*dbb99499SAndroid Build Coastguard Worker counter = PerfCounters::Create(kMetrics);
129*dbb99499SAndroid Build Coastguard Worker }
130*dbb99499SAndroid Build Coastguard Worker PerfCounterValues values(1);
131*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counters[0].Snapshot(&values));
132*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counters[1].Snapshot(&values));
133*dbb99499SAndroid Build Coastguard Worker }
134*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,CreateExistingMeasurements)135*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, CreateExistingMeasurements) {
136*dbb99499SAndroid Build Coastguard Worker // The test works (i.e. causes read to fail) for the assumptions
137*dbb99499SAndroid Build Coastguard Worker // about hardware capabilities (i.e. small number (2) hardware
138*dbb99499SAndroid Build Coastguard Worker // counters) at this date,
139*dbb99499SAndroid Build Coastguard Worker // the same as previous test ReopenExistingCounters.
140*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
141*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Test skipped because libpfm is not supported.\n";
142*dbb99499SAndroid Build Coastguard Worker }
143*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
144*dbb99499SAndroid Build Coastguard Worker
145*dbb99499SAndroid Build Coastguard Worker // This means we will try 10 counters but we can only guarantee
146*dbb99499SAndroid Build Coastguard Worker // for sure at this time that only 3 will work. Perhaps in the future
147*dbb99499SAndroid Build Coastguard Worker // we could use libpfm to query for the hardware limits on this
148*dbb99499SAndroid Build Coastguard Worker // particular platform.
149*dbb99499SAndroid Build Coastguard Worker const int kMaxCounters = 10;
150*dbb99499SAndroid Build Coastguard Worker const int kMinValidCounters = 2;
151*dbb99499SAndroid Build Coastguard Worker
152*dbb99499SAndroid Build Coastguard Worker // Let's use a ubiquitous counter that is guaranteed to work
153*dbb99499SAndroid Build Coastguard Worker // on all platforms
154*dbb99499SAndroid Build Coastguard Worker const std::vector<std::string> kMetrics{"cycles"};
155*dbb99499SAndroid Build Coastguard Worker
156*dbb99499SAndroid Build Coastguard Worker // Cannot create a vector of actual objects because the
157*dbb99499SAndroid Build Coastguard Worker // copy constructor of PerfCounters is deleted - and so is
158*dbb99499SAndroid Build Coastguard Worker // implicitly deleted on PerfCountersMeasurement too
159*dbb99499SAndroid Build Coastguard Worker std::vector<std::unique_ptr<PerfCountersMeasurement>>
160*dbb99499SAndroid Build Coastguard Worker perf_counter_measurements;
161*dbb99499SAndroid Build Coastguard Worker
162*dbb99499SAndroid Build Coastguard Worker perf_counter_measurements.reserve(kMaxCounters);
163*dbb99499SAndroid Build Coastguard Worker for (int j = 0; j < kMaxCounters; ++j) {
164*dbb99499SAndroid Build Coastguard Worker perf_counter_measurements.emplace_back(
165*dbb99499SAndroid Build Coastguard Worker new PerfCountersMeasurement(kMetrics));
166*dbb99499SAndroid Build Coastguard Worker }
167*dbb99499SAndroid Build Coastguard Worker
168*dbb99499SAndroid Build Coastguard Worker std::vector<std::pair<std::string, double>> measurements;
169*dbb99499SAndroid Build Coastguard Worker
170*dbb99499SAndroid Build Coastguard Worker // Start all counters together to see if they hold
171*dbb99499SAndroid Build Coastguard Worker size_t max_counters = kMaxCounters;
172*dbb99499SAndroid Build Coastguard Worker for (size_t i = 0; i < kMaxCounters; ++i) {
173*dbb99499SAndroid Build Coastguard Worker auto& counter(*perf_counter_measurements[i]);
174*dbb99499SAndroid Build Coastguard Worker EXPECT_EQ(counter.num_counters(), 1);
175*dbb99499SAndroid Build Coastguard Worker if (!counter.Start()) {
176*dbb99499SAndroid Build Coastguard Worker max_counters = i;
177*dbb99499SAndroid Build Coastguard Worker break;
178*dbb99499SAndroid Build Coastguard Worker };
179*dbb99499SAndroid Build Coastguard Worker }
180*dbb99499SAndroid Build Coastguard Worker
181*dbb99499SAndroid Build Coastguard Worker ASSERT_GE(max_counters, kMinValidCounters);
182*dbb99499SAndroid Build Coastguard Worker
183*dbb99499SAndroid Build Coastguard Worker // Start all together
184*dbb99499SAndroid Build Coastguard Worker for (size_t i = 0; i < max_counters; ++i) {
185*dbb99499SAndroid Build Coastguard Worker auto& counter(*perf_counter_measurements[i]);
186*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counter.Stop(measurements) || (i >= kMinValidCounters));
187*dbb99499SAndroid Build Coastguard Worker }
188*dbb99499SAndroid Build Coastguard Worker
189*dbb99499SAndroid Build Coastguard Worker // Start/stop individually
190*dbb99499SAndroid Build Coastguard Worker for (size_t i = 0; i < max_counters; ++i) {
191*dbb99499SAndroid Build Coastguard Worker auto& counter(*perf_counter_measurements[i]);
192*dbb99499SAndroid Build Coastguard Worker measurements.clear();
193*dbb99499SAndroid Build Coastguard Worker counter.Start();
194*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counter.Stop(measurements) || (i >= kMinValidCounters));
195*dbb99499SAndroid Build Coastguard Worker }
196*dbb99499SAndroid Build Coastguard Worker }
197*dbb99499SAndroid Build Coastguard Worker
198*dbb99499SAndroid Build Coastguard Worker // We try to do some meaningful work here but the compiler
199*dbb99499SAndroid Build Coastguard Worker // insists in optimizing away our loop so we had to add a
200*dbb99499SAndroid Build Coastguard Worker // no-optimize macro. In case it fails, we added some entropy
201*dbb99499SAndroid Build Coastguard Worker // to this pool as well.
202*dbb99499SAndroid Build Coastguard Worker
do_work()203*dbb99499SAndroid Build Coastguard Worker BENCHMARK_DONT_OPTIMIZE size_t do_work() {
204*dbb99499SAndroid Build Coastguard Worker static std::mt19937 rd{std::random_device{}()};
205*dbb99499SAndroid Build Coastguard Worker static std::uniform_int_distribution<size_t> mrand(0, 10);
206*dbb99499SAndroid Build Coastguard Worker const size_t kNumLoops = 1000000;
207*dbb99499SAndroid Build Coastguard Worker size_t sum = 0;
208*dbb99499SAndroid Build Coastguard Worker for (size_t j = 0; j < kNumLoops; ++j) {
209*dbb99499SAndroid Build Coastguard Worker sum += mrand(rd);
210*dbb99499SAndroid Build Coastguard Worker }
211*dbb99499SAndroid Build Coastguard Worker benchmark::DoNotOptimize(sum);
212*dbb99499SAndroid Build Coastguard Worker return sum;
213*dbb99499SAndroid Build Coastguard Worker }
214*dbb99499SAndroid Build Coastguard Worker
measure(size_t threadcount,PerfCounterValues * before,PerfCounterValues * after)215*dbb99499SAndroid Build Coastguard Worker void measure(size_t threadcount, PerfCounterValues* before,
216*dbb99499SAndroid Build Coastguard Worker PerfCounterValues* after) {
217*dbb99499SAndroid Build Coastguard Worker BM_CHECK_NE(before, nullptr);
218*dbb99499SAndroid Build Coastguard Worker BM_CHECK_NE(after, nullptr);
219*dbb99499SAndroid Build Coastguard Worker std::vector<std::thread> threads(threadcount);
220*dbb99499SAndroid Build Coastguard Worker auto work = [&]() { BM_CHECK(do_work() > 1000); };
221*dbb99499SAndroid Build Coastguard Worker
222*dbb99499SAndroid Build Coastguard Worker // We need to first set up the counters, then start the threads, so the
223*dbb99499SAndroid Build Coastguard Worker // threads would inherit the counters. But later, we need to first destroy
224*dbb99499SAndroid Build Coastguard Worker // the thread pool (so all the work finishes), then measure the counters. So
225*dbb99499SAndroid Build Coastguard Worker // the scopes overlap, and we need to explicitly control the scope of the
226*dbb99499SAndroid Build Coastguard Worker // threadpool.
227*dbb99499SAndroid Build Coastguard Worker auto counters =
228*dbb99499SAndroid Build Coastguard Worker PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2});
229*dbb99499SAndroid Build Coastguard Worker for (auto& t : threads) t = std::thread(work);
230*dbb99499SAndroid Build Coastguard Worker counters.Snapshot(before);
231*dbb99499SAndroid Build Coastguard Worker for (auto& t : threads) t.join();
232*dbb99499SAndroid Build Coastguard Worker counters.Snapshot(after);
233*dbb99499SAndroid Build Coastguard Worker }
234*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,MultiThreaded)235*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, MultiThreaded) {
236*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
237*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Test skipped because libpfm is not supported.";
238*dbb99499SAndroid Build Coastguard Worker }
239*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
240*dbb99499SAndroid Build Coastguard Worker PerfCounterValues before(2);
241*dbb99499SAndroid Build Coastguard Worker PerfCounterValues after(2);
242*dbb99499SAndroid Build Coastguard Worker
243*dbb99499SAndroid Build Coastguard Worker // Notice that this test will work even if we taskset it to a single CPU
244*dbb99499SAndroid Build Coastguard Worker // In this case the threads will run sequentially
245*dbb99499SAndroid Build Coastguard Worker // Start two threads and measure the number of combined cycles and
246*dbb99499SAndroid Build Coastguard Worker // instructions
247*dbb99499SAndroid Build Coastguard Worker measure(2, &before, &after);
248*dbb99499SAndroid Build Coastguard Worker std::vector<double> Elapsed2Threads{
249*dbb99499SAndroid Build Coastguard Worker static_cast<double>(after[0] - before[0]),
250*dbb99499SAndroid Build Coastguard Worker static_cast<double>(after[1] - before[1])};
251*dbb99499SAndroid Build Coastguard Worker
252*dbb99499SAndroid Build Coastguard Worker // Start four threads and measure the number of combined cycles and
253*dbb99499SAndroid Build Coastguard Worker // instructions
254*dbb99499SAndroid Build Coastguard Worker measure(4, &before, &after);
255*dbb99499SAndroid Build Coastguard Worker std::vector<double> Elapsed4Threads{
256*dbb99499SAndroid Build Coastguard Worker static_cast<double>(after[0] - before[0]),
257*dbb99499SAndroid Build Coastguard Worker static_cast<double>(after[1] - before[1])};
258*dbb99499SAndroid Build Coastguard Worker
259*dbb99499SAndroid Build Coastguard Worker // The following expectations fail (at least on a beefy workstation with lots
260*dbb99499SAndroid Build Coastguard Worker // of cpus) - it seems that in some circumstances the runtime of 4 threads
261*dbb99499SAndroid Build Coastguard Worker // can even be better than with 2.
262*dbb99499SAndroid Build Coastguard Worker // So instead of expecting 4 threads to be slower, let's just make sure they
263*dbb99499SAndroid Build Coastguard Worker // do not differ too much in general (one is not more than 10x than the
264*dbb99499SAndroid Build Coastguard Worker // other).
265*dbb99499SAndroid Build Coastguard Worker EXPECT_THAT(Elapsed4Threads[0] / Elapsed2Threads[0], AllOf(Gt(0.1), Lt(10)));
266*dbb99499SAndroid Build Coastguard Worker EXPECT_THAT(Elapsed4Threads[1] / Elapsed2Threads[1], AllOf(Gt(0.1), Lt(10)));
267*dbb99499SAndroid Build Coastguard Worker }
268*dbb99499SAndroid Build Coastguard Worker
TEST(PerfCountersTest,HardwareLimits)269*dbb99499SAndroid Build Coastguard Worker TEST(PerfCountersTest, HardwareLimits) {
270*dbb99499SAndroid Build Coastguard Worker // The test works (i.e. causes read to fail) for the assumptions
271*dbb99499SAndroid Build Coastguard Worker // about hardware capabilities (i.e. small number (3-4) hardware
272*dbb99499SAndroid Build Coastguard Worker // counters) at this date,
273*dbb99499SAndroid Build Coastguard Worker // the same as previous test ReopenExistingCounters.
274*dbb99499SAndroid Build Coastguard Worker if (!PerfCounters::kSupported) {
275*dbb99499SAndroid Build Coastguard Worker GTEST_SKIP() << "Test skipped because libpfm is not supported.\n";
276*dbb99499SAndroid Build Coastguard Worker }
277*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(PerfCounters::Initialize());
278*dbb99499SAndroid Build Coastguard Worker
279*dbb99499SAndroid Build Coastguard Worker // Taken from `perf list`, but focusses only on those HW events that actually
280*dbb99499SAndroid Build Coastguard Worker // were reported when running `sudo perf stat -a sleep 10`, intersected over
281*dbb99499SAndroid Build Coastguard Worker // several platforms. All HW events listed in the first command not reported
282*dbb99499SAndroid Build Coastguard Worker // in the second seem to not work. This is sad as we don't really get to test
283*dbb99499SAndroid Build Coastguard Worker // the grouping here (groups can contain up to 6 members)...
284*dbb99499SAndroid Build Coastguard Worker std::vector<std::string> counter_names{
285*dbb99499SAndroid Build Coastguard Worker "cycles", // leader
286*dbb99499SAndroid Build Coastguard Worker "instructions", //
287*dbb99499SAndroid Build Coastguard Worker "branch-misses", //
288*dbb99499SAndroid Build Coastguard Worker };
289*dbb99499SAndroid Build Coastguard Worker
290*dbb99499SAndroid Build Coastguard Worker // In the off-chance that some of these values are not supported,
291*dbb99499SAndroid Build Coastguard Worker // we filter them out so the test will complete without failure
292*dbb99499SAndroid Build Coastguard Worker // albeit it might not actually test the grouping on that platform
293*dbb99499SAndroid Build Coastguard Worker std::vector<std::string> valid_names;
294*dbb99499SAndroid Build Coastguard Worker for (const std::string& name : counter_names) {
295*dbb99499SAndroid Build Coastguard Worker if (PerfCounters::IsCounterSupported(name)) {
296*dbb99499SAndroid Build Coastguard Worker valid_names.push_back(name);
297*dbb99499SAndroid Build Coastguard Worker }
298*dbb99499SAndroid Build Coastguard Worker }
299*dbb99499SAndroid Build Coastguard Worker PerfCountersMeasurement counter(valid_names);
300*dbb99499SAndroid Build Coastguard Worker
301*dbb99499SAndroid Build Coastguard Worker std::vector<std::pair<std::string, double>> measurements;
302*dbb99499SAndroid Build Coastguard Worker
303*dbb99499SAndroid Build Coastguard Worker counter.Start();
304*dbb99499SAndroid Build Coastguard Worker EXPECT_TRUE(counter.Stop(measurements));
305*dbb99499SAndroid Build Coastguard Worker }
306*dbb99499SAndroid Build Coastguard Worker
307*dbb99499SAndroid Build Coastguard Worker } // namespace
308