1*dbb99499SAndroid Build Coastguard Worker // Copyright 2021 Google Inc. All rights reserved. 2*dbb99499SAndroid Build Coastguard Worker // 3*dbb99499SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*dbb99499SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*dbb99499SAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*dbb99499SAndroid Build Coastguard Worker // 7*dbb99499SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 8*dbb99499SAndroid Build Coastguard Worker // 9*dbb99499SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*dbb99499SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*dbb99499SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*dbb99499SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*dbb99499SAndroid Build Coastguard Worker // limitations under the License. 14*dbb99499SAndroid Build Coastguard Worker 15*dbb99499SAndroid Build Coastguard Worker #ifndef BENCHMARK_PERF_COUNTERS_H 16*dbb99499SAndroid Build Coastguard Worker #define BENCHMARK_PERF_COUNTERS_H 17*dbb99499SAndroid Build Coastguard Worker 18*dbb99499SAndroid Build Coastguard Worker #include <array> 19*dbb99499SAndroid Build Coastguard Worker #include <cstdint> 20*dbb99499SAndroid Build Coastguard Worker #include <cstring> 21*dbb99499SAndroid Build Coastguard Worker #include <memory> 22*dbb99499SAndroid Build Coastguard Worker #include <vector> 23*dbb99499SAndroid Build Coastguard Worker 24*dbb99499SAndroid Build Coastguard Worker #include "benchmark/benchmark.h" 25*dbb99499SAndroid Build Coastguard Worker #include "check.h" 26*dbb99499SAndroid Build Coastguard Worker #include "log.h" 27*dbb99499SAndroid Build Coastguard Worker #include "mutex.h" 28*dbb99499SAndroid Build Coastguard Worker 29*dbb99499SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_WINDOWS 30*dbb99499SAndroid Build Coastguard Worker #include <unistd.h> 31*dbb99499SAndroid Build Coastguard Worker #endif 32*dbb99499SAndroid Build Coastguard Worker 33*dbb99499SAndroid Build Coastguard Worker #if defined(_MSC_VER) 34*dbb99499SAndroid Build Coastguard Worker #pragma warning(push) 35*dbb99499SAndroid Build Coastguard Worker // C4251: <symbol> needs to have dll-interface to be used by clients of class 36*dbb99499SAndroid Build Coastguard Worker #pragma warning(disable : 4251) 37*dbb99499SAndroid Build Coastguard Worker #endif 38*dbb99499SAndroid Build Coastguard Worker 39*dbb99499SAndroid Build Coastguard Worker namespace benchmark { 40*dbb99499SAndroid Build Coastguard Worker namespace internal { 41*dbb99499SAndroid Build Coastguard Worker 42*dbb99499SAndroid Build Coastguard Worker // Typically, we can only read a small number of counters. There is also a 43*dbb99499SAndroid Build Coastguard Worker // padding preceding counter values, when reading multiple counters with one 44*dbb99499SAndroid Build Coastguard Worker // syscall (which is desirable). PerfCounterValues abstracts these details. 45*dbb99499SAndroid Build Coastguard Worker // The implementation ensures the storage is inlined, and allows 0-based 46*dbb99499SAndroid Build Coastguard Worker // indexing into the counter values. 47*dbb99499SAndroid Build Coastguard Worker // The object is used in conjunction with a PerfCounters object, by passing it 48*dbb99499SAndroid Build Coastguard Worker // to Snapshot(). The Read() method relocates individual reads, discarding 49*dbb99499SAndroid Build Coastguard Worker // the initial padding from each group leader in the values buffer such that 50*dbb99499SAndroid Build Coastguard Worker // all user accesses through the [] operator are correct. 51*dbb99499SAndroid Build Coastguard Worker class BENCHMARK_EXPORT PerfCounterValues { 52*dbb99499SAndroid Build Coastguard Worker public: PerfCounterValues(size_t nr_counters)53*dbb99499SAndroid Build Coastguard Worker explicit PerfCounterValues(size_t nr_counters) : nr_counters_(nr_counters) { 54*dbb99499SAndroid Build Coastguard Worker BM_CHECK_LE(nr_counters_, kMaxCounters); 55*dbb99499SAndroid Build Coastguard Worker } 56*dbb99499SAndroid Build Coastguard Worker 57*dbb99499SAndroid Build Coastguard Worker // We are reading correctly now so the values don't need to skip padding 58*dbb99499SAndroid Build Coastguard Worker uint64_t operator[](size_t pos) const { return values_[pos]; } 59*dbb99499SAndroid Build Coastguard Worker 60*dbb99499SAndroid Build Coastguard Worker // Increased the maximum to 32 only since the buffer 61*dbb99499SAndroid Build Coastguard Worker // is std::array<> backed 62*dbb99499SAndroid Build Coastguard Worker static constexpr size_t kMaxCounters = 32; 63*dbb99499SAndroid Build Coastguard Worker 64*dbb99499SAndroid Build Coastguard Worker private: 65*dbb99499SAndroid Build Coastguard Worker friend class PerfCounters; 66*dbb99499SAndroid Build Coastguard Worker // Get the byte buffer in which perf counters can be captured. 67*dbb99499SAndroid Build Coastguard Worker // This is used by PerfCounters::Read get_data_buffer()68*dbb99499SAndroid Build Coastguard Worker std::pair<char*, size_t> get_data_buffer() { 69*dbb99499SAndroid Build Coastguard Worker return {reinterpret_cast<char*>(values_.data()), 70*dbb99499SAndroid Build Coastguard Worker sizeof(uint64_t) * (kPadding + nr_counters_)}; 71*dbb99499SAndroid Build Coastguard Worker } 72*dbb99499SAndroid Build Coastguard Worker 73*dbb99499SAndroid Build Coastguard Worker // This reading is complex and as the goal of this class is to 74*dbb99499SAndroid Build Coastguard Worker // abstract away the intrincacies of the reading process, this is 75*dbb99499SAndroid Build Coastguard Worker // a better place for it 76*dbb99499SAndroid Build Coastguard Worker size_t Read(const std::vector<int>& leaders); 77*dbb99499SAndroid Build Coastguard Worker 78*dbb99499SAndroid Build Coastguard Worker // Move the padding to 2 due to the reading algorithm (1st padding plus a 79*dbb99499SAndroid Build Coastguard Worker // current read padding) 80*dbb99499SAndroid Build Coastguard Worker static constexpr size_t kPadding = 2; 81*dbb99499SAndroid Build Coastguard Worker std::array<uint64_t, kPadding + kMaxCounters> values_; 82*dbb99499SAndroid Build Coastguard Worker const size_t nr_counters_; 83*dbb99499SAndroid Build Coastguard Worker }; 84*dbb99499SAndroid Build Coastguard Worker 85*dbb99499SAndroid Build Coastguard Worker // Collect PMU counters. The object, once constructed, is ready to be used by 86*dbb99499SAndroid Build Coastguard Worker // calling read(). PMU counter collection is enabled from the time create() is 87*dbb99499SAndroid Build Coastguard Worker // called, to obtain the object, until the object's destructor is called. 88*dbb99499SAndroid Build Coastguard Worker class BENCHMARK_EXPORT PerfCounters final { 89*dbb99499SAndroid Build Coastguard Worker public: 90*dbb99499SAndroid Build Coastguard Worker // True iff this platform supports performance counters. 91*dbb99499SAndroid Build Coastguard Worker static const bool kSupported; 92*dbb99499SAndroid Build Coastguard Worker 93*dbb99499SAndroid Build Coastguard Worker // Returns an empty object NoCounters()94*dbb99499SAndroid Build Coastguard Worker static PerfCounters NoCounters() { return PerfCounters(); } 95*dbb99499SAndroid Build Coastguard Worker ~PerfCounters()96*dbb99499SAndroid Build Coastguard Worker ~PerfCounters() { CloseCounters(); } 97*dbb99499SAndroid Build Coastguard Worker PerfCounters() = default; 98*dbb99499SAndroid Build Coastguard Worker PerfCounters(PerfCounters&&) = default; 99*dbb99499SAndroid Build Coastguard Worker PerfCounters(const PerfCounters&) = delete; 100*dbb99499SAndroid Build Coastguard Worker PerfCounters& operator=(PerfCounters&&) noexcept; 101*dbb99499SAndroid Build Coastguard Worker PerfCounters& operator=(const PerfCounters&) = delete; 102*dbb99499SAndroid Build Coastguard Worker 103*dbb99499SAndroid Build Coastguard Worker // Platform-specific implementations may choose to do some library 104*dbb99499SAndroid Build Coastguard Worker // initialization here. 105*dbb99499SAndroid Build Coastguard Worker static bool Initialize(); 106*dbb99499SAndroid Build Coastguard Worker 107*dbb99499SAndroid Build Coastguard Worker // Check if the given counter is supported, if the app wants to 108*dbb99499SAndroid Build Coastguard Worker // check before passing 109*dbb99499SAndroid Build Coastguard Worker static bool IsCounterSupported(const std::string& name); 110*dbb99499SAndroid Build Coastguard Worker 111*dbb99499SAndroid Build Coastguard Worker // Return a PerfCounters object ready to read the counters with the names 112*dbb99499SAndroid Build Coastguard Worker // specified. The values are user-mode only. The counter name format is 113*dbb99499SAndroid Build Coastguard Worker // implementation and OS specific. 114*dbb99499SAndroid Build Coastguard Worker // In case of failure, this method will in the worst case return an 115*dbb99499SAndroid Build Coastguard Worker // empty object whose state will still be valid. 116*dbb99499SAndroid Build Coastguard Worker static PerfCounters Create(const std::vector<std::string>& counter_names); 117*dbb99499SAndroid Build Coastguard Worker 118*dbb99499SAndroid Build Coastguard Worker // Take a snapshot of the current value of the counters into the provided 119*dbb99499SAndroid Build Coastguard Worker // valid PerfCounterValues storage. The values are populated such that: 120*dbb99499SAndroid Build Coastguard Worker // names()[i]'s value is (*values)[i] Snapshot(PerfCounterValues * values)121*dbb99499SAndroid Build Coastguard Worker BENCHMARK_ALWAYS_INLINE bool Snapshot(PerfCounterValues* values) const { 122*dbb99499SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_WINDOWS 123*dbb99499SAndroid Build Coastguard Worker assert(values != nullptr); 124*dbb99499SAndroid Build Coastguard Worker return values->Read(leader_ids_) == counter_ids_.size(); 125*dbb99499SAndroid Build Coastguard Worker #else 126*dbb99499SAndroid Build Coastguard Worker (void)values; 127*dbb99499SAndroid Build Coastguard Worker return false; 128*dbb99499SAndroid Build Coastguard Worker #endif 129*dbb99499SAndroid Build Coastguard Worker } 130*dbb99499SAndroid Build Coastguard Worker names()131*dbb99499SAndroid Build Coastguard Worker const std::vector<std::string>& names() const { return counter_names_; } num_counters()132*dbb99499SAndroid Build Coastguard Worker size_t num_counters() const { return counter_names_.size(); } 133*dbb99499SAndroid Build Coastguard Worker 134*dbb99499SAndroid Build Coastguard Worker private: PerfCounters(const std::vector<std::string> & counter_names,std::vector<int> && counter_ids,std::vector<int> && leader_ids)135*dbb99499SAndroid Build Coastguard Worker PerfCounters(const std::vector<std::string>& counter_names, 136*dbb99499SAndroid Build Coastguard Worker std::vector<int>&& counter_ids, std::vector<int>&& leader_ids) 137*dbb99499SAndroid Build Coastguard Worker : counter_ids_(std::move(counter_ids)), 138*dbb99499SAndroid Build Coastguard Worker leader_ids_(std::move(leader_ids)), 139*dbb99499SAndroid Build Coastguard Worker counter_names_(counter_names) {} 140*dbb99499SAndroid Build Coastguard Worker 141*dbb99499SAndroid Build Coastguard Worker void CloseCounters() const; 142*dbb99499SAndroid Build Coastguard Worker 143*dbb99499SAndroid Build Coastguard Worker std::vector<int> counter_ids_; 144*dbb99499SAndroid Build Coastguard Worker std::vector<int> leader_ids_; 145*dbb99499SAndroid Build Coastguard Worker std::vector<std::string> counter_names_; 146*dbb99499SAndroid Build Coastguard Worker }; 147*dbb99499SAndroid Build Coastguard Worker 148*dbb99499SAndroid Build Coastguard Worker // Typical usage of the above primitives. 149*dbb99499SAndroid Build Coastguard Worker class BENCHMARK_EXPORT PerfCountersMeasurement final { 150*dbb99499SAndroid Build Coastguard Worker public: 151*dbb99499SAndroid Build Coastguard Worker PerfCountersMeasurement(const std::vector<std::string>& counter_names); 152*dbb99499SAndroid Build Coastguard Worker num_counters()153*dbb99499SAndroid Build Coastguard Worker size_t num_counters() const { return counters_.num_counters(); } 154*dbb99499SAndroid Build Coastguard Worker names()155*dbb99499SAndroid Build Coastguard Worker std::vector<std::string> names() const { return counters_.names(); } 156*dbb99499SAndroid Build Coastguard Worker Start()157*dbb99499SAndroid Build Coastguard Worker BENCHMARK_ALWAYS_INLINE bool Start() { 158*dbb99499SAndroid Build Coastguard Worker if (num_counters() == 0) return true; 159*dbb99499SAndroid Build Coastguard Worker // Tell the compiler to not move instructions above/below where we take 160*dbb99499SAndroid Build Coastguard Worker // the snapshot. 161*dbb99499SAndroid Build Coastguard Worker ClobberMemory(); 162*dbb99499SAndroid Build Coastguard Worker valid_read_ &= counters_.Snapshot(&start_values_); 163*dbb99499SAndroid Build Coastguard Worker ClobberMemory(); 164*dbb99499SAndroid Build Coastguard Worker 165*dbb99499SAndroid Build Coastguard Worker return valid_read_; 166*dbb99499SAndroid Build Coastguard Worker } 167*dbb99499SAndroid Build Coastguard Worker Stop(std::vector<std::pair<std::string,double>> & measurements)168*dbb99499SAndroid Build Coastguard Worker BENCHMARK_ALWAYS_INLINE bool Stop( 169*dbb99499SAndroid Build Coastguard Worker std::vector<std::pair<std::string, double>>& measurements) { 170*dbb99499SAndroid Build Coastguard Worker if (num_counters() == 0) return true; 171*dbb99499SAndroid Build Coastguard Worker // Tell the compiler to not move instructions above/below where we take 172*dbb99499SAndroid Build Coastguard Worker // the snapshot. 173*dbb99499SAndroid Build Coastguard Worker ClobberMemory(); 174*dbb99499SAndroid Build Coastguard Worker valid_read_ &= counters_.Snapshot(&end_values_); 175*dbb99499SAndroid Build Coastguard Worker ClobberMemory(); 176*dbb99499SAndroid Build Coastguard Worker 177*dbb99499SAndroid Build Coastguard Worker for (size_t i = 0; i < counters_.names().size(); ++i) { 178*dbb99499SAndroid Build Coastguard Worker double measurement = static_cast<double>(end_values_[i]) - 179*dbb99499SAndroid Build Coastguard Worker static_cast<double>(start_values_[i]); 180*dbb99499SAndroid Build Coastguard Worker measurements.push_back({counters_.names()[i], measurement}); 181*dbb99499SAndroid Build Coastguard Worker } 182*dbb99499SAndroid Build Coastguard Worker 183*dbb99499SAndroid Build Coastguard Worker return valid_read_; 184*dbb99499SAndroid Build Coastguard Worker } 185*dbb99499SAndroid Build Coastguard Worker 186*dbb99499SAndroid Build Coastguard Worker private: 187*dbb99499SAndroid Build Coastguard Worker PerfCounters counters_; 188*dbb99499SAndroid Build Coastguard Worker bool valid_read_ = true; 189*dbb99499SAndroid Build Coastguard Worker PerfCounterValues start_values_; 190*dbb99499SAndroid Build Coastguard Worker PerfCounterValues end_values_; 191*dbb99499SAndroid Build Coastguard Worker }; 192*dbb99499SAndroid Build Coastguard Worker 193*dbb99499SAndroid Build Coastguard Worker } // namespace internal 194*dbb99499SAndroid Build Coastguard Worker } // namespace benchmark 195*dbb99499SAndroid Build Coastguard Worker 196*dbb99499SAndroid Build Coastguard Worker #if defined(_MSC_VER) 197*dbb99499SAndroid Build Coastguard Worker #pragma warning(pop) 198*dbb99499SAndroid Build Coastguard Worker #endif 199*dbb99499SAndroid Build Coastguard Worker 200*dbb99499SAndroid Build Coastguard Worker #endif // BENCHMARK_PERF_COUNTERS_H 201