blob: 3539e7bfd8a826fe55d907d8fc47871f980d4a57 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_COMPUTE_PRESSURE_PROCFS_STAT_CPU_PARSER_H_
#define CONTENT_BROWSER_COMPUTE_PRESSURE_PROCFS_STAT_CPU_PARSER_H_
#include <stdint.h>
#include <vector>
#include "base/files/file_path.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
#include "base/thread_annotations.h"
#include "content/common/content_export.h"
namespace content {
// Parses CPU time usage stats from procfs (/proc/stat).
//
// This class is not thread-safe. Each instance must be used on the same
// sequence, which must allow blocking I/O. The constructor may be used on a
// different sequence.
class CONTENT_EXPORT ProcfsStatCpuParser {
public:
// CPU core utilization statistics.
//
// Quantities are expressed in "user hertz", which is a Linux kernel
// configuration knob (USER_HZ). Typical values range between 1/100 seconds
// and 1/1000 seconds. The denominator can be obtained from
// sysconf(_SC_CLK_TCK).
struct CoreTimes {
// Normal processes executing in user mode.
uint64_t user() const { return times[0]; }
// Niced processes executing in user mode.
uint64_t nice() const { return times[1]; }
// Processes executing in kernel mode.
uint64_t system() const { return times[2]; }
// Twiddling thumbs.
uint64_t idle() const { return times[3]; }
// Waiting for I/O to complete. Unreliable.
uint64_t iowait() const { return times[4]; }
// Servicing interrupts.
uint64_t irq() const { return times[5]; }
// Servicing softirqs.
uint64_t softirq() const { return times[6]; }
// Involuntary wait.
uint64_t steal() const { return times[7]; }
// Running a normal guest.
uint64_t guest() const { return times[8]; }
// Running a niced guest.
uint64_t guest_nice() const { return times[9]; }
uint64_t times[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// Computes a CPU's utilization over the time between two stat snapshots.
//
// Returns a value between 0.0 and 1.0 on success, and -1.0 when given
// invalid data, such as a `baseline` that does not represent a stat
// snapshot collected before `this` snapshot.
double TimeUtilization(const CoreTimes& baseline) const;
};
// The "production" `procfs_path` value for the constructor.
static constexpr base::FilePath::CharType kProcfsStatPath[] =
FILE_PATH_LITERAL("/proc/stat");
// `stat_path` is exposed for testing. Production instances should be
// constructed using base::FilePath(kProcfsStatPath).
explicit ProcfsStatCpuParser(base::FilePath stat_path);
~ProcfsStatCpuParser();
ProcfsStatCpuParser(const ProcfsStatCpuParser&) = delete;
ProcfsStatCpuParser& operator=(const ProcfsStatCpuParser&) = delete;
const std::vector<CoreTimes>& core_times() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return core_times_;
}
// Reads /proc/stat and updates the vector returned by core_times().
//
// Returns false if parsing fails. This only happens if /proc/stat is not
// accessible. Invalid data is ignored.
//
// Cores without entries in /proc/stat will remain unchanged. Counters that
// decrease below the last parsed value are ignored.
bool Update();
private:
// Returns -1 if the line does not include any CPU.
static int CoreIdFromLine(base::StringPiece stat_line);
static void UpdateCore(base::StringPiece core_line, CoreTimes& core_times);
SEQUENCE_CHECKER(sequence_checker_);
const base::FilePath stat_path_;
std::vector<CoreTimes> core_times_ GUARDED_BY_CONTEXT(sequence_checker_);
};
} // namespace content
#endif // CONTENT_BROWSER_COMPUTE_PRESSURE_PROCFS_STAT_CPU_PARSER_H_