summaryrefslogtreecommitdiffstats
path: root/base/process_util_linux.cc
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-19 01:57:39 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-19 01:57:39 +0000
commitd2ed2383f5820e1fc26c9ac709b00bc8cdc8d086 (patch)
tree361278c499794f39d2b5c3c218fc59a7a98f7016 /base/process_util_linux.cc
parentc2788ecbcd5c443fb129f63b7b86f83e944b4950 (diff)
downloadchromium_src-d2ed2383f5820e1fc26c9ac709b00bc8cdc8d086.zip
chromium_src-d2ed2383f5820e1fc26c9ac709b00bc8cdc8d086.tar.gz
chromium_src-d2ed2383f5820e1fc26c9ac709b00bc8cdc8d086.tar.bz2
linux: implement GetCPUUsage() so the task manager shows CPU
Discussed in part here: http://groups.google.com/group/chromium-dev/browse_thread/thread/8e91f66f9af6ccec This implements option 3, which turned out to be pretty simple. BUG=19864 Review URL: http://codereview.chromium.org/215020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26647 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/process_util_linux.cc')
-rw-r--r--base/process_util_linux.cc96
1 files changed, 96 insertions, 0 deletions
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
index 8342414..9a725c0 100644
--- a/base/process_util_linux.cc
+++ b/base/process_util_linux.cc
@@ -6,9 +6,12 @@
#include <ctype.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <time.h>
#include <unistd.h>
#include <string>
@@ -338,4 +341,97 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return true;
}
+
+// Exposed for testing.
+int ParseProcStatCPU(const std::string& input) {
+ // /proc/<pid>/stat contains the process name in parens. In case the
+ // process name itself contains parens, skip past them.
+ std::string::size_type rparen = input.rfind(')');
+ if (rparen == std::string::npos)
+ return -1;
+
+ // From here, we expect a bunch of space-separated fields, where the
+ // 0-indexed 11th and 12th are utime and stime. On two different machines
+ // I found 42 and 39 fields, so let's just expect the ones we need.
+ std::vector<std::string> fields;
+ SplitString(input.substr(rparen + 2), ' ', &fields);
+ if (fields.size() < 13)
+ return -1; // Output not in the format we expect.
+
+ return StringToInt(fields[11]) + StringToInt(fields[12]);
+}
+
+// Get the total CPU of a single process. Return value is number of jiffies
+// on success or -1 on error.
+static int GetProcessCPU(pid_t pid) {
+ // Use /proc/<pid>/task to find all threads and parse their /stat file.
+ FilePath path = FilePath(StringPrintf("/proc/%d/task/", pid));
+
+ DIR* dir = opendir(path.value().c_str());
+ if (!dir) {
+ LOG(ERROR) << "opendir(" << path.value() << "): " << strerror(errno);
+ return -1;
+ }
+
+ int total_cpu = 0;
+ while (struct dirent* ent = readdir(dir)) {
+ if (ent->d_name[0] == '.')
+ continue;
+
+ FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat");
+ std::string stat;
+ if (file_util::ReadFileToString(stat_path, &stat)) {
+ int cpu = ParseProcStatCPU(stat);
+ if (cpu > 0)
+ total_cpu += cpu;
+ }
+ }
+ closedir(dir);
+
+ return total_cpu;
+}
+
+int ProcessMetrics::GetCPUUsage() {
+ // This queries the /proc-specific scaling factor which is
+ // conceptually the system hertz. To dump this value on another
+ // system, try
+ // od -t dL /proc/self/auxv
+ // and look for the number after 17 in the output; mine is
+ // 0000040 17 100 3 134512692
+ // which means the answer is 100.
+ // It may be the case that this value is always 100.
+ static const int kHertz = sysconf(_SC_CLK_TCK);
+
+ struct timeval now;
+ int retval = gettimeofday(&now, NULL);
+ if (retval)
+ return 0;
+ int64 time = TimeValToMicroseconds(now);
+
+ if (last_time_ == 0) {
+ // First call, just set the last values.
+ last_time_ = time;
+ last_cpu_ = GetProcessCPU(process_);
+ return 0;
+ }
+
+ int64 time_delta = time - last_time_;
+ DCHECK(time_delta != 0);
+ if (time_delta == 0)
+ return 0;
+
+ int cpu = GetProcessCPU(process_);
+
+ // We have the number of jiffies in the time period. Convert to percentage.
+ // Note this means we will go *over* 100 in the case where multiple threads
+ // are together adding to more than one CPU's worth.
+ int percentage = 100 * (cpu - last_cpu_) /
+ (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
+
+ last_time_ = time;
+ last_cpu_ = cpu;
+
+ return percentage;
+}
+
} // namespace base