1
0
mirror of https://github.com/google/benchmark.git synced 2025-04-29 14:30:37 +08:00

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.
This commit is contained in:
Jesse Rosenstock 2023-08-24 07:29:18 +02:00
parent e73915667c
commit cb5fc2d77a
2 changed files with 14 additions and 3 deletions

View File

@ -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
static bool InitLibPfmOnce() {
// Function-scope static gets initialized only once on first call.
static bool success = []() { return pfm_initialize() == PFM_SUCCESS; }();
return success;
}
bool PerfCounters::Initialize() { return InitLibPfmOnce(); }
bool PerfCounters::IsCounterSupported(const std::string& name) {
InitLibPfmOnce();
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()) {
InitLibPfmOnce();
}
// Valid counters will populate these arrays but we start empty
std::vector<std::string> valid_names;
std::vector<int> counter_ids;

View File

@ -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