aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Rosenstock <jmr@google.com>2023-08-24 11:04:09 +0200
committerGitHub <noreply@github.com>2023-08-24 10:04:09 +0100
commit9c65aebb266f35b035c5d2a46a19b795d6bf23c8 (patch)
treeb42c4ddfc318e961c4c6069dc462f76178ac74e0
parente73915667c21faccd7019c6da8ab083b0264db13 (diff)
downloadgoogle-benchmark-9c65aebb266f35b035c5d2a46a19b795d6bf23c8.tar.gz
perf_counters: Initialize once only when needed (#1656)
* perf_counters: Initialize once only when needed This works around some performance problems running Android under QEMU. Calling `pfm_initialize` was very slow, and was called during dynamic initialization (before `main` or when loaded as a shared library). This happened whenever benchmark was linked, even if no benchmarks were run. Instead, call `pfm_initialize` at most once, and only when one of: 1. `PerfCounters::Initialize` is called 2. `PerfCounters::Create` is called with a non-empty counter list 3. `PerfCounters::IsCounterSupported` is called The return value of the first `pfm_initialize()` is saved and returned from all subsequent `PerfCounters::Initialize` calls. * perf_counters: Make success var const * InitLibPfmOnce: Inline function
-rw-r--r--src/perf_counters.cc15
-rw-r--r--src/perf_counters.h2
2 files changed, 14 insertions, 3 deletions
diff --git a/src/perf_counters.cc b/src/perf_counters.cc
index 3980ea0..417acdb 100644
--- a/src/perf_counters.cc
+++ b/src/perf_counters.cc
@@ -57,9 +57,18 @@ size_t PerfCounterValues::Read(const std::vector<int>& leaders) {
const bool PerfCounters::kSupported = true;
-bool PerfCounters::Initialize() { return pfm_initialize() == PFM_SUCCESS; }
+// Initializes libpfm only on the first call. Returns whether that single
+// initialization was successful.
+bool PerfCounters::Initialize() {
+ // Function-scope static gets initialized only once on first call.
+ static const bool success = []() {
+ return pfm_initialize() == PFM_SUCCESS;
+ }();
+ return success;
+}
bool PerfCounters::IsCounterSupported(const std::string& name) {
+ Initialize();
perf_event_attr_t attr;
std::memset(&attr, 0, sizeof(attr));
pfm_perf_encode_arg_t arg;
@@ -73,6 +82,10 @@ bool PerfCounters::IsCounterSupported(const std::string& name) {
PerfCounters PerfCounters::Create(
const std::vector<std::string>& counter_names) {
+ if (!counter_names.empty()) {
+ Initialize();
+ }
+
// Valid counters will populate these arrays but we start empty
std::vector<std::string> valid_names;
std::vector<int> counter_ids;
diff --git a/src/perf_counters.h b/src/perf_counters.h
index 152a6f2..bf5eb6b 100644
--- a/src/perf_counters.h
+++ b/src/perf_counters.h
@@ -190,8 +190,6 @@ class BENCHMARK_EXPORT PerfCountersMeasurement final {
PerfCounterValues end_values_;
};
-BENCHMARK_UNUSED static bool perf_init_anchor = PerfCounters::Initialize();
-
} // namespace internal
} // namespace benchmark