| Index: base/process/process_metrics_linux.cc
|
| diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
|
| index be166e33e322959bb7d10111e0746dbe5680c27f..03cc7ebee9951f817af38c946e6e53a79c68c408 100644
|
| --- a/base/process/process_metrics_linux.cc
|
| +++ b/base/process/process_metrics_linux.cc
|
| @@ -25,6 +25,15 @@ namespace base {
|
|
|
| namespace {
|
|
|
| +void TrimKeyValuePairs(StringPairs* pairs) {
|
| + DCHECK(pairs);
|
| + StringPairs& p_ref = *pairs;
|
| + for (size_t i = 0; i < p_ref.size(); ++i) {
|
| + TrimWhitespaceASCII(p_ref[i].first, TRIM_ALL, &p_ref[i].first);
|
| + TrimWhitespaceASCII(p_ref[i].second, TRIM_ALL, &p_ref[i].second);
|
| + }
|
| +}
|
| +
|
| #if defined(OS_CHROMEOS)
|
| // Read a file with a single number string and return the number as a uint64.
|
| static uint64 ReadFileToUint64(const FilePath file) {
|
| @@ -44,19 +53,19 @@ static uint64 ReadFileToUint64(const FilePath file) {
|
| size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) {
|
| std::string status;
|
| {
|
| - // Synchronously reading files in /proc is safe.
|
| + // Synchronously reading files in /proc does not hit the disk.
|
| ThreadRestrictions::ScopedAllowIO allow_io;
|
| FilePath stat_file = internal::GetProcPidDir(pid).Append("status");
|
| if (!ReadFileToString(stat_file, &status))
|
| return 0;
|
| }
|
|
|
| - std::vector<std::pair<std::string, std::string> > pairs;
|
| + StringPairs pairs;
|
| SplitStringIntoKeyValuePairs(status, ':', '\n', &pairs);
|
| + TrimKeyValuePairs(&pairs);
|
| for (size_t i = 0; i < pairs.size(); ++i) {
|
| - std::string key, value_str;
|
| - TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key);
|
| - TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value_str);
|
| + const std::string& key = pairs[i].first;
|
| + const std::string& value_str = pairs[i].second;
|
| if (key == field) {
|
| std::vector<std::string> split_value_str;
|
| SplitString(value_str, ' ', &split_value_str);
|
| @@ -76,6 +85,40 @@ size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) {
|
| return 0;
|
| }
|
|
|
| +#if defined(OS_LINUX)
|
| +// Read /proc/<pid>/sched and look for |field|. On succes, return true and
|
| +// write the value for |field| into |result|.
|
| +// Only works for fields in the form of "field : uint_value"
|
| +bool ReadProcSchedAndGetFieldAsUint64(pid_t pid,
|
| + const std::string& field,
|
| + uint64* result) {
|
| + std::string sched_data;
|
| + {
|
| + // Synchronously reading files in /proc does not hit the disk.
|
| + ThreadRestrictions::ScopedAllowIO allow_io;
|
| + FilePath sched_file = internal::GetProcPidDir(pid).Append("sched");
|
| + if (!ReadFileToString(sched_file, &sched_data))
|
| + return false;
|
| + }
|
| +
|
| + StringPairs pairs;
|
| + SplitStringIntoKeyValuePairs(sched_data, ':', '\n', &pairs);
|
| + TrimKeyValuePairs(&pairs);
|
| + for (size_t i = 0; i < pairs.size(); ++i) {
|
| + const std::string& key = pairs[i].first;
|
| + const std::string& value_str = pairs[i].second;
|
| + if (key == field) {
|
| + uint64 value;
|
| + if (!StringToUint64(value_str, &value))
|
| + return false;
|
| + *result = value;
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +#endif // defined(OS_LINUX)
|
| +
|
| // Get the total CPU of a single process. Return value is number of jiffies
|
| // on success or -1 on error.
|
| int GetProcessCPU(pid_t pid) {
|
| @@ -94,7 +137,7 @@ int GetProcessCPU(pid_t pid) {
|
| if (!tid)
|
| continue;
|
|
|
| - // Synchronously reading files in /proc is safe.
|
| + // Synchronously reading files in /proc does not hit the disk.
|
| ThreadRestrictions::ScopedAllowIO allow_io;
|
|
|
| std::string stat;
|
| @@ -197,7 +240,7 @@ double ProcessMetrics::GetCPUUsage() {
|
| // To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
|
| // in your kernel configuration.
|
| bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
|
| - // Synchronously reading files in /proc is safe.
|
| + // Synchronously reading files in /proc does not hit the disk.
|
| ThreadRestrictions::ScopedAllowIO allow_io;
|
|
|
| std::string proc_io_contents;
|
| @@ -208,12 +251,12 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
|
| io_counters->OtherOperationCount = 0;
|
| io_counters->OtherTransferCount = 0;
|
|
|
| - std::vector<std::pair<std::string, std::string> > pairs;
|
| + StringPairs pairs;
|
| SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs);
|
| + TrimKeyValuePairs(&pairs);
|
| for (size_t i = 0; i < pairs.size(); ++i) {
|
| - std::string key, value_str;
|
| - TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key);
|
| - TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value_str);
|
| + const std::string& key = pairs[i].first;
|
| + const std::string& value_str = pairs[i].second;
|
| uint64* target_counter = NULL;
|
| if (key == "syscr")
|
| target_counter = &io_counters->ReadOperationCount;
|
| @@ -234,6 +277,9 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
|
| ProcessMetrics::ProcessMetrics(ProcessHandle process)
|
| : process_(process),
|
| last_system_time_(0),
|
| +#if defined(OS_LINUX)
|
| + last_absolute_idle_wakeups_(0),
|
| +#endif
|
| last_cpu_(0) {
|
| processor_count_ = SysInfo::NumberOfProcessors();
|
| }
|
| @@ -315,7 +361,7 @@ bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage)
|
| std::string statm;
|
| {
|
| FilePath statm_file = internal::GetProcPidDir(process_).Append("statm");
|
| - // Synchronously reading files in /proc is safe.
|
| + // Synchronously reading files in /proc does not hit the disk.
|
| ThreadRestrictions::ScopedAllowIO allow_io;
|
| bool ret = ReadFileToString(statm_file, &statm);
|
| if (!ret || statm.length() == 0)
|
| @@ -717,7 +763,7 @@ bool IsValidDiskName(const std::string& candidate) {
|
| }
|
|
|
| bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) {
|
| - // Synchronously reading files in /proc is safe.
|
| + // Synchronously reading files in /proc does not hit the disk.
|
| ThreadRestrictions::ScopedAllowIO allow_io;
|
|
|
| FilePath diskinfo_file("/proc/diskstats");
|
| @@ -814,7 +860,7 @@ scoped_ptr<Value> SwapInfo::ToValue() const {
|
| }
|
|
|
| void GetSwapInfo(SwapInfo* swap_info) {
|
| - // Synchronously reading files in /sys/block/zram0 is safe.
|
| + // Synchronously reading files in /sys/block/zram0 does not hit the disk.
|
| ThreadRestrictions::ScopedAllowIO allow_io;
|
|
|
| FilePath zram_path("/sys/block/zram0");
|
| @@ -839,4 +885,13 @@ void GetSwapInfo(SwapInfo* swap_info) {
|
| }
|
| #endif // defined(OS_CHROMEOS)
|
|
|
| +#if defined(OS_LINUX)
|
| +int ProcessMetrics::GetIdleWakeupsPerSecond() {
|
| + uint64 wake_ups;
|
| + const char kWakeupStat[] = "se.statistics.nr_wakeups";
|
| + return ReadProcSchedAndGetFieldAsUint64(process_, kWakeupStat, &wake_ups) ?
|
| + CalculateIdleWakeupsPerSecond(wake_ups) : 0;
|
| +}
|
| +#endif // defined(OS_LINUX)
|
| +
|
| } // namespace base
|
|
|