blob: d6b9074e0b18b61ceacf65b35d24e1d071bf3d63 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/metrics/power/power_metrics.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
namespace {
#if BUILDFLAG(IS_MAC)
power_metrics::CoalitionResourceUsageRate GetFakeResourceUsageRate() {
power_metrics::CoalitionResourceUsageRate rate;
rate.cpu_time_per_second = 0.5;
rate.interrupt_wakeups_per_second = 10;
rate.platform_idle_wakeups_per_second = 11;
rate.bytesread_per_second = 12;
rate.byteswritten_per_second = 13;
rate.gpu_time_per_second = 0.6;
rate.energy_impact_per_second = 15;
rate.power_nw = 1000000;
for (int i = 0; i < COALITION_NUM_THREAD_QOS_TYPES; ++i)
rate.qos_time_per_second[i] = 0.1 * i;
return rate;
}
#endif // BUILDFLAG(IS_MAC)
struct HistogramSampleExpectation {
std::string histogram_name_prefix;
base::Histogram::Sample sample;
};
// For each histogram named after the combination of prefixes from
// `expectations` and suffixes from `suffixes`, verifies that there is a unique
// sample `expectation.sample`.
void ExpectHistogramSamples(
base::HistogramTester* histogram_tester,
const std::vector<const char*>& suffixes,
const std::vector<HistogramSampleExpectation>& expectations) {
for (const char* suffix : suffixes) {
for (const auto& expectation : expectations) {
std::string histogram_name =
base::StrCat({expectation.histogram_name_prefix, suffix});
SCOPED_TRACE(histogram_name);
histogram_tester->ExpectUniqueSample(histogram_name, expectation.sample,
1);
}
}
}
} // namespace
TEST(PowerMetricsTest, ReportAggregatedProcessMetricsHistograms) {
base::HistogramTester histogram_tester;
const std::vector<const char*> suffixes = {"", ".Foo", ".Bar"};
ProcessMonitor::Metrics process_metrics;
process_metrics.cpu_usage = 0.20;
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_AIX)
// Returns the number of average idle cpu wakeups per second since the last
// time the metric was sampled.
process_metrics.idle_wakeups = 51;
#endif
#if BUILDFLAG(IS_MAC)
// The number of average "package idle exits" per second since the last
// time the metric was sampled. See base/process/process_metrics.h for a
// more detailed explanation.
process_metrics.package_idle_wakeups = 52;
// "Energy Impact" is a synthetic power estimation metric displayed by macOS
// in Activity Monitor and the battery menu.
process_metrics.energy_impact = 10.00;
#endif
ReportAggregatedProcessMetricsHistograms(process_metrics, suffixes);
ExpectHistogramSamples(&histogram_tester, suffixes, {
// Windows ARM64 does not support Constant Rate TSC so
// PerformanceMonitor.AverageCPU8.Total is not recorded there.
#if !BUILDFLAG(IS_WIN) || !defined(ARCH_CPU_ARM64)
{"PerformanceMonitor.AverageCPU8.Total", 20},
#endif
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_AIX)
{"PerformanceMonitor.IdleWakeups2.Total", 51},
#endif
#if BUILDFLAG(IS_MAC)
{"PerformanceMonitor.PackageExitIdleWakeups2.Total", 52},
{"PerformanceMonitor.EnergyImpact2.Total", 10},
#endif
});
}
#if BUILDFLAG(IS_MAC)
TEST(PowerMetricsTest, ReportShortIntervalHistograms) {
base::HistogramTester histogram_tester;
const char* kScenarioSuffix = ".AllTabsHidden_Audio";
ReportShortIntervalHistograms(kScenarioSuffix, GetFakeResourceUsageRate());
const std::vector<const char*> suffixes({"", kScenarioSuffix});
ExpectHistogramSamples(
&histogram_tester, suffixes,
{{"PerformanceMonitor.ResourceCoalition.CPUTime2_10sec", 5000}});
}
TEST(PowerMetricsTest, ReportResourceCoalitionHistograms) {
base::HistogramTester histogram_tester;
const std::vector<const char*> suffixes = {"", ".Foo", ".Bar"};
ReportResourceCoalitionHistograms(GetFakeResourceUsageRate(), suffixes);
ExpectHistogramSamples(
&histogram_tester, suffixes,
{// These histograms reports the CPU/GPU times as a percentage of
// time with a permyriad granularity, 10% (0.1) will be represented
// as 1000.
{"PerformanceMonitor.ResourceCoalition.CPUTime2", 5000},
{"PerformanceMonitor.ResourceCoalition.GPUTime2", 6000},
// These histograms report counts with a millievent/second
// granularity.
{"PerformanceMonitor.ResourceCoalition.InterruptWakeupsPerSecond",
10000},
{"PerformanceMonitor.ResourceCoalition."
"PlatformIdleWakeupsPerSecond",
11000},
{"PerformanceMonitor.ResourceCoalition.BytesReadPerSecond2", 12},
{"PerformanceMonitor.ResourceCoalition.BytesWrittenPerSecond2", 13},
// EI is reported in centi-EI so the data needs to be multiplied by
// 100.0.
{"PerformanceMonitor.ResourceCoalition.EnergyImpact", 1500},
// The QoS histograms also reports the CPU times as a percentage of
// time with a permyriad granularity.
{"PerformanceMonitor.ResourceCoalition.QoSLevel.Default", 0},
{"PerformanceMonitor.ResourceCoalition.QoSLevel.Maintenance", 1000},
{"PerformanceMonitor.ResourceCoalition.QoSLevel.Background", 2000},
{"PerformanceMonitor.ResourceCoalition.QoSLevel.Utility", 3000},
{"PerformanceMonitor.ResourceCoalition.QoSLevel.Legacy", 4000},
{"PerformanceMonitor.ResourceCoalition.QoSLevel.UserInitiated", 5000},
{"PerformanceMonitor.ResourceCoalition.QoSLevel.UserInteractive",
6000}});
if (base::mac::GetCPUType() == base::mac::CPUType::kArm) {
ExpectHistogramSamples(
&histogram_tester, suffixes,
{// Power is reported in milliwatts (mj/s), the data
// is in nj/s so it has to be divided by 1000000.
{"PerformanceMonitor.ResourceCoalition.Power2", 1}});
} else {
histogram_tester.ExpectTotalCount(
"PerformanceMonitor.ResourceCoalition.Power2", 0);
}
}
// Verify that no energy impact histogram is reported when
// `CoalitionResourceUsageRate::energy_impact_per_second` is nullopt.
TEST(PowerMetricsTest, ReportResourceCoalitionHistograms_NoEnergyImpact) {
base::HistogramTester histogram_tester;
power_metrics::CoalitionResourceUsageRate rate = GetFakeResourceUsageRate();
rate.energy_impact_per_second.reset();
std::vector<const char*> suffixes = {"", ".Foo"};
ReportResourceCoalitionHistograms(rate, suffixes);
histogram_tester.ExpectTotalCount(
"PerformanceMonitor.ResourceCoalition.EnergyImpact", 0);
histogram_tester.ExpectTotalCount(
"PerformanceMonitor.ResourceCoalition.EnergyImpact.Foo", 0);
}
#endif // BUILDFLAG(IS_MAC)