Commit 4d5e8304 authored by Bailey Berro's avatar Bailey Berro Committed by Commit Bot

Add information about CPU throttling to SystemDataProvider

This change adds a cpu_max_clock_speed_khz field to SystemInfo and a
scaling_current_frequency_khz to CpuUsage.

Bug: 1128204
Change-Id: I1773748f1fc307564e2a98d7504f3823e1e08c75
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2532765
Commit-Queue: Bailey Berro <baileyberro@chromium.org>
Commit-Queue: Dominick Ng <dominickn@chromium.org>
Auto-Submit: Bailey Berro <baileyberro@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#830838}
parent 6507c9cc
...@@ -39,6 +39,7 @@ export function fakeSystemDataProviderTestSuite() { ...@@ -39,6 +39,7 @@ export function fakeSystemDataProviderTestSuite() {
marketingName: 'Bestest 1000', marketingName: 'Bestest 1000',
totalMemoryKib: 9999, totalMemoryKib: 9999,
cpuThreadsCount: 4, cpuThreadsCount: 4,
cpuMaxClockSpeedKhz: 1000,
versionInfo: version, versionInfo: version,
deviceCapabilities: capabilities, deviceCapabilities: capabilities,
}; };
......
...@@ -62,6 +62,17 @@ void PopulateCpuInfo(const healthd::CpuInfo& cpu_info, ...@@ -62,6 +62,17 @@ void PopulateCpuInfo(const healthd::CpuInfo& cpu_info,
// If there is more than one physical cpu on the device, use the name of the // If there is more than one physical cpu on the device, use the name of the
// first CPU. // first CPU.
out_system_info.cpu_model_name = physical_cpus[0]->model_name.value_or(""); out_system_info.cpu_model_name = physical_cpus[0]->model_name.value_or("");
// Calculate `max_clock_speed_khz` as the average of all logical core clock
// speeds until we decide the best way to consume the information in the UI.
uint32_t total_max_ghz = 0;
for (const auto& logical_cpu_ptr : physical_cpus[0]->logical_cpus) {
total_max_ghz += logical_cpu_ptr->max_clock_speed_khz;
}
// Integer division.
out_system_info.cpu_max_clock_speed_khz =
total_max_ghz / physical_cpus[0]->logical_cpus.size();
} }
void PopulateVersionInfo(const healthd::SystemInfo& system_info, void PopulateVersionInfo(const healthd::SystemInfo& system_info,
...@@ -185,6 +196,18 @@ void PopulateAverageCpuTemperature(const healthd::CpuInfo& cpu_info, ...@@ -185,6 +196,18 @@ void PopulateAverageCpuTemperature(const healthd::CpuInfo& cpu_info,
cumulative_total / cpu_info.temperature_channels.size(); cumulative_total / cpu_info.temperature_channels.size();
} }
void PopulateAverageScaledClockSpeed(const healthd::CpuInfo& cpu_info,
mojom::CpuUsage& out_cpu_usage) {
uint32_t total_scaled_ghz = 0;
for (const auto& logical_cpu_ptr : cpu_info.physical_cpus[0]->logical_cpus) {
total_scaled_ghz += logical_cpu_ptr->scaling_current_frequency_khz;
}
// Integer division.
out_cpu_usage.scaling_current_frequency_khz =
total_scaled_ghz / cpu_info.physical_cpus[0]->logical_cpus.size();
}
} // namespace } // namespace
SystemDataProvider::SystemDataProvider() { SystemDataProvider::SystemDataProvider() {
...@@ -524,6 +547,7 @@ void SystemDataProvider::OnCpuUsageUpdated(healthd::TelemetryInfoPtr info_ptr) { ...@@ -524,6 +547,7 @@ void SystemDataProvider::OnCpuUsageUpdated(healthd::TelemetryInfoPtr info_ptr) {
ComputeAndPopulateCpuUsage(*cpu_info, *cpu_usage.get()); ComputeAndPopulateCpuUsage(*cpu_info, *cpu_usage.get());
PopulateAverageCpuTemperature(*cpu_info, *cpu_usage.get()); PopulateAverageCpuTemperature(*cpu_info, *cpu_usage.get());
PopulateAverageScaledClockSpeed(*cpu_info, *cpu_usage.get());
NotifyCpuUsageObservers(cpu_usage); NotifyCpuUsageObservers(cpu_usage);
} }
......
...@@ -61,6 +61,7 @@ void SetCrosHealthdSystemInfoResponse(const std::string& board_name, ...@@ -61,6 +61,7 @@ void SetCrosHealthdSystemInfoResponse(const std::string& board_name,
const std::string& cpu_model, const std::string& cpu_model,
uint32_t total_memory_kib, uint32_t total_memory_kib,
uint16_t cpu_threads_count, uint16_t cpu_threads_count,
uint32_t cpu_max_clock_speed_khz,
bool has_battery, bool has_battery,
const std::string& milestone_version) { const std::string& milestone_version) {
// System info // System info
...@@ -82,6 +83,9 @@ void SetCrosHealthdSystemInfoResponse(const std::string& board_name, ...@@ -82,6 +83,9 @@ void SetCrosHealthdSystemInfoResponse(const std::string& board_name,
// CPU info // CPU info
auto cpu_info = cros_healthd::mojom::CpuInfo::New(); auto cpu_info = cros_healthd::mojom::CpuInfo::New();
auto physical_cpu_info = cros_healthd::mojom::PhysicalCpuInfo::New(); auto physical_cpu_info = cros_healthd::mojom::PhysicalCpuInfo::New();
auto logical_cpu_info = cros_healthd::mojom::LogicalCpuInfo::New();
logical_cpu_info->max_clock_speed_khz = cpu_max_clock_speed_khz;
physical_cpu_info->logical_cpus.push_back(std::move(logical_cpu_info));
physical_cpu_info->model_name = cpu_model; physical_cpu_info->model_name = cpu_model;
cpu_info->num_total_threads = cpu_threads_count; cpu_info->num_total_threads = cpu_threads_count;
cpu_info->physical_cpus.emplace_back(std::move(physical_cpu_info)); cpu_info->physical_cpus.emplace_back(std::move(physical_cpu_info));
...@@ -221,18 +225,25 @@ void SetCrosHealthdMemoryUsageResponse(uint32_t total_memory_kib, ...@@ -221,18 +225,25 @@ void SetCrosHealthdMemoryUsageResponse(uint32_t total_memory_kib,
/*system_info=*/nullptr); /*system_info=*/nullptr);
} }
void SetCrosHealthdCpuResponse(const std::vector<CpuUsageData>& usage_data, void SetCrosHealthdCpuResponse(
const std::vector<int32_t>& cpu_temps) { const std::vector<CpuUsageData>& usage_data,
const std::vector<int32_t>& cpu_temps,
const std::vector<uint32_t>& scaled_cpu_clock_speed) {
auto cpu_info_ptr = cros_healthd::mojom::CpuInfo::New(); auto cpu_info_ptr = cros_healthd::mojom::CpuInfo::New();
auto physical_cpu_info_ptr = cros_healthd::mojom::PhysicalCpuInfo::New(); auto physical_cpu_info_ptr = cros_healthd::mojom::PhysicalCpuInfo::New();
for (const auto& data : usage_data) { DCHECK_EQ(usage_data.size(), scaled_cpu_clock_speed.size());
for (size_t i = 0; i < usage_data.size(); ++i) {
const auto& data = usage_data[i];
auto logical_cpu_info_ptr = cros_healthd::mojom::LogicalCpuInfo::New(); auto logical_cpu_info_ptr = cros_healthd::mojom::LogicalCpuInfo::New();
logical_cpu_info_ptr->user_time_user_hz = data.GetUserTime(); logical_cpu_info_ptr->user_time_user_hz = data.GetUserTime();
logical_cpu_info_ptr->system_time_user_hz = data.GetSystemTime(); logical_cpu_info_ptr->system_time_user_hz = data.GetSystemTime();
logical_cpu_info_ptr->idle_time_user_hz = data.GetIdleTime(); logical_cpu_info_ptr->idle_time_user_hz = data.GetIdleTime();
logical_cpu_info_ptr->scaling_current_frequency_khz =
scaled_cpu_clock_speed[i];
physical_cpu_info_ptr->logical_cpus.emplace_back( physical_cpu_info_ptr->logical_cpus.emplace_back(
std::move(logical_cpu_info_ptr)); std::move(logical_cpu_info_ptr));
} }
...@@ -256,14 +267,23 @@ void SetCrosHealthdCpuResponse(const std::vector<CpuUsageData>& usage_data, ...@@ -256,14 +267,23 @@ void SetCrosHealthdCpuResponse(const std::vector<CpuUsageData>& usage_data,
// entry for each logical cpu. // entry for each logical cpu.
void SetCrosHealthdCpuUsageResponse( void SetCrosHealthdCpuUsageResponse(
const std::vector<CpuUsageData>& usage_data) { const std::vector<CpuUsageData>& usage_data) {
// Use fake temp data since none was supplied. // Use fake temp and scaled clock speed data since none was supplied.
SetCrosHealthdCpuResponse(usage_data, {50}); const std::vector<uint32_t> scaled_clock_speeds(usage_data.size(), 10000);
SetCrosHealthdCpuResponse(usage_data, {50}, scaled_clock_speeds);
} }
void SetCrosHealthdCpuTemperatureResponse( void SetCrosHealthdCpuTemperatureResponse(
const std::vector<int32_t>& cpu_temps) { const std::vector<int32_t>& cpu_temps) {
// Use fake usage_data data since none was supplied. // Use fake usage_data and scaled clock speed data since none was supplied.
SetCrosHealthdCpuResponse({CpuUsageData(1000, 1000, 1000)}, cpu_temps); SetCrosHealthdCpuResponse({CpuUsageData(1000, 1000, 1000)}, cpu_temps,
{10000});
}
void SetCrosHealthdCpuScalingResponse(const std::vector<uint32_t>& cpu_speeds) {
// Use fake temp and usage_data data since none was supplied.
const std::vector<CpuUsageData> usage_data(cpu_speeds.size(),
CpuUsageData(1000, 1000, 1000));
SetCrosHealthdCpuResponse(usage_data, {50}, cpu_speeds);
} }
bool AreValidPowerTimes(int64_t time_to_full, int64_t time_to_empty) { bool AreValidPowerTimes(int64_t time_to_full, int64_t time_to_empty) {
...@@ -398,6 +418,11 @@ void VerifyCpuTempResult(const mojom::CpuUsagePtr& update, ...@@ -398,6 +418,11 @@ void VerifyCpuTempResult(const mojom::CpuUsagePtr& update,
EXPECT_EQ(expected_average_temp, update->average_cpu_temp_celsius); EXPECT_EQ(expected_average_temp, update->average_cpu_temp_celsius);
} }
void VerifyCpuScalingResult(const mojom::CpuUsagePtr& update,
uint32_t expected_scaled_speed) {
EXPECT_EQ(expected_scaled_speed, update->scaling_current_frequency_khz);
}
} // namespace } // namespace
struct FakeBatteryChargeStatusObserver struct FakeBatteryChargeStatusObserver
...@@ -482,13 +507,15 @@ TEST_F(SystemDataProviderTest, GetSystemInfo) { ...@@ -482,13 +507,15 @@ TEST_F(SystemDataProviderTest, GetSystemInfo) {
const std::string expected_cpu_model = "cpu_model"; const std::string expected_cpu_model = "cpu_model";
const uint32_t expected_total_memory_kib = 1234; const uint32_t expected_total_memory_kib = 1234;
const uint16_t expected_cpu_threads_count = 5678; const uint16_t expected_cpu_threads_count = 5678;
const uint32_t expected_cpu_max_clock_speed_khz = 91011;
const bool expected_has_battery = true; const bool expected_has_battery = true;
const std::string expected_milestone_version = "M99"; const std::string expected_milestone_version = "M99";
SetCrosHealthdSystemInfoResponse( SetCrosHealthdSystemInfoResponse(
expected_board_name, expected_marketing_name, expected_cpu_model, expected_board_name, expected_marketing_name, expected_cpu_model,
expected_total_memory_kib, expected_cpu_threads_count, expected_total_memory_kib, expected_cpu_threads_count,
expected_has_battery, expected_milestone_version); expected_cpu_max_clock_speed_khz, expected_has_battery,
expected_milestone_version);
base::RunLoop run_loop; base::RunLoop run_loop;
system_data_provider_->GetSystemInfo( system_data_provider_->GetSystemInfo(
...@@ -499,6 +526,8 @@ TEST_F(SystemDataProviderTest, GetSystemInfo) { ...@@ -499,6 +526,8 @@ TEST_F(SystemDataProviderTest, GetSystemInfo) {
EXPECT_EQ(expected_cpu_model, ptr->cpu_model_name); EXPECT_EQ(expected_cpu_model, ptr->cpu_model_name);
EXPECT_EQ(expected_total_memory_kib, ptr->total_memory_kib); EXPECT_EQ(expected_total_memory_kib, ptr->total_memory_kib);
EXPECT_EQ(expected_cpu_threads_count, ptr->cpu_threads_count); EXPECT_EQ(expected_cpu_threads_count, ptr->cpu_threads_count);
EXPECT_EQ(expected_cpu_max_clock_speed_khz,
ptr->cpu_max_clock_speed_khz);
EXPECT_EQ(expected_milestone_version, EXPECT_EQ(expected_milestone_version,
ptr->version_info->milestone_version); ptr->version_info->milestone_version);
EXPECT_EQ(expected_has_battery, ptr->device_capabilities->has_battery); EXPECT_EQ(expected_has_battery, ptr->device_capabilities->has_battery);
...@@ -514,13 +543,15 @@ TEST_F(SystemDataProviderTest, NoBattery) { ...@@ -514,13 +543,15 @@ TEST_F(SystemDataProviderTest, NoBattery) {
const std::string expected_cpu_model = "cpu_model"; const std::string expected_cpu_model = "cpu_model";
const uint32_t expected_total_memory_kib = 1234; const uint32_t expected_total_memory_kib = 1234;
const uint16_t expected_cpu_threads_count = 5678; const uint16_t expected_cpu_threads_count = 5678;
const uint32_t expected_cpu_max_clock_speed_khz = 91011;
const bool expected_has_battery = false; const bool expected_has_battery = false;
const std::string expected_milestone_version = "M99"; const std::string expected_milestone_version = "M99";
SetCrosHealthdSystemInfoResponse( SetCrosHealthdSystemInfoResponse(
expected_board_name, expected_marketing_name, expected_cpu_model, expected_board_name, expected_marketing_name, expected_cpu_model,
expected_total_memory_kib, expected_cpu_threads_count, expected_total_memory_kib, expected_cpu_threads_count,
expected_has_battery, expected_milestone_version); expected_cpu_max_clock_speed_khz, expected_has_battery,
expected_milestone_version);
base::RunLoop run_loop; base::RunLoop run_loop;
system_data_provider_->GetSystemInfo( system_data_provider_->GetSystemInfo(
...@@ -531,6 +562,8 @@ TEST_F(SystemDataProviderTest, NoBattery) { ...@@ -531,6 +562,8 @@ TEST_F(SystemDataProviderTest, NoBattery) {
EXPECT_EQ(expected_cpu_model, ptr->cpu_model_name); EXPECT_EQ(expected_cpu_model, ptr->cpu_model_name);
EXPECT_EQ(expected_total_memory_kib, ptr->total_memory_kib); EXPECT_EQ(expected_total_memory_kib, ptr->total_memory_kib);
EXPECT_EQ(expected_cpu_threads_count, ptr->cpu_threads_count); EXPECT_EQ(expected_cpu_threads_count, ptr->cpu_threads_count);
EXPECT_EQ(expected_cpu_max_clock_speed_khz,
ptr->cpu_max_clock_speed_khz);
EXPECT_EQ(expected_milestone_version, EXPECT_EQ(expected_milestone_version,
ptr->version_info->milestone_version); ptr->version_info->milestone_version);
EXPECT_EQ(expected_has_battery, ptr->device_capabilities->has_battery); EXPECT_EQ(expected_has_battery, ptr->device_capabilities->has_battery);
...@@ -857,5 +890,53 @@ TEST_F(SystemDataProviderTest, CpuUsageObserverTemp) { ...@@ -857,5 +890,53 @@ TEST_F(SystemDataProviderTest, CpuUsageObserverTemp) {
/*expected_average_temp=*/30); /*expected_average_temp=*/30);
} }
TEST_F(SystemDataProviderTest, CpuUsageScaledClock) {
// Setup Timer
auto timer = std::make_unique<base::MockRepeatingTimer>();
auto* timer_ptr = timer.get();
system_data_provider_->SetCpuUsageTimerForTesting(std::move(timer));
// Setup initial data
uint32_t core_1_speed = 4000;
uint32_t core_2_speed = 5000;
SetCrosHealthdCpuScalingResponse({core_1_speed, core_2_speed});
// Registering as an observer should trigger one update.
FakeCpuUsageObserver cpu_usage_observer;
system_data_provider_->ObserveCpuUsage(
cpu_usage_observer.receiver.BindNewPipeAndPassRemote());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, cpu_usage_observer.updates.size());
VerifyCpuScalingResult(cpu_usage_observer.updates[0],
/*expected_scaled_speed=*/4500);
core_1_speed = 2000;
core_2_speed = 2000;
SetCrosHealthdCpuScalingResponse({core_1_speed, core_2_speed});
timer_ptr->Fire();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, cpu_usage_observer.updates.size());
VerifyCpuScalingResult(cpu_usage_observer.updates[1],
/*expected_scaled_speed=*/2000);
core_1_speed = 2000;
core_2_speed = 2001;
SetCrosHealthdCpuScalingResponse({core_1_speed, core_2_speed});
timer_ptr->Fire();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, cpu_usage_observer.updates.size());
// Integer division so `expected_scaled_speed` should still be 2000.
VerifyCpuScalingResult(cpu_usage_observer.updates[2],
/*expected_scaled_speed=*/2000);
}
} // namespace diagnostics } // namespace diagnostics
} // namespace chromeos } // namespace chromeos
...@@ -23,6 +23,7 @@ struct SystemInfo { ...@@ -23,6 +23,7 @@ struct SystemInfo {
string cpu_model_name; string cpu_model_name;
uint32 total_memory_kib; uint32 total_memory_kib;
uint16 cpu_threads_count; uint16 cpu_threads_count;
uint32 cpu_max_clock_speed_khz;
VersionInfo version_info; VersionInfo version_info;
DeviceCapabilities device_capabilities; DeviceCapabilities device_capabilities;
}; };
...@@ -76,6 +77,7 @@ struct CpuUsage { ...@@ -76,6 +77,7 @@ struct CpuUsage {
uint8 percent_usage_system; uint8 percent_usage_system;
uint8 percent_usage_free; uint8 percent_usage_free;
uint16 average_cpu_temp_celsius; uint16 average_cpu_temp_celsius;
uint32 scaling_current_frequency_khz;
}; };
// Implemented by clients that wish to be updated periodically about changes to // Implemented by clients that wish to be updated periodically about changes to
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {BatteryChargeStatus, BatteryHealth, BatteryInfo, BatteryRateRoutineResult, CpuUsage, ExternalPowerSource, MemoryUsage, RoutineName, StandardRoutineResult, SystemInfo} from './diagnostics_types.js' import { BatteryChargeStatus, BatteryHealth, BatteryInfo, BatteryRateRoutineResult, CpuUsage, ExternalPowerSource, MemoryUsage, RoutineName, StandardRoutineResult, SystemInfo } from './diagnostics_types.js'
import {stringToMojoString16} from './mojo_utils.js'; import { stringToMojoString16 } from './mojo_utils.js';
/** @type {!Array<!BatteryChargeStatus>} */ /** @type {!Array<!BatteryChargeStatus>} */
export const fakeBatteryChargeStatus = [ export const fakeBatteryChargeStatus = [
...@@ -128,10 +128,11 @@ export const fakeSystemInfo = { ...@@ -128,10 +128,11 @@ export const fakeSystemInfo = {
boardName: 'CrOS Board', boardName: 'CrOS Board',
cpuModelName: 'BestCpu SoFast 1000', cpuModelName: 'BestCpu SoFast 1000',
cpuThreadsCount: 8, cpuThreadsCount: 8,
deviceCapabilities: {hasBattery: true}, cpuMaxClockSpeedKhz: 1000,
deviceCapabilities: { hasBattery: true },
marketingName: 'Coolest Chromebook', marketingName: 'Coolest Chromebook',
totalMemoryKib: 128000, totalMemoryKib: 128000,
versionInfo: {milestoneVersion: 'M99'}, versionInfo: { milestoneVersion: 'M99' },
}; };
/** @type {!SystemInfo} */ /** @type {!SystemInfo} */
...@@ -139,10 +140,11 @@ export const fakeSystemInfoWithoutBattery = { ...@@ -139,10 +140,11 @@ export const fakeSystemInfoWithoutBattery = {
boardName: 'CrOS Board', boardName: 'CrOS Board',
cpuModelName: 'BestCpu SoFast 1000', cpuModelName: 'BestCpu SoFast 1000',
cpuThreadsCount: 8, cpuThreadsCount: 8,
deviceCapabilities: {hasBattery: false}, cpuMaxClockSpeedKhz: 1000,
deviceCapabilities: { hasBattery: false },
marketingName: 'Coolest Chromebook', marketingName: 'Coolest Chromebook',
totalMemoryKib: 128000, totalMemoryKib: 128000,
versionInfo: {milestoneVersion: 'M99'}, versionInfo: { milestoneVersion: 'M99' },
}; };
/** @type {!Map<!RoutineName, !StandardRoutineResult>} */ /** @type {!Map<!RoutineName, !StandardRoutineResult>} */
...@@ -172,4 +174,4 @@ export const fakeBatteryRoutineResults = new Map([ ...@@ -172,4 +174,4 @@ export const fakeBatteryRoutineResults = new Map([
time_delta_seconds: 0 time_delta_seconds: 0
} }
], ],
]); ]);
\ No newline at end of file
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