| // 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 |