1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Use of this source code is governed by a BSD-style license that can be
359d709d503bab6e2b61931737e662dd293b40578ccornelius// found in the LICENSE file.
459d709d503bab6e2b61931737e662dd293b40578ccornelius
5b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/process/process_metrics.h"
6b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
7b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <dirent.h>
8b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <fcntl.h>
9b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <sys/stat.h>
10b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <sys/time.h>
11b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <sys/types.h>
12103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include <unistd.h>
13103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
14103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "base/files/file_util.h"
15103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "base/logging.h"
16103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "base/process/internal_linux.h"
17b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/strings/string_number_conversions.h"
18b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/strings/string_split.h"
19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/strings/string_tokenizer.h"
20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/strings/string_util.h"
21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/sys_info.h"
22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "base/threading/thread_restrictions.h"
23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
24103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusnamespace base {
25103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
26103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusnamespace {
27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid TrimKeyValuePairs(StringPairs* pairs) {
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  DCHECK(pairs);
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  StringPairs& p_ref = *pairs;
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  for (size_t i = 0; i < p_ref.size(); ++i) {
328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    TrimWhitespaceASCII(p_ref[i].first, TRIM_ALL, &p_ref[i].first);
338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    TrimWhitespaceASCII(p_ref[i].second, TRIM_ALL, &p_ref[i].second);
348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  }
358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#if defined(OS_CHROMEOS)
388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// Read a file with a single number string and return the number as a uint64.
398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic uint64 ReadFileToUint64(const FilePath file) {
408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  std::string file_as_string;
418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (!ReadFileToString(file, &file_as_string))
428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return 0;
438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string);
448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  uint64 file_as_uint64 = 0;
458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (!StringToUint64(file_as_string, &file_as_uint64))
468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return 0;
478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return file_as_uint64;
488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#endif
508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// Read /proc/<pid>/status and return the value for |field|, or 0 on failure.
528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// Only works for fields in the form of "Field: value kB".
538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliussize_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) {
548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  std::string status;
558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  {
568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Synchronously reading files in /proc does not hit the disk.
578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ThreadRestrictions::ScopedAllowIO allow_io;
588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    FilePath stat_file = internal::GetProcPidDir(pid).Append("status");
59103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!ReadFileToString(stat_file, &status))
60103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return 0;
61103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
62103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
63103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  StringPairs pairs;
64103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  SplitStringIntoKeyValuePairs(status, ':', '\n', &pairs);
658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  TrimKeyValuePairs(&pairs);
668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  for (size_t i = 0; i < pairs.size(); ++i) {
678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const std::string& key = pairs[i].first;
688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const std::string& value_str = pairs[i].second;
69103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (key == field) {
70103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      std::vector<std::string> split_value_str;
7154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius      SplitString(value_str, ' ', &split_value_str);
728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      if (split_value_str.size() != 2 || split_value_str[1] != "kB") {
738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        NOTREACHED();
748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return 0;
758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      }
768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      size_t value;
778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      if (!StringToSizeT(split_value_str[0], &value)) {
78103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        NOTREACHED();
79103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return 0;
80103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      }
81103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return value;
82103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
83103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
84103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  NOTREACHED();
85103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return 0;
86103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
88103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(OS_LINUX)
89103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Read /proc/<pid>/sched and look for |field|. On succes, return true and
90103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// write the value for |field| into |result|.
91103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Only works for fields in the form of "field    :     uint_value"
92103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ReadProcSchedAndGetFieldAsUint64(pid_t pid,
93103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                      const std::string& field,
94103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                      uint64* result) {
95103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string sched_data;
96103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  {
97103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // Synchronously reading files in /proc does not hit the disk.
98103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    ThreadRestrictions::ScopedAllowIO allow_io;
99103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    FilePath sched_file = internal::GetProcPidDir(pid).Append("sched");
100103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!ReadFileToString(sched_file, &sched_data))
101103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return false;
102103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
103103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
104103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  StringPairs pairs;
105103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  SplitStringIntoKeyValuePairs(sched_data, ':', '\n', &pairs);
1068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  TrimKeyValuePairs(&pairs);
1078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  for (size_t i = 0; i < pairs.size(); ++i) {
108103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const std::string& key = pairs[i].first;
109103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const std::string& value_str = pairs[i].second;
110103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (key == field) {
111103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      uint64 value;
112103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      if (!StringToUint64(value_str, &value))
113103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return false;
114103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      *result = value;
115103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return true;
116103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
117103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
118103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return false;
119103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
120103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif  // defined(OS_LINUX)
121103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
122103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Get the total CPU of a single process.  Return value is number of jiffies
123103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// on success or -1 on error.
124103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint GetProcessCPU(pid_t pid) {
125103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Use /proc/<pid>/task to find all threads and parse their /stat file.
126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath task_path = internal::GetProcPidDir(pid).Append("task");
127103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
128103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  DIR* dir = opendir(task_path.value().c_str());
129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (!dir) {
130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    DPLOG(ERROR) << "opendir(" << task_path.value() << ")";
1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return -1;
132103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int total_cpu = 0;
135103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  while (struct dirent* ent = readdir(dir)) {
136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    pid_t tid = internal::ProcDirSlotToPid(ent->d_name);
1378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (!tid)
1388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      continue;
13959d709d503bab6e2b61931737e662dd293b40578ccornelius
1408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Synchronously reading files in /proc does not hit the disk.
1418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ThreadRestrictions::ScopedAllowIO allow_io;
14259d709d503bab6e2b61931737e662dd293b40578ccornelius
1438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    std::string stat;
1448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    FilePath stat_path =
1458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        task_path.Append(ent->d_name).Append(internal::kStatFile);
1468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (ReadFileToString(stat_path, &stat)) {
1478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      int cpu = ParseProcStatCPU(stat);
1488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      if (cpu > 0)
1498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        total_cpu += cpu;
1508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
1518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  }
1528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  closedir(dir);
1538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return total_cpu;
1558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
15659d709d503bab6e2b61931737e662dd293b40578ccornelius
1578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}  // namespace
1588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// static
1608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
1618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return new ProcessMetrics(process);
16259d709d503bab6e2b61931737e662dd293b40578ccornelius}
1638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// On linux, we return vsize.
1658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliussize_t ProcessMetrics::GetPagefileUsage() const {
1668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return internal::ReadProcStatsAndGetFieldAsSizeT(process_,
167103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                                   internal::VM_VSIZE);
168103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
169103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
170103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// On linux, we return the high water mark of vsize.
171103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliussize_t ProcessMetrics::GetPeakPagefileUsage() const {
172103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return ReadProcStatusAndGetFieldAsSizeT(process_, "VmPeak") * 1024;
173103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// On linux, we return RSS.
176103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliussize_t ProcessMetrics::GetWorkingSetSize() const {
177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return internal::ReadProcStatsAndGetFieldAsSizeT(process_, internal::VM_RSS) *
178103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      getpagesize();
179103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
180103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
181103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// On linux, we return the high water mark of RSS.
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehosize_t ProcessMetrics::GetPeakWorkingSetSize() const {
183103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return ReadProcStatusAndGetFieldAsSizeT(process_, "VmHWM") * 1024;
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
185103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
186103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
187103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                    size_t* shared_bytes) {
188103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  WorkingSetKBytes ws_usage;
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (!GetWorkingSetKBytes(&ws_usage))
190103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
191103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
192103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (private_bytes)
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *private_bytes = ws_usage.priv * 1024;
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
195103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (shared_bytes)
196103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    *shared_bytes = ws_usage.shared * 1024;
197103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return true;
199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
200103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehobool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
202103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(OS_CHROMEOS)
203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (GetWorkingSetKBytesTotmaps(ws_usage))
204103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return true;
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif
206103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return GetWorkingSetKBytesStatm(ws_usage);
207103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
208103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
209103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusdouble ProcessMetrics::GetCPUUsage() {
210103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  TimeTicks time = TimeTicks::Now();
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (last_cpu_ == 0) {
213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // First call, just set the last values.
214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    last_cpu_time_ = time;
215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    last_cpu_ = GetProcessCPU(process_);
216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return 0;
217103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
218103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
219103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int64 time_delta = (time - last_cpu_time_).InMicroseconds();
220103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  DCHECK_NE(time_delta, 0);
221103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (time_delta == 0)
222103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return 0;
223103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
224103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int cpu = GetProcessCPU(process_);
225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
226103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We have the number of jiffies in the time period.  Convert to percentage.
227103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Note this means we will go *over* 100 in the case where multiple threads
228103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // are together adding to more than one CPU's worth.
229103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  TimeDelta cpu_time = internal::ClockTicksToTimeDelta(cpu);
230103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  TimeDelta last_cpu_time = internal::ClockTicksToTimeDelta(last_cpu_);
231103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int percentage = 100 * (cpu_time - last_cpu_time).InSecondsF() /
232103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      TimeDelta::FromMicroseconds(time_delta).InSecondsF();
233103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
234103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  last_cpu_time_ = time;
235103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  last_cpu_ = cpu;
236103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
237103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return percentage;
238103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
239103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
240103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
241103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// in your kernel configuration.
242103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
243103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Synchronously reading files in /proc does not hit the disk.
244103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ThreadRestrictions::ScopedAllowIO allow_io;
245103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string proc_io_contents;
247103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath io_file = internal::GetProcPidDir(process_).Append("io");
248103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (!ReadFileToString(io_file, &proc_io_contents))
249103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
250103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
251103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  io_counters->OtherOperationCount = 0;
252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  io_counters->OtherTransferCount = 0;
253103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
254103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  StringPairs pairs;
255103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs);
256103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  TrimKeyValuePairs(&pairs);
257103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  for (size_t i = 0; i < pairs.size(); ++i) {
258103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const std::string& key = pairs[i].first;
259103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const std::string& value_str = pairs[i].second;
260103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    uint64* target_counter = NULL;
261103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (key == "syscr")
262103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target_counter = &io_counters->ReadOperationCount;
263103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    else if (key == "syscw")
264103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target_counter = &io_counters->WriteOperationCount;
265103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    else if (key == "rchar")
266103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target_counter = &io_counters->ReadTransferCount;
267103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    else if (key == "wchar")
268103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target_counter = &io_counters->WriteTransferCount;
269103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!target_counter)
270103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      continue;
271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    bool converted = StringToUint64(value_str, target_counter);
272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    DCHECK(converted);
273103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
274103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return true;
275103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
276103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
277103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusProcessMetrics::ProcessMetrics(ProcessHandle process)
278103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    : process_(process),
279103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      last_system_time_(0),
280103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(OS_LINUX)
281103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      last_absolute_idle_wakeups_(0),
282103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
283103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      last_cpu_(0) {
284103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  processor_count_ = SysInfo::NumberOfProcessors();
285103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
286103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
287103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(OS_CHROMEOS)
288103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Private, Shared and Proportional working set sizes are obtained from
289103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// /proc/<pid>/totmaps
290103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
291103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const {
292103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // The format of /proc/<pid>/totmaps is:
293103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  //
294103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Rss:                6120 kB
295103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Pss:                3335 kB
296103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Shared_Clean:       1008 kB
297103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Shared_Dirty:       4012 kB
298103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Private_Clean:         4 kB
299103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Private_Dirty:      1096 kB
300103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Referenced:          XXX kB
301103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Anonymous:           XXX kB
302103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // AnonHugePages:       XXX kB
303103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Swap:                XXX kB
304103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Locked:              XXX kB
305103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const size_t kPssIndex = (1 * 3) + 1;
306103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const size_t kPrivate_CleanIndex = (4 * 3) + 1;
307103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const size_t kPrivate_DirtyIndex = (5 * 3) + 1;
308103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const size_t kSwapIndex = (9 * 3) + 1;
309103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
310103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string totmaps_data;
31154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  {
312103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    FilePath totmaps_file = internal::GetProcPidDir(process_).Append("totmaps");
3138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ThreadRestrictions::ScopedAllowIO allow_io;
314103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    bool ret = ReadFileToString(totmaps_file, &totmaps_data);
315103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!ret || totmaps_data.length() == 0)
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      return false;
317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  std::vector<std::string> totmaps_fields;
320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  SplitStringAlongWhitespace(totmaps_data, &totmaps_fields);
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  DCHECK_EQ("Pss:", totmaps_fields[kPssIndex-1]);
323103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  DCHECK_EQ("Private_Clean:", totmaps_fields[kPrivate_CleanIndex - 1]);
324103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  DCHECK_EQ("Private_Dirty:", totmaps_fields[kPrivate_DirtyIndex - 1]);
325103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  DCHECK_EQ("Swap:", totmaps_fields[kSwapIndex-1]);
326103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
327103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int pss = 0;
328103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int private_clean = 0;
329103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int private_dirty = 0;
330103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int swap = 0;
331103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  bool ret = true;
332103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ret &= StringToInt(totmaps_fields[kPssIndex], &pss);
333103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ret &= StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean);
334103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ret &= StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty);
335103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ret &= StringToInt(totmaps_fields[kSwapIndex], &swap);
336103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
3378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  // On ChromeOS swap is to zram. We count this as private / shared, as
3388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  // increased swap decreases available RAM to user processes, which would
3398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  // otherwise create surprising results.
340103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ws_usage->priv = private_clean + private_dirty + swap;
341103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ws_usage->shared = pss + swap;
342103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ws_usage->shareable = 0;
343103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ws_usage->swapped = swap;
344103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return ret;
345103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
346103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
347103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
348103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Private and Shared working set sizes are obtained from /proc/<pid>/statm.
349103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage)
350103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const {
351103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Use statm instead of smaps because smaps is:
352103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // a) Large and slow to parse.
353103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // b) Unavailable in the SUID sandbox.
354103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
355103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // First we need to get the page size, since everything is measured in pages.
356103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // For details, see: man 5 proc.
357103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const int page_size_kb = getpagesize() / 1024;
358103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (page_size_kb <= 0)
359103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
360103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
361103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string statm;
362103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  {
363103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    FilePath statm_file = internal::GetProcPidDir(process_).Append("statm");
364103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // Synchronously reading files in /proc does not hit the disk.
365103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    ThreadRestrictions::ScopedAllowIO allow_io;
366103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    bool ret = ReadFileToString(statm_file, &statm);
367103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!ret || statm.length() == 0)
368103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return false;
369103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
3708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
371103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::vector<std::string> statm_vec;
372103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  SplitString(statm, ' ', &statm_vec);
373103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (statm_vec.size() != 7)
3748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return false;  // Not the format we expect.
375103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
376103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int statm_rss, statm_shared;
3778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  bool ret = true;
3788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  ret &= StringToInt(statm_vec[1], &statm_rss);
3798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  ret &= StringToInt(statm_vec[2], &statm_shared);
3808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
3818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  ws_usage->priv = (statm_rss - statm_shared) * page_size_kb;
3828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  ws_usage->shared = statm_shared * page_size_kb;
3838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
384103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Sharable is not calculated, as it does not provide interesting data.
385103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ws_usage->shareable = 0;
3868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
3878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#if defined(OS_CHROMEOS)
388103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Can't get swapped memory from statm.
389103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ws_usage->swapped = 0;
3908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#endif
391103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
392103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return ret;
393103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
394103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
395103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliussize_t GetSystemCommitCharge() {
396103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  SystemMemoryInfoKB meminfo;
397103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (!GetSystemMemoryInfo(&meminfo))
398103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return 0;
399103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached;
400103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
401103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
402103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Exposed for testing.
403103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint ParseProcStatCPU(const std::string& input) {
404103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::vector<std::string> proc_stats;
405103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (!internal::ParseProcStats(input, &proc_stats))
406103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return -1;
407103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
408103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (proc_stats.size() <= internal::VM_STIME)
409103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return -1;
410103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int utime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME);
4118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  int stime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
412103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return utime + stime;
413103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
414103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
415103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst char kProcSelfExe[] = "/proc/self/exe";
416103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
417103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint GetNumberOfThreads(ProcessHandle process) {
418103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return internal::ReadProcStatsAndGetFieldAsInt64(process,
419103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                                   internal::VM_NUMTHREADS);
420103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
4218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
422103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusnamespace {
423103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
424103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// The format of /proc/diskstats is:
425103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Device major number
426103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Device minor number
427103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Device name
428103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  1 -- # of reads completed
429103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This is the total number of reads completed successfully.
430103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  2 -- # of reads merged, field 6 -- # of writes merged
431103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      Reads and writes which are adjacent to each other may be merged for
432103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      efficiency.  Thus two 4K reads may become one 8K read before it is
433103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      ultimately handed to the disk, and so it will be counted (and queued)
434103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      as only one I/O.  This field lets you know how often this was done.
435103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  3 -- # of sectors read
436103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This is the total number of sectors read successfully.
437103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  4 -- # of milliseconds spent reading
438103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This is the total number of milliseconds spent by all reads (as
439103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      measured from __make_request() to end_that_request_last()).
440103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  5 -- # of writes completed
44159d709d503bab6e2b61931737e662dd293b40578ccornelius//      This is the total number of writes completed successfully.
442103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  6 -- # of writes merged
443103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      See the description of field 2.
444103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  7 -- # of sectors written
445103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This is the total number of sectors written successfully.
446103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  8 -- # of milliseconds spent writing
447103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This is the total number of milliseconds spent by all writes (as
448103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      measured from __make_request() to end_that_request_last()).
449103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field  9 -- # of I/Os currently in progress
4508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius//      The only field that should go to zero. Incremented as requests are
451103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      given to appropriate struct request_queue and decremented as they
452103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      finish.
453103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field 10 -- # of milliseconds spent doing I/Os
454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This field increases so long as field 9 is nonzero.
455103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//  Field 11 -- weighted # of milliseconds spent doing I/Os
456103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      This field is incremented at each I/O start, I/O completion, I/O
457103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      merge, or read of these stats by the number of I/Os in progress
458103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      (field 9) times the number of milliseconds spent doing I/O since the
459103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      last update of this field.  This can provide an easy measure of both
460103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius//      I/O completion time and the backlog that may be accumulating.
461103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
462103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskDriveName = 2;
463103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskReads = 3;
464103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskReadsMerged = 4;
465103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskSectorsRead = 5;
466103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskReadTime = 6;
467103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskWrites = 7;
468103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskWritesMerged = 8;
469103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskSectorsWritten = 9;
470103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskWriteTime = 10;
471103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskIO = 11;
472103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskIOTime = 12;
473103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst size_t kDiskWeightedIOTime = 13;
474103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
475103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}  // namespace
476103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
4778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusSystemMemoryInfoKB::SystemMemoryInfoKB() {
478103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  total = 0;
479103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  free = 0;
480103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  buffers = 0;
481103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  cached = 0;
482103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  active_anon = 0;
483103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  inactive_anon = 0;
484103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  active_file = 0;
485103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  inactive_file = 0;
486103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  swap_total = 0;
487103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  swap_free = 0;
488103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  dirty = 0;
489103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
490103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  pswpin = 0;
491103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  pswpout = 0;
492103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  pgmajfault = 0;
493103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
494103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifdef OS_CHROMEOS
495103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  shmem = 0;
496103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  slab = 0;
497103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  gem_objects = -1;
498103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  gem_size = -1;
499103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
500103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
501103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
502103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusscoped_ptr<Value> SystemMemoryInfoKB::ToValue() const {
503103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  scoped_ptr<DictionaryValue> res(new DictionaryValue());
504103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
505103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("total", total);
506103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("free", free);
507103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("buffers", buffers);
508103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("cached", cached);
509103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("active_anon", active_anon);
510103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("inactive_anon", inactive_anon);
511103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("active_file", active_file);
512103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("inactive_file", inactive_file);
513103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("swap_total", swap_total);
514103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("swap_free", swap_free);
515103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("swap_used", swap_total - swap_free);
516103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("dirty", dirty);
517103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("pswpin", pswpin);
518103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("pswpout", pswpout);
519103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("pgmajfault", pgmajfault);
520103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifdef OS_CHROMEOS
521103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("shmem", shmem);
522103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("slab", slab);
523103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("gem_objects", gem_objects);
524103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetInteger("gem_size", gem_size);
525103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
526103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
527103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return res.PassAs<Value>();
528103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
529103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
53054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius// exposed for testing
531103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ParseProcMeminfo(const std::string& meminfo_data,
532103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                      SystemMemoryInfoKB* meminfo) {
533103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // The format of /proc/meminfo is:
53454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  //
535103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // MemTotal:      8235324 kB
536103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // MemFree:       1628304 kB
537103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Buffers:        429596 kB
538103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Cached:        4728232 kB
539103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // ...
540103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // There is no guarantee on the ordering or position
541103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // though it doesn't appear to change very often
542103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
543103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // As a basic sanity check, let's make sure we at least get non-zero
544103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // MemTotal value
545103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  meminfo->total = 0;
546103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
547103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::vector<std::string> meminfo_lines;
548103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  Tokenize(meminfo_data, "\n", &meminfo_lines);
549103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  for (std::vector<std::string>::iterator it = meminfo_lines.begin();
550103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius       it != meminfo_lines.end(); ++it) {
551103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    std::vector<std::string> tokens;
552103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    SplitStringAlongWhitespace(*it, &tokens);
553103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // HugePages_* only has a number and no suffix so we can't rely on
554103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // there being exactly 3 tokens.
555103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (tokens.size() <= 1) {
556103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      DLOG(WARNING) << "meminfo: tokens: " << tokens.size()
557103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    << " malformed line: " << *it;
558103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      continue;
559103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
560103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
561103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int* target = NULL;
562103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (tokens[0] == "MemTotal:")
563103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target = &meminfo->total;
564103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    else if (tokens[0] == "MemFree:")
5658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->free;
5668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Buffers:")
5678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->buffers;
5688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Cached:")
5698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->cached;
5708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Active(anon):")
5718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->active_anon;
5728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Inactive(anon):")
5738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->inactive_anon;
5748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Active(file):")
5758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->active_file;
5768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Inactive(file):")
5778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->inactive_file;
5788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "SwapTotal:")
5798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->swap_total;
5808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "SwapFree:")
5818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      target = &meminfo->swap_free;
5828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    else if (tokens[0] == "Dirty:")
583103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target = &meminfo->dirty;
584103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(OS_CHROMEOS)
585103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // Chrome OS has a tweaked kernel that allows us to query Shmem, which is
586103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // usually video memory otherwise invisible to the OS.
587103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    else if (tokens[0] == "Shmem:")
588103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target = &meminfo->shmem;
589103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    else if (tokens[0] == "Slab:")
590103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      target = &meminfo->slab;
591103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
5928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (target)
593103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToInt(tokens[1], target);
594103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
595103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
596103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Make sure we got a valid MemTotal.
597103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return meminfo->total > 0;
598103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
599103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
600103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// exposed for testing
601103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool ParseProcVmstat(const std::string& vmstat_data,
602103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                     SystemMemoryInfoKB* meminfo) {
603103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // The format of /proc/vmstat is:
604103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  //
605103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // nr_free_pages 299878
606103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // nr_inactive_anon 239863
607103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // nr_active_anon 1318966
608103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // nr_inactive_file 2015629
609103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // ...
610103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  //
611103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We iterate through the whole file because the position of the
612103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // fields are dependent on the kernel version and configuration.
613103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
614103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::vector<std::string> vmstat_lines;
615103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  Tokenize(vmstat_data, "\n", &vmstat_lines);
616103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  for (std::vector<std::string>::iterator it = vmstat_lines.begin();
617103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius       it != vmstat_lines.end(); ++it) {
618103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    std::vector<std::string> tokens;
619103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    SplitString(*it, ' ', &tokens);
620103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (tokens.size() != 2)
621103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      continue;
622103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
623103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (tokens[0] == "pswpin") {
624103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToInt(tokens[1], &meminfo->pswpin);
625103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    } else if (tokens[0] == "pswpout") {
626103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToInt(tokens[1], &meminfo->pswpout);
627103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    } else if (tokens[0] == "pgmajfault") {
628103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToInt(tokens[1], &meminfo->pgmajfault);
629103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
630103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
631103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
632103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return true;
633103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
634103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
635103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
636103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Synchronously reading files in /proc and /sys are safe.
637103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ThreadRestrictions::ScopedAllowIO allow_io;
638103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
639103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Used memory is: total - free - buffers - caches
640103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath meminfo_file("/proc/meminfo");
641103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string meminfo_data;
64259d709d503bab6e2b61931737e662dd293b40578ccornelius  if (!ReadFileToString(meminfo_file, &meminfo_data)) {
64359d709d503bab6e2b61931737e662dd293b40578ccornelius    DLOG(WARNING) << "Failed to open " << meminfo_file.value();
64459d709d503bab6e2b61931737e662dd293b40578ccornelius    return false;
645103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
646103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
647103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (!ParseProcMeminfo(meminfo_data, meminfo)) {
648103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    DLOG(WARNING) << "Failed to parse " << meminfo_file.value();
649103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
650103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
651103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
652103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(OS_CHROMEOS)
653103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Report on Chrome OS GEM object graphics memory. /var/run/debugfs_gpu is a
654103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // bind mount into /sys/kernel/debug and synchronously reading the in-memory
655103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // files in /sys is fast.
656103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(ARCH_CPU_ARM_FAMILY)
657103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath geminfo_file("/var/run/debugfs_gpu/exynos_gem_objects");
658103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#else
659103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath geminfo_file("/var/run/debugfs_gpu/i915_gem_objects");
660103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
66159d709d503bab6e2b61931737e662dd293b40578ccornelius  std::string geminfo_data;
66259d709d503bab6e2b61931737e662dd293b40578ccornelius  meminfo->gem_objects = -1;
66359d709d503bab6e2b61931737e662dd293b40578ccornelius  meminfo->gem_size = -1;
66459d709d503bab6e2b61931737e662dd293b40578ccornelius  if (ReadFileToString(geminfo_file, &geminfo_data)) {
66559d709d503bab6e2b61931737e662dd293b40578ccornelius    int gem_objects = -1;
66659d709d503bab6e2b61931737e662dd293b40578ccornelius    long long gem_size = -1;
66759d709d503bab6e2b61931737e662dd293b40578ccornelius    int num_res = sscanf(geminfo_data.c_str(),
66859d709d503bab6e2b61931737e662dd293b40578ccornelius                         "%d objects, %lld bytes",
66959d709d503bab6e2b61931737e662dd293b40578ccornelius                         &gem_objects, &gem_size);
67059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (num_res == 2) {
67159d709d503bab6e2b61931737e662dd293b40578ccornelius      meminfo->gem_objects = gem_objects;
67259d709d503bab6e2b61931737e662dd293b40578ccornelius      meminfo->gem_size = gem_size;
67359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
67459d709d503bab6e2b61931737e662dd293b40578ccornelius  }
67559d709d503bab6e2b61931737e662dd293b40578ccornelius
67659d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined(ARCH_CPU_ARM_FAMILY)
67759d709d503bab6e2b61931737e662dd293b40578ccornelius  // Incorporate Mali graphics memory if present.
67859d709d503bab6e2b61931737e662dd293b40578ccornelius  FilePath mali_memory_file("/sys/class/misc/mali0/device/memory");
67959d709d503bab6e2b61931737e662dd293b40578ccornelius  std::string mali_memory_data;
68059d709d503bab6e2b61931737e662dd293b40578ccornelius  if (ReadFileToString(mali_memory_file, &mali_memory_data)) {
68159d709d503bab6e2b61931737e662dd293b40578ccornelius    long long mali_size = -1;
6828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int num_res = sscanf(mali_memory_data.c_str(), "%lld bytes", &mali_size);
683103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (num_res == 1)
684103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      meminfo->gem_size += mali_size;
685103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
686103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif  // defined(ARCH_CPU_ARM_FAMILY)
68759d709d503bab6e2b61931737e662dd293b40578ccornelius#endif  // defined(OS_CHROMEOS)
688103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
689103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath vmstat_file("/proc/vmstat");
690103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string vmstat_data;
6918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (!ReadFileToString(vmstat_file, &vmstat_data)) {
692103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    DLOG(WARNING) << "Failed to open " << vmstat_file.value();
693103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
6948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  }
6958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (!ParseProcVmstat(vmstat_data, meminfo)) {
6968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    DLOG(WARNING) << "Failed to parse " << vmstat_file.value();
6978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return false;
6988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  }
6998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return true;
7018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
7028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusSystemDiskInfo::SystemDiskInfo() {
7048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  reads = 0;
705103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  reads_merged = 0;
7068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  sectors_read = 0;
7078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  read_time = 0;
7088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  writes = 0;
709103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  writes_merged = 0;
7108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  sectors_written = 0;
7118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  write_time = 0;
7128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  io = 0;
7138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  io_time = 0;
7148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  weighted_io_time = 0;
7158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
7168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusscoped_ptr<Value> SystemDiskInfo::ToValue() const {
7188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  scoped_ptr<DictionaryValue> res(new DictionaryValue());
7198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  // Write out uint64 variables as doubles.
7218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  // Note: this may discard some precision, but for JS there's no other option.
7228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("reads", static_cast<double>(reads));
7238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("reads_merged", static_cast<double>(reads_merged));
7248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("sectors_read", static_cast<double>(sectors_read));
7258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("read_time", static_cast<double>(read_time));
7268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("writes", static_cast<double>(writes));
7278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("writes_merged", static_cast<double>(writes_merged));
7288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("sectors_written", static_cast<double>(sectors_written));
7298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("write_time", static_cast<double>(write_time));
7308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("io", static_cast<double>(io));
7318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("io_time", static_cast<double>(io_time));
7328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("weighted_io_time", static_cast<double>(weighted_io_time));
7338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return res.PassAs<Value>();
7358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
7368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusbool IsValidDiskName(const std::string& candidate) {
7388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (candidate.length() < 3)
7398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return false;
7408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (candidate[1] == 'd' &&
7418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      (candidate[0] == 'h' || candidate[0] == 's' || candidate[0] == 'v')) {
7428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // [hsv]d[a-z]+ case
7438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    for (size_t i = 2; i < candidate.length(); ++i) {
7448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      if (!islower(candidate[i]))
7458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return false;
7468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
74759d709d503bab6e2b61931737e662dd293b40578ccornelius    return true;
74859d709d503bab6e2b61931737e662dd293b40578ccornelius  }
74959d709d503bab6e2b61931737e662dd293b40578ccornelius
750103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  const char kMMCName[] = "mmcblk";
75159d709d503bab6e2b61931737e662dd293b40578ccornelius  const size_t kMMCNameLen = strlen(kMMCName);
752103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (candidate.length() < kMMCNameLen + 1)
753103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
754103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (candidate.compare(0, kMMCNameLen, kMMCName) != 0)
755103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
756103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // mmcblk[0-9]+ case
758103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  for (size_t i = kMMCNameLen; i < candidate.length(); ++i) {
759103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!isdigit(candidate[i]))
760103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return false;
761103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
762103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return true;
763103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
764103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
765103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusbool GetSystemDiskInfo(SystemDiskInfo* diskinfo) {
766103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Synchronously reading files in /proc does not hit the disk.
767103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  ThreadRestrictions::ScopedAllowIO allow_io;
768103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
769103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  FilePath diskinfo_file("/proc/diskstats");
770103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::string diskinfo_data;
771103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (!ReadFileToString(diskinfo_file, &diskinfo_data)) {
772103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    DLOG(WARNING) << "Failed to open " << diskinfo_file.value();
773103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
774103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
775103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
776103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  std::vector<std::string> diskinfo_lines;
777103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  size_t line_count = Tokenize(diskinfo_data, "\n", &diskinfo_lines);
778103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if (line_count == 0) {
779103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    DLOG(WARNING) << "No lines found";
780103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return false;
781103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
782103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
783103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->reads = 0;
784103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->reads_merged = 0;
785103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->sectors_read = 0;
786103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->read_time = 0;
787103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->writes = 0;
788103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->writes_merged = 0;
789103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->sectors_written = 0;
790103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->write_time = 0;
791103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->io = 0;
792103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->io_time = 0;
793103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  diskinfo->weighted_io_time = 0;
794103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
795103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 reads = 0;
796103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 reads_merged = 0;
797103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 sectors_read = 0;
798103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 read_time = 0;
799103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 writes = 0;
800103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 writes_merged = 0;
801103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 sectors_written = 0;
802103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 write_time = 0;
803103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 io = 0;
804103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 io_time = 0;
805103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 weighted_io_time = 0;
806103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
807103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  for (size_t i = 0; i < line_count; i++) {
808103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    std::vector<std::string> disk_fields;
809103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    SplitStringAlongWhitespace(diskinfo_lines[i], &disk_fields);
810103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
811103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // Fields may have overflowed and reset to zero.
8128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (IsValidDiskName(disk_fields[kDiskDriveName])) {
8138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      StringToUint64(disk_fields[kDiskReads], &reads);
8148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      StringToUint64(disk_fields[kDiskReadsMerged], &reads_merged);
8158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      StringToUint64(disk_fields[kDiskSectorsRead], &sectors_read);
8168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      StringToUint64(disk_fields[kDiskReadTime], &read_time);
817103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToUint64(disk_fields[kDiskWrites], &writes);
8188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      StringToUint64(disk_fields[kDiskWritesMerged], &writes_merged);
819103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToUint64(disk_fields[kDiskSectorsWritten], &sectors_written);
820103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToUint64(disk_fields[kDiskWriteTime], &write_time);
821103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToUint64(disk_fields[kDiskIO], &io);
822103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToUint64(disk_fields[kDiskIOTime], &io_time);
823103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      StringToUint64(disk_fields[kDiskWeightedIOTime], &weighted_io_time);
824103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
8258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      diskinfo->reads += reads;
826103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->reads_merged += reads_merged;
8278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      diskinfo->sectors_read += sectors_read;
828103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->read_time += read_time;
829103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->writes += writes;
830103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->writes_merged += writes_merged;
831103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->sectors_written += sectors_written;
832103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->write_time += write_time;
833103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->io += io;
834103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->io_time += io_time;
835103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      diskinfo->weighted_io_time += weighted_io_time;
836103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
837103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
838103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
839103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return true;
8408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
8418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#if defined(OS_CHROMEOS)
8438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusscoped_ptr<Value> SwapInfo::ToValue() const {
844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  scoped_ptr<DictionaryValue> res(new DictionaryValue());
845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
846103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Write out uint64 variables as doubles.
847103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // Note: this may discard some precision, but for JS there's no other option.
848103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetDouble("num_reads", static_cast<double>(num_reads));
849103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetDouble("num_writes", static_cast<double>(num_writes));
850103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetDouble("orig_data_size", static_cast<double>(orig_data_size));
8518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  res->SetDouble("compr_data_size", static_cast<double>(compr_data_size));
852103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  res->SetDouble("mem_used_total", static_cast<double>(mem_used_total));
8538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (compr_data_size > 0)
8548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    res->SetDouble("compression_ratio", static_cast<double>(orig_data_size) /
8558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                        static_cast<double>(compr_data_size));
8568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  else
857103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    res->SetDouble("compression_ratio", 0);
858103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
859103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return res.PassAs<Value>();
860103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
861103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
8628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid GetSwapInfo(SwapInfo* swap_info) {
8638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  // Synchronously reading files in /sys/block/zram0 does not hit the disk.
8648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  ThreadRestrictions::ScopedAllowIO allow_io;
8658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  FilePath zram_path("/sys/block/zram0");
8678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size"));
8688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  if (orig_data_size <= 4096) {
869103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // A single page is compressed at startup, and has a high compression
8708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // ratio. We ignore this as it doesn't indicate any real swapping.
8718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    swap_info->orig_data_size = 0;
8728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    swap_info->num_reads = 0;
8738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    swap_info->num_writes = 0;
874103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    swap_info->compr_data_size = 0;
875103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    swap_info->mem_used_total = 0;
876103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return;
877103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
878103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  swap_info->orig_data_size = orig_data_size;
8798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  swap_info->num_reads = ReadFileToUint64(zram_path.Append("num_reads"));
8808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  swap_info->num_writes = ReadFileToUint64(zram_path.Append("num_writes"));
8818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  swap_info->compr_data_size =
8828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      ReadFileToUint64(zram_path.Append("compr_data_size"));
8838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  swap_info->mem_used_total =
8848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      ReadFileToUint64(zram_path.Append("mem_used_total"));
8858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
8868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#endif  // defined(OS_CHROMEOS)
8878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#if defined(OS_LINUX)
8898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusint ProcessMetrics::GetIdleWakeupsPerSecond() {
890103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uint64 wake_ups;
8918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  const char kWakeupStat[] = "se.statistics.nr_wakeups";
8928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  return ReadProcSchedAndGetFieldAsUint64(process_, kWakeupStat, &wake_ups) ?
8938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      CalculateIdleWakeupsPerSecond(wake_ups) : 0;
894103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
895103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif  // defined(OS_LINUX)
896103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
897103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}  // namespace base
898103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius