Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for collection of more PMUs than are physically available. #1737

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions src/perf_counters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ PerfCounters PerfCounters::Create(
Initialize();
}

// Initially try to create a single group which holds all PMUs since that
// has lower overhead. Group multiplexing doesn't work on all platforms so if
// that fails try again without using groups.
bool group_pmus = true;
retry_without_groups:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe extracting this into a separate method and calling it with group_pmus as a parameter (and having a return value to indicate whether retry should happen) would be cleaner than a goto


// Valid counters will populate these arrays but we start empty
std::vector<std::string> valid_names;
std::vector<int> counter_ids;
Expand All @@ -96,11 +102,6 @@ PerfCounters PerfCounters::Create(
counter_ids.reserve(counter_names.size());

const int kCounterMode = PFM_PLM3; // user mode only

// Group leads will be assigned on demand. The idea is that once we cannot
// create a counter descriptor, the reason is that this group has maxed out
// so we set the group_id again to -1 and retry - giving the algorithm a
// chance to create a new group leader to hold the next set of counters.
int group_id = -1;

// Loop through all performance counters
Expand Down Expand Up @@ -150,7 +151,7 @@ PerfCounters PerfCounters::Create(
// case.
attr.disabled = is_first;
attr.inherit = true;
attr.pinned = is_first;
attr.pinned = group_pmus;
attr.exclude_kernel = true;
attr.exclude_user = false;
attr.exclude_hv = true;
Expand All @@ -171,10 +172,14 @@ PerfCounters PerfCounters::Create(
}
if (id < 0) {
// If the file descriptor is negative we might have reached a limit
// in the current group. Set the group_id to -1 and retry
if (group_id >= 0) {
// Create a new group
group_id = -1;
// in the current group. Let's try again without groups.
if (group_id >= 0 && group_pmus) {
// Close all performance counters
for (int close_id : counter_ids) {
::close(close_id);
}
group_pmus = false;
goto retry_without_groups;
} else {
// At this point we have already retried to set a new group id and
// failed. We then give up.
Expand All @@ -197,7 +202,9 @@ PerfCounters PerfCounters::Create(
if (group_id < 0) {
// This is a leader, store and assign it to the current file descriptor
leader_ids.push_back(id);
group_id = id;
if (group_pmus) {
group_id = id;
}
}
// This is a valid counter, add it to our descriptor's list
counter_ids.push_back(id);
Expand All @@ -214,9 +221,9 @@ PerfCounters PerfCounters::Create(
// This should never happen but if it does, we give up on the
// entire batch as recovery would be a mess.
GetErrorLogInstance() << "***WARNING*** Failed to start counters. "
"Claring out all counters.\n";
"Clearing out all counters.\n";

// Close all peformance counters
// Close all performance counters
for (int id : counter_ids) {
::close(id);
}
Expand Down Expand Up @@ -254,7 +261,7 @@ bool PerfCounters::IsCounterSupported(const std::string&) { return false; }
PerfCounters PerfCounters::Create(
const std::vector<std::string>& counter_names) {
if (!counter_names.empty()) {
GetErrorLogInstance() << "Performance counters not supported.\n";
GetErrorLogInstance() << "Performance counters not supported.";
}
return NoCounters();
}
Expand All @@ -280,3 +287,4 @@ PerfCounters& PerfCounters::operator=(PerfCounters&& other) noexcept {
}
} // namespace internal
} // namespace benchmark

2 changes: 1 addition & 1 deletion src/perf_counters.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class BENCHMARK_EXPORT PerfCounterValues {
}

// This reading is complex and as the goal of this class is to
// abstract away the intrincacies of the reading process, this is
// abstract away the intricacies of the reading process, this is
// a better place for it
size_t Read(const std::vector<int>& leaders);

Expand Down