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], §ors_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], §ors_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