Skip to content

Commit

Permalink
Optimistically read from /proc for process stats.
Browse files Browse the repository at this point in the history
b/341774149
  • Loading branch information
aee-google committed Jun 7, 2024
1 parent 678cd4f commit 9a36b01
Show file tree
Hide file tree
Showing 8 changed files with 482 additions and 10 deletions.
7 changes: 7 additions & 0 deletions base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,13 @@ component("base") {
]
}

if (use_cobalt_customizations) {
sources += [
"process/internal_linux.cc",
"process/internal_linux.h",
]
}

if (!use_cobalt_customizations && (is_linux || is_chromeos || is_android)) {
sources += [
"files/file_path_watcher_inotify.cc",
Expand Down
33 changes: 23 additions & 10 deletions base/process/internal_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

#include "base/process/internal_linux.h"

#if !defined(STARBOARD)
#include <limits.h>
#include <unistd.h>
#endif // !defined(STARBOARD)

#include <map>
#include <string>
Expand Down Expand Up @@ -33,6 +35,7 @@ const char kProcDir[] = "/proc";

const char kStatFile[] = "stat";

#if !defined(STARBOARD)
FilePath GetProcPidDir(pid_t pid) {
return FilePath(kProcDir).Append(NumberToString(pid));
}
Expand All @@ -56,6 +59,7 @@ pid_t ProcDirSlotToPid(const char* d_name) {
}
return pid;
}
#endif // !defined(STARBOARD)

bool ReadProcFile(const FilePath& file, std::string* buffer) {
DCHECK(FilePath(kProcDir).IsParent(file));
Expand All @@ -70,10 +74,12 @@ bool ReadProcFile(const FilePath& file, std::string* buffer) {
return !buffer->empty();
}

#if !defined(STARBOARD)
bool ReadProcStats(pid_t pid, std::string* buffer) {
FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
return ReadProcFile(stat_file, buffer);
}
#endif // !defined(STARBOARD)

bool ParseProcStats(const std::string& stats_data,
std::vector<std::string>* proc_stats) {
Expand All @@ -86,28 +92,29 @@ bool ParseProcStats(const std::string& stats_data,
// pid (process name) data1 data2 .... dataN
// Look for the closing paren by scanning backwards, to avoid being fooled by
// processes with ')' in the name.
size_t open_parens_idx = stats_data.find(" (");
size_t close_parens_idx = stats_data.rfind(") ");
if (open_parens_idx == std::string::npos ||
close_parens_idx == std::string::npos ||
open_parens_idx > close_parens_idx) {
size_t pid_end = stats_data.find(" (");
size_t comm_start = pid_end + 2;
size_t comm_end = stats_data.rfind(") ");
size_t state_start = comm_end + 2;
if (pid_end == std::string::npos ||
comm_end == std::string::npos ||
pid_end > comm_end) {
DLOG(WARNING) << "Failed to find matched parens in '" << stats_data << "'";
NOTREACHED();
return false;
}
open_parens_idx++;

proc_stats->clear();
// PID.
proc_stats->push_back(stats_data.substr(0, open_parens_idx));
proc_stats->push_back(stats_data.substr(0, pid_end));
// Process name without parentheses.
proc_stats->push_back(
stats_data.substr(open_parens_idx + 1,
close_parens_idx - (open_parens_idx + 1)));
stats_data.substr(comm_start,
comm_end - comm_start));

// Split the rest.
std::vector<std::string> other_stats = SplitString(
stats_data.substr(close_parens_idx + 2), " ",
stats_data.substr(state_start), " ",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
for (const auto& i : other_stats)
proc_stats->push_back(i);
Expand Down Expand Up @@ -152,16 +159,19 @@ int64_t ReadStatFileAndGetFieldAsInt64(const FilePath& stat_file,
return GetProcStatsFieldAsInt64(proc_stats, field_num);
}

#if !defined(STARBOARD)
int64_t ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num) {
FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
return ReadStatFileAndGetFieldAsInt64(stat_file, field_num);
}
#endif // !defined(STARBOARD)

int64_t ReadProcSelfStatsAndGetFieldAsInt64(ProcStatsFields field_num) {
FilePath stat_file = FilePath(kProcDir).Append("self").Append(kStatFile);
return ReadStatFileAndGetFieldAsInt64(stat_file, field_num);
}

#if !defined(STARBOARD)
size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
ProcStatsFields field_num) {
std::string stats_data;
Expand All @@ -172,6 +182,7 @@ size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
return 0;
return GetProcStatsFieldAsSizeT(proc_stats, field_num);
}
#endif // !defined(STARBOARD)

Time GetBootTime() {
FilePath path("/proc/stat");
Expand All @@ -189,6 +200,7 @@ Time GetBootTime() {
return Time::FromTimeT(btime);
}

#if !defined(STARBOARD)
TimeDelta GetUserCpuTimeSinceBoot() {
FilePath path("/proc/stat");
std::string contents;
Expand Down Expand Up @@ -228,6 +240,7 @@ TimeDelta ClockTicksToTimeDelta(int64_t clock_ticks) {

return Microseconds(Time::kMicrosecondsPerSecond * clock_ticks / kHertz);
}
#endif // !defined(STARBOARD)

} // namespace internal
} // namespace base
14 changes: 14 additions & 0 deletions base/process/internal_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@
#ifndef BASE_PROCESS_INTERNAL_LINUX_H_
#define BASE_PROCESS_INTERNAL_LINUX_H_

#if !defined(STARBOARD)
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#endif // !defined(STARBOARD)
#include <string>
#include <vector>

#if !defined(STARBOARD)
#include "base/files/dir_reader_posix.h"
#endif // !defined(STARBOARD)
#include "base/files/file_path.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
Expand All @@ -33,14 +37,17 @@ extern const char kProcDir[];
// "stat"
extern const char kStatFile[];

#if !defined(STARBOARD)
// Returns a FilePath to "/proc/pid".
base::FilePath GetProcPidDir(pid_t pid);
#endif // !defined(STARBOARD)

// Reads a file from /proc into a string. This is allowed on any thread as
// reading from /proc does not hit the disk. Returns true if the file can be
// read and is non-empty.
bool ReadProcFile(const FilePath& file, std::string* buffer);

#if !defined(STARBOARD)
// Take a /proc directory entry named |d_name|, and if it is the directory for
// a process, convert it to a pid_t.
// Returns 0 on failure.
Expand All @@ -50,6 +57,7 @@ pid_t ProcDirSlotToPid(const char* d_name);
// Reads /proc/<pid>/stat into |buffer|. Returns true if the file can be read
// and is non-empty.
bool ReadProcStats(pid_t pid, std::string* buffer);
#endif // !defined(STARBOARD)

// Takes |stats_data| and populates |proc_stats| with the values split by
// spaces. Taking into account the 2nd field may, in itself, contain spaces.
Expand Down Expand Up @@ -89,16 +97,21 @@ size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
// ReadProcStats(). See GetProcStatsFieldAsInt64() for details.
int64_t ReadStatsFilendGetFieldAsInt64(const FilePath& stat_file,
ProcStatsFields field_num);
#if !defined(STARBOARD)
int64_t ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num);
#endif // !defined(STARBOARD)
int64_t ReadProcSelfStatsAndGetFieldAsInt64(ProcStatsFields field_num);

#if !defined(STARBOARD)
// Same as ReadProcStatsAndGetFieldAsInt64() but for size_t values.
size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
ProcStatsFields field_num);
#endif // !defined(STARBOARD)

// Returns the time that the OS started. Clock ticks are relative to this.
Time GetBootTime();

#if !defined(STARBOARD)
// Returns the amount of time spent in user space since boot across all CPUs.
TimeDelta GetUserCpuTimeSinceBoot();

Expand Down Expand Up @@ -130,6 +143,7 @@ void ForEachProcessTask(base::ProcessHandle process, Lambda&& lambda) {
lambda(tid, task_path);
}
}
#endif // !defined(STARBOARD)

} // namespace internal
} // namespace base
Expand Down
3 changes: 3 additions & 0 deletions cobalt/base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ static_library("base") {
"path_provider.h",
"polymorphic_downcast.h",
"polymorphic_equatable.h",
"process/process_metrics_helper.cc",
"process/process_metrics_helper.h",
"ref_counted_lock.h",
"source_location.cc",
"source_location.h",
Expand Down Expand Up @@ -117,6 +119,7 @@ target(gtest_target_type, "base_test") {
"c_val_time_interval_timer_stats_test.cc",
"circular_buffer_shell_unittest.cc",
"fixed_size_lru_cache_test.cc",
"process/process_metrics_helper_test.cc",
"statistics_test.cc",
"token_test.cc",
]
Expand Down
Loading

0 comments on commit 9a36b01

Please sign in to comment.