Commit 108d547b authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

base::CPU: Return no-destruct reference from GuessCoreTypes()

Currently, base::CPU::GuessCoreTypes() is called in multiple places and
executes the same code multiple times, even though the result is
constant. There's already some static caching in different places.

This patch moves the static caching into base::CPU::GuessCoreTypes()
and renames it to base::CPU::GetGuessedCoreTypes().

Bug: 1081760
Change-Id: Ifaff01cc19abc48a36d5fe19bc4cb9a9cfa4fd24
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463309
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816122}
parent 265aefa0
......@@ -388,16 +388,14 @@ bool ParseTimeInState(const std::string& content,
return true;
}
} // namespace
// static
std::vector<CPU::CoreType> CPU::GuessCoreTypes() {
std::vector<CPU::CoreType> GuessCoreTypes() {
// Try to guess the CPU architecture and cores of each cluster by comparing
// the maximum frequencies of the available (online and offline) cores.
const char kCPUMaxFreqPath[] =
"/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq";
int num_cpus = SysInfo::NumberOfProcessors();
std::vector<CPU::CoreType> core_index_to_type(num_cpus, CoreType::kUnknown);
std::vector<CPU::CoreType> core_index_to_type(num_cpus,
CPU::CoreType::kUnknown);
std::vector<uint32_t> max_core_frequencies_mhz(num_cpus, 0);
flat_set<uint32_t> frequencies_mhz;
......@@ -424,9 +422,9 @@ std::vector<CPU::CoreType> CPU::GuessCoreTypes() {
for (int core_index = 0; core_index < num_cpus; ++core_index) {
uint32_t core_frequency_mhz = max_core_frequencies_mhz[core_index];
CoreType core_type = CoreType::kOther;
CPU::CoreType core_type = CPU::CoreType::kOther;
if (num_frequencies == 1u) {
core_type = CoreType::kSymmetric;
core_type = CPU::CoreType::kSymmetric;
} else if (num_frequencies == 2u || num_frequencies == 3u) {
auto it = frequencies_mhz.find(core_frequency_mhz);
if (it != frequencies_mhz.end()) {
......@@ -435,16 +433,17 @@ std::vector<CPU::CoreType> CPU::GuessCoreTypes() {
switch (frequency_index) {
case 0:
core_type = num_frequencies == 2u
? CoreType::kBigLittle_Little
: CoreType::kBigLittleBigger_Little;
? CPU::CoreType::kBigLittle_Little
: CPU::CoreType::kBigLittleBigger_Little;
break;
case 1:
core_type = num_frequencies == 2u ? CoreType::kBigLittle_Big
: CoreType::kBigLittleBigger_Big;
core_type = num_frequencies == 2u
? CPU::CoreType::kBigLittle_Big
: CPU::CoreType::kBigLittleBigger_Big;
break;
case 2:
DCHECK_EQ(num_frequencies, 3u);
core_type = CoreType::kBigLittleBigger_Bigger;
core_type = CPU::CoreType::kBigLittleBigger_Bigger;
break;
default:
NOTREACHED();
......@@ -458,6 +457,14 @@ std::vector<CPU::CoreType> CPU::GuessCoreTypes() {
return core_index_to_type;
}
} // namespace
// static
const std::vector<CPU::CoreType>& CPU::GetGuessedCoreTypes() {
static NoDestructor<std::vector<CoreType>> kCoreTypes(GuessCoreTypes());
return *kCoreTypes.get();
}
// static
bool CPU::GetTimeInState(TimeInState& time_in_state) {
time_in_state.clear();
......@@ -467,7 +474,7 @@ bool CPU::GetTimeInState(TimeInState& time_in_state) {
if (!kSupportsTimeInState)
return false;
static NoDestructor<std::vector<CoreType>> kCoreTypes(GuessCoreTypes());
static const std::vector<CoreType>& kCoreTypes = GetGuessedCoreTypes();
// time_in_state is reported per cluster. Identify the first cores of each
// cluster.
......@@ -516,7 +523,7 @@ bool CPU::GetTimeInState(TimeInState& time_in_state) {
if (!ReadFileToString(time_in_state_path, &buffer))
return false;
if (!ParseTimeInState(buffer, (*kCoreTypes)[cluster_core_index],
if (!ParseTimeInState(buffer, kCoreTypes[cluster_core_index],
cluster_core_index, time_in_state)) {
return false;
}
......
......@@ -90,10 +90,9 @@ class BASE_EXPORT CPU final {
// Attempts to guess the core types of individual CPU cores based on frequency
// information from /sys/devices/system/cpu/cpuN/cpufreq/cpuinfo_max_freq.
// Beware that it is kernel/hardware dependent whether the information from
// sys is accurate.
//
// Returns a vector with the guessed type for core N at index N.
static std::vector<CoreType> GuessCoreTypes();
// sys is accurate. Returns a reference to a static-storage vector (leaked on
// shutdown) with the guessed type for core N at index N.
static const std::vector<CoreType>& GetGuessedCoreTypes();
struct TimeInStateEntry {
CPU::CoreType core_type; // type of the cores in this cluster.
......
......@@ -17,7 +17,7 @@ const cpu_set_t& AllCores() {
static const cpu_set_t kAllCores = []() {
cpu_set_t set;
CPU_ZERO(&set);
std::vector<CPU::CoreType> core_types = CPU::GuessCoreTypes();
const std::vector<CPU::CoreType>& core_types = CPU::GetGuessedCoreTypes();
if (core_types.empty()) {
memset(&set, 0xff, sizeof(set));
} else {
......@@ -31,7 +31,7 @@ const cpu_set_t& AllCores() {
const cpu_set_t& LittleCores() {
static const cpu_set_t kLittleCores = []() {
std::vector<CPU::CoreType> core_types = CPU::GuessCoreTypes();
const std::vector<CPU::CoreType>& core_types = CPU::GetGuessedCoreTypes();
if (core_types.empty())
return AllCores();
......@@ -64,7 +64,7 @@ const cpu_set_t& LittleCores() {
bool HasBigCpuCores() {
static const bool kHasBigCores = []() {
std::vector<CPU::CoreType> core_types = CPU::GuessCoreTypes();
const std::vector<CPU::CoreType>& core_types = CPU::GetGuessedCoreTypes();
if (core_types.empty())
return false;
for (CPU::CoreType core_type : core_types) {
......
......@@ -249,9 +249,6 @@ class BASE_EXPORT ProcessMetrics {
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \
defined(OS_AIX)
CPU::CoreType GetCoreType(int core_index);
// Initialized on the first call to GetCoreType().
base::Optional<std::vector<CPU::CoreType>> core_index_to_type_;
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) ||
// defined(OS_AIX)
......
......@@ -481,13 +481,10 @@ bool ProcessMetrics::ParseProcTimeInState(
}
CPU::CoreType ProcessMetrics::GetCoreType(int core_index) {
if (!core_index_to_type_)
core_index_to_type_ = CPU::GuessCoreTypes();
if (static_cast<size_t>(core_index) >= core_index_to_type_->size())
const std::vector<CPU::CoreType>& core_types = CPU::GetGuessedCoreTypes();
if (static_cast<size_t>(core_index) >= core_types.size())
return CPU::CoreType::kUnknown;
return core_index_to_type_->at(static_cast<size_t>(core_index));
return core_types[static_cast<size_t>(core_index)];
}
const char kProcSelfExe[] = "/proc/self/exe";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment