blob: 6cc8c90138293c192234da1c954df62059841b33 [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 "components/system_cpu/core_times.h"
#include "base/check_op.h"
namespace system_cpu {
CoreTimes::CoreTimes(const std::initializer_list<uint64_t>& times) {
CHECK_EQ(times.size(), 10u);
size_t i = 0;
for (auto value : times) {
times_[i++] = value;
}
}
void CoreTimes::set_user(uint64_t time) {
if (times_[0] < time) {
times_[0] = time;
}
}
void CoreTimes::set_nice(uint64_t time) {
if (times_[1] < time) {
times_[1] = time;
}
}
void CoreTimes::set_system(uint64_t time) {
if (times_[2] < time) {
times_[2] = time;
}
}
void CoreTimes::set_idle(uint64_t time) {
if (times_[3] < time) {
times_[3] = time;
}
}
void CoreTimes::set_iowait(uint64_t time) {
if (times_[4] < time) {
times_[4] = time;
}
}
void CoreTimes::set_irq(uint64_t time) {
if (times_[5] < time) {
times_[5] = time;
}
}
void CoreTimes::set_softirq(uint64_t time) {
if (times_[6] < time) {
times_[6] = time;
}
}
void CoreTimes::set_steal(uint64_t time) {
if (times_[7] < time) {
times_[7] = time;
}
}
void CoreTimes::set_guest(uint64_t time) {
if (times_[8] < time) {
times_[8] = time;
}
}
void CoreTimes::set_guest_nice(uint64_t time) {
if (times_[9] < time) {
times_[9] = time;
}
}
double CoreTimes::TimeUtilization(const CoreTimes& baseline) const {
// Each of the blocks below consists of a check and a subtraction. The check
// is used to bail on invalid input (/proc/stat counters should never
// decrease over time).
//
// The check is also essential for the correctness of the subtraction -- the
// result of the subtraction is stored in a temporary `uint64_t` before being
// accumulated in `active_delta`, and this intermediate result must not be
// negative.
if (user() < baseline.user()) {
return -1;
}
double active_delta = user() - baseline.user();
if (nice() < baseline.nice()) {
return -1;
}
active_delta += nice() - baseline.nice();
if (system() < baseline.system()) {
return -1;
}
active_delta += system() - baseline.system();
if (idle() < baseline.idle()) {
return -1;
}
uint64_t idle_delta = idle() - baseline.idle();
// iowait() is unreliable, according to the Linux kernel documentation at
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt.
if (irq() < baseline.irq()) {
return -1;
}
active_delta += irq() - baseline.irq();
if (softirq() < baseline.softirq()) {
return -1;
}
active_delta += softirq() - baseline.softirq();
if (steal() < baseline.steal()) {
return -1;
}
active_delta += steal() - baseline.steal();
// guest() and guest_nice() are included in user(). Full analysis in
// https://unix.stackexchange.com/a/303224/
double total_delta = active_delta + idle_delta;
if (total_delta == 0) {
// The two snapshots represent the same point in time, so the time interval
// between the two snapshots is empty.
return -1;
}
return active_delta / total_delta;
}
} // namespace system_cpu