1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/process/process_metrics.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <dirent.h> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <fcntl.h> 9cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stddef.h> 10cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stdint.h> 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/stat.h> 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/time.h> 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/types.h> 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <unistd.h> 15cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <utility> 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 17cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/files/dir_reader_posix.h" 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/files/file_util.h" 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/process/internal_linux.h" 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/string_number_conversions.h" 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/string_split.h" 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/string_tokenizer.h" 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/string_util.h" 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/sys_info.h" 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/thread_restrictions.h" 27cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "build/build_config.h" 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TrimKeyValuePairs(StringPairs* pairs) { 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(pairs); 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringPairs& p_ref = *pairs; 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (size_t i = 0; i < p_ref.size(); ++i) { 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrimWhitespaceASCII(p_ref[i].first, TRIM_ALL, &p_ref[i].first); 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrimWhitespaceASCII(p_ref[i].second, TRIM_ALL, &p_ref[i].second); 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 43cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko// Read a file with a single number string and return the number as a uint64_t. 44cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkostatic uint64_t ReadFileToUint64(const FilePath file) { 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string file_as_string; 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(file, &file_as_string)) 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string); 49cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t file_as_uint64 = 0; 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!StringToUint64(file_as_string, &file_as_uint64)) 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return file_as_uint64; 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Read /proc/<pid>/status and return the value for |field|, or 0 on failure. 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Only works for fields in the form of "Field: value kB". 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratsize_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) { 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string status; 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc does not hit the disk. 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath stat_file = internal::GetProcPidDir(pid).Append("status"); 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(stat_file, &status)) 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringPairs pairs; 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SplitStringIntoKeyValuePairs(status, ':', '\n', &pairs); 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrimKeyValuePairs(&pairs); 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (size_t i = 0; i < pairs.size(); ++i) { 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& key = pairs[i].first; 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& value_str = pairs[i].second; 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (key == field) { 75cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<StringPiece> split_value_str = SplitStringPiece( 76cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko value_str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (split_value_str.size() != 2 || split_value_str[1] != "kB") { 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t value; 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!StringToSizeT(split_value_str[0], &value)) { 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return value; 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_LINUX) 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Read /proc/<pid>/sched and look for |field|. On succes, return true and 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// write the value for |field| into |result|. 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Only works for fields in the form of "field : uint_value" 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ReadProcSchedAndGetFieldAsUint64(pid_t pid, 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& field, 99cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t* result) { 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string sched_data; 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc does not hit the disk. 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath sched_file = internal::GetProcPidDir(pid).Append("sched"); 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(sched_file, &sched_data)) 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringPairs pairs; 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SplitStringIntoKeyValuePairs(sched_data, ':', '\n', &pairs); 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrimKeyValuePairs(&pairs); 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (size_t i = 0; i < pairs.size(); ++i) { 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& key = pairs[i].first; 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& value_str = pairs[i].second; 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (key == field) { 116cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t value; 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!StringToUint64(value_str, &value)) 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *result = value; 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_LINUX) 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Get the total CPU of a single process. Return value is number of jiffies 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// on success or -1 on error. 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint GetProcessCPU(pid_t pid) { 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Use /proc/<pid>/task to find all threads and parse their /stat file. 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath task_path = internal::GetProcPidDir(pid).Append("task"); 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DIR* dir = opendir(task_path.value().c_str()); 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!dir) { 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(ERROR) << "opendir(" << task_path.value() << ")"; 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return -1; 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int total_cpu = 0; 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (struct dirent* ent = readdir(dir)) { 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat pid_t tid = internal::ProcDirSlotToPid(ent->d_name); 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!tid) 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat continue; 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc does not hit the disk. 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string stat; 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath stat_path = 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_path.Append(ent->d_name).Append(internal::kStatFile); 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (ReadFileToString(stat_path, &stat)) { 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int cpu = ParseProcStatCPU(stat); 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (cpu > 0) 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat total_cpu += cpu; 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat closedir(dir); 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return total_cpu; 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return new ProcessMetrics(process); 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// On linux, we return vsize. 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratsize_t ProcessMetrics::GetPagefileUsage() const { 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return internal::ReadProcStatsAndGetFieldAsSizeT(process_, 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat internal::VM_VSIZE); 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// On linux, we return the high water mark of vsize. 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratsize_t ProcessMetrics::GetPeakPagefileUsage() const { 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ReadProcStatusAndGetFieldAsSizeT(process_, "VmPeak") * 1024; 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// On linux, we return RSS. 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratsize_t ProcessMetrics::GetWorkingSetSize() const { 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return internal::ReadProcStatsAndGetFieldAsSizeT(process_, internal::VM_RSS) * 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat getpagesize(); 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// On linux, we return the high water mark of RSS. 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratsize_t ProcessMetrics::GetPeakWorkingSetSize() const { 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ReadProcStatusAndGetFieldAsSizeT(process_, "VmHWM") * 1024; 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, 192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t* shared_bytes) { 193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WorkingSetKBytes ws_usage; 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!GetWorkingSetKBytes(&ws_usage)) 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (private_bytes) 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *private_bytes = ws_usage.priv * 1024; 199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (shared_bytes) 201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *shared_bytes = ws_usage.shared * 1024; 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { 207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (GetWorkingSetKBytesTotmaps(ws_usage)) 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return GetWorkingSetKBytesStatm(ws_usage); 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratdouble ProcessMetrics::GetCPUUsage() { 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TimeTicks time = TimeTicks::Now(); 216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (last_cpu_ == 0) { 218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // First call, just set the last values. 219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_cpu_time_ = time; 220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_cpu_ = GetProcessCPU(process_); 221cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return 0.0; 222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 224cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko TimeDelta time_delta = time - last_cpu_time_; 225cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (time_delta.is_zero()) { 226cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko NOTREACHED(); 227cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return 0.0; 228cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int cpu = GetProcessCPU(process_); 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We have the number of jiffies in the time period. Convert to percentage. 233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Note this means we will go *over* 100 in the case where multiple threads 234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // are together adding to more than one CPU's worth. 235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TimeDelta cpu_time = internal::ClockTicksToTimeDelta(cpu); 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TimeDelta last_cpu_time = internal::ClockTicksToTimeDelta(last_cpu_); 237cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 238cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // If the number of threads running in the process has decreased since the 239cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // last time this function was called, |last_cpu_time| will be greater than 240cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // |cpu_time| which will result in a negative value in the below percentage 241cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // calculation. We prevent this by clamping to 0. crbug.com/546565. 242cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // This computation is known to be shaky when threads are destroyed between 243cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // "last" and "now", but for our current purposes, it's all right. 244cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko double percentage = 0.0; 245cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (last_cpu_time < cpu_time) { 246cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko percentage = 100.0 * (cpu_time - last_cpu_time).InSecondsF() / 247cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko time_delta.InSecondsF(); 248cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_cpu_time_ = time; 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_cpu_ = cpu; 252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return percentage; 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING 257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// in your kernel configuration. 258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { 259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc does not hit the disk. 260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string proc_io_contents; 263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath io_file = internal::GetProcPidDir(process_).Append("io"); 264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(io_file, &proc_io_contents)) 265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat io_counters->OtherOperationCount = 0; 268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat io_counters->OtherTransferCount = 0; 269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringPairs pairs; 271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs); 272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrimKeyValuePairs(&pairs); 273b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (size_t i = 0; i < pairs.size(); ++i) { 274b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& key = pairs[i].first; 275b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& value_str = pairs[i].second; 276cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t* target_counter = NULL; 277b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (key == "syscr") 278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target_counter = &io_counters->ReadOperationCount; 279b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (key == "syscw") 280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target_counter = &io_counters->WriteOperationCount; 281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (key == "rchar") 282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target_counter = &io_counters->ReadTransferCount; 283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (key == "wchar") 284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target_counter = &io_counters->WriteTransferCount; 285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!target_counter) 286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat continue; 287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool converted = StringToUint64(value_str, target_counter); 288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(converted); 289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 290b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 291b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 292b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 293cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#if defined(OS_LINUX) 294cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkoint ProcessMetrics::GetOpenFdCount() const { 295cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // Use /proc/<pid>/fd to count the number of entries there. 296cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko FilePath fd_path = internal::GetProcPidDir(process_).Append("fd"); 297cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 298cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko DirReaderPosix dir_reader(fd_path.value().c_str()); 299cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (!dir_reader.IsValid()) 300cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return -1; 301cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 302cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko int total_count = 0; 303cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (; dir_reader.Next(); ) { 304cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const char* name = dir_reader.name(); 305cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) 306cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko ++total_count; 307cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } 308cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 309cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return total_count; 310cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko} 311cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#endif // defined(OS_LINUX) 312cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 313b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessMetrics::ProcessMetrics(ProcessHandle process) 314b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : process_(process), 315b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_system_time_(0), 316b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_LINUX) 317b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_absolute_idle_wakeups_(0), 318b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 319b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_cpu_(0) { 320b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat processor_count_ = SysInfo::NumberOfProcessors(); 321b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 322b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 323b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 324b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Private, Shared and Proportional working set sizes are obtained from 325b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// /proc/<pid>/totmaps 326b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) 327b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const { 328b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The format of /proc/<pid>/totmaps is: 329b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 330b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Rss: 6120 kB 331b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Pss: 3335 kB 332b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Shared_Clean: 1008 kB 333b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Shared_Dirty: 4012 kB 334b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Private_Clean: 4 kB 335b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Private_Dirty: 1096 kB 336b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Referenced: XXX kB 337b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Anonymous: XXX kB 338b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // AnonHugePages: XXX kB 339b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Swap: XXX kB 340b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Locked: XXX kB 341b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kPssIndex = (1 * 3) + 1; 342b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kPrivate_CleanIndex = (4 * 3) + 1; 343b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kPrivate_DirtyIndex = (5 * 3) + 1; 344b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kSwapIndex = (9 * 3) + 1; 345b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 346b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string totmaps_data; 347b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 348b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath totmaps_file = internal::GetProcPidDir(process_).Append("totmaps"); 349b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 350b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool ret = ReadFileToString(totmaps_file, &totmaps_data); 351b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ret || totmaps_data.length() == 0) 352b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 353b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 354b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 355cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<std::string> totmaps_fields = SplitString( 356cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko totmaps_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE, 357cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko base::SPLIT_WANT_NONEMPTY); 358b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 359b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ("Pss:", totmaps_fields[kPssIndex-1]); 360b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ("Private_Clean:", totmaps_fields[kPrivate_CleanIndex - 1]); 361b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ("Private_Dirty:", totmaps_fields[kPrivate_DirtyIndex - 1]); 362b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ("Swap:", totmaps_fields[kSwapIndex-1]); 363b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 364b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int pss = 0; 365b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int private_clean = 0; 366b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int private_dirty = 0; 367b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int swap = 0; 368b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool ret = true; 369b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ret &= StringToInt(totmaps_fields[kPssIndex], &pss); 370b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ret &= StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean); 371b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ret &= StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty); 372b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ret &= StringToInt(totmaps_fields[kSwapIndex], &swap); 373b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 374b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // On ChromeOS swap is to zram. We count this as private / shared, as 375b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // increased swap decreases available RAM to user processes, which would 376b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // otherwise create surprising results. 377b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->priv = private_clean + private_dirty + swap; 378b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->shared = pss + swap; 379b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->shareable = 0; 380b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->swapped = swap; 381b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ret; 382b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 383b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 384b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 385b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Private and Shared working set sizes are obtained from /proc/<pid>/statm. 386b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) 387b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const { 388b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Use statm instead of smaps because smaps is: 389b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // a) Large and slow to parse. 390b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // b) Unavailable in the SUID sandbox. 391b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 392b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // First we need to get the page size, since everything is measured in pages. 393b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // For details, see: man 5 proc. 394b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const int page_size_kb = getpagesize() / 1024; 395b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (page_size_kb <= 0) 396b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 397b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 398b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string statm; 399b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 400b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath statm_file = internal::GetProcPidDir(process_).Append("statm"); 401b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc does not hit the disk. 402b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 403b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool ret = ReadFileToString(statm_file, &statm); 404b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ret || statm.length() == 0) 405b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 406b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 407b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 408cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<StringPiece> statm_vec = SplitStringPiece( 409cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko statm, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 410b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (statm_vec.size() != 7) 411b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; // Not the format we expect. 412b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 413b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int statm_rss, statm_shared; 414b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool ret = true; 415b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ret &= StringToInt(statm_vec[1], &statm_rss); 416b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ret &= StringToInt(statm_vec[2], &statm_shared); 417b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 418b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->priv = (statm_rss - statm_shared) * page_size_kb; 419b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->shared = statm_shared * page_size_kb; 420b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 421b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Sharable is not calculated, as it does not provide interesting data. 422b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->shareable = 0; 423b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 424b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 425b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Can't get swapped memory from statm. 426b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ws_usage->swapped = 0; 427b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 428b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 429b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ret; 430b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 431b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 432b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratsize_t GetSystemCommitCharge() { 433b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SystemMemoryInfoKB meminfo; 434b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!GetSystemMemoryInfo(&meminfo)) 435b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 436b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached; 437b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 438b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 439b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint ParseProcStatCPU(const std::string& input) { 440b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // |input| may be empty if the process disappeared somehow. 441b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // e.g. http://crbug.com/145811. 442b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (input.empty()) 443b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return -1; 444b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 445b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t start = input.find_last_of(')'); 446b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (start == input.npos) 447b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return -1; 448b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 449b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Number of spaces remaining until reaching utime's index starting after the 450b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // last ')'. 451b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int num_spaces_remaining = internal::VM_UTIME - 1; 452b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 453b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t i = start; 454b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while ((i = input.find(' ', i + 1)) != input.npos) { 455b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Validate the assumption that there aren't any contiguous spaces 456b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // in |input| before utime. 457b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_NE(input[i - 1], ' '); 458b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (--num_spaces_remaining == 0) { 459b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int utime = 0; 460b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int stime = 0; 461b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (sscanf(&input.data()[i], "%d %d", &utime, &stime) != 2) 462b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return -1; 463b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 464b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return utime + stime; 465b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 466b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 467b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 468b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return -1; 469b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 470b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 471b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst char kProcSelfExe[] = "/proc/self/exe"; 472b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 473b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint GetNumberOfThreads(ProcessHandle process) { 474b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return internal::ReadProcStatsAndGetFieldAsInt64(process, 475b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat internal::VM_NUMTHREADS); 476b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 477b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 478b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 479b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 480b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The format of /proc/diskstats is: 481b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Device major number 482b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Device minor number 483b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Device name 484b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 1 -- # of reads completed 485b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This is the total number of reads completed successfully. 486b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 2 -- # of reads merged, field 6 -- # of writes merged 487b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Reads and writes which are adjacent to each other may be merged for 488b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// efficiency. Thus two 4K reads may become one 8K read before it is 489b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ultimately handed to the disk, and so it will be counted (and queued) 490b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// as only one I/O. This field lets you know how often this was done. 491b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 3 -- # of sectors read 492b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This is the total number of sectors read successfully. 493b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 4 -- # of milliseconds spent reading 494b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This is the total number of milliseconds spent by all reads (as 495b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// measured from __make_request() to end_that_request_last()). 496b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 5 -- # of writes completed 497b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This is the total number of writes completed successfully. 498b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 6 -- # of writes merged 499b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// See the description of field 2. 500b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 7 -- # of sectors written 501b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This is the total number of sectors written successfully. 502b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 8 -- # of milliseconds spent writing 503b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This is the total number of milliseconds spent by all writes (as 504b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// measured from __make_request() to end_that_request_last()). 505b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 9 -- # of I/Os currently in progress 506b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The only field that should go to zero. Incremented as requests are 507b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// given to appropriate struct request_queue and decremented as they 508b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// finish. 509b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 10 -- # of milliseconds spent doing I/Os 510b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This field increases so long as field 9 is nonzero. 511b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Field 11 -- weighted # of milliseconds spent doing I/Os 512b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This field is incremented at each I/O start, I/O completion, I/O 513b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// merge, or read of these stats by the number of I/Os in progress 514b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// (field 9) times the number of milliseconds spent doing I/O since the 515b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// last update of this field. This can provide an easy measure of both 516b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// I/O completion time and the backlog that may be accumulating. 517b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 518b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskDriveName = 2; 519b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskReads = 3; 520b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskReadsMerged = 4; 521b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskSectorsRead = 5; 522b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskReadTime = 6; 523b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskWrites = 7; 524b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskWritesMerged = 8; 525b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskSectorsWritten = 9; 526b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskWriteTime = 10; 527b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskIO = 11; 528b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskIOTime = 12; 529b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst size_t kDiskWeightedIOTime = 13; 530b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 531b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 532b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 533b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratSystemMemoryInfoKB::SystemMemoryInfoKB() { 534b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat total = 0; 535b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat free = 0; 536b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat buffers = 0; 537b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat cached = 0; 538b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat active_anon = 0; 539b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inactive_anon = 0; 540b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat active_file = 0; 541b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inactive_file = 0; 542b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_total = 0; 543b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_free = 0; 544b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dirty = 0; 545b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 546b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat pswpin = 0; 547b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat pswpout = 0; 548b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat pgmajfault = 0; 549b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 550b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifdef OS_CHROMEOS 551b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat shmem = 0; 552b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat slab = 0; 553b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat gem_objects = -1; 554b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat gem_size = -1; 555b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 556b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 557b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 558b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratscoped_ptr<Value> SystemMemoryInfoKB::ToValue() const { 559b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<DictionaryValue> res(new DictionaryValue()); 560b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 561b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("total", total); 562b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("free", free); 563b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("buffers", buffers); 564b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("cached", cached); 565b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("active_anon", active_anon); 566b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("inactive_anon", inactive_anon); 567b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("active_file", active_file); 568b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("inactive_file", inactive_file); 569b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("swap_total", swap_total); 570b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("swap_free", swap_free); 571b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("swap_used", swap_total - swap_free); 572b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("dirty", dirty); 573b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("pswpin", pswpin); 574b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("pswpout", pswpout); 575b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("pgmajfault", pgmajfault); 576b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifdef OS_CHROMEOS 577b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("shmem", shmem); 578b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("slab", slab); 579b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("gem_objects", gem_objects); 580b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetInteger("gem_size", gem_size); 581b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 582b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 583cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return std::move(res); 584b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 585b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 586b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// exposed for testing 587b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ParseProcMeminfo(const std::string& meminfo_data, 588b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SystemMemoryInfoKB* meminfo) { 589b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The format of /proc/meminfo is: 590b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 591b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // MemTotal: 8235324 kB 592b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // MemFree: 1628304 kB 593b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Buffers: 429596 kB 594b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Cached: 4728232 kB 595b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ... 596b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // There is no guarantee on the ordering or position 597b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // though it doesn't appear to change very often 598b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 599b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // As a basic sanity check, let's make sure we at least get non-zero 600b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // MemTotal value 601b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat meminfo->total = 0; 602b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 603cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (const StringPiece& line : SplitStringPiece( 604cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko meminfo_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) { 605cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<StringPiece> tokens = SplitStringPiece( 606cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko line, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); 607b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // HugePages_* only has a number and no suffix so we can't rely on 608b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // there being exactly 3 tokens. 609b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (tokens.size() <= 1) { 610b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "meminfo: tokens: " << tokens.size() 611cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko << " malformed line: " << line.as_string(); 612b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat continue; 613b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 614b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 615b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int* target = NULL; 616b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (tokens[0] == "MemTotal:") 617b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->total; 618b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "MemFree:") 619b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->free; 620b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Buffers:") 621b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->buffers; 622b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Cached:") 623b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->cached; 624b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Active(anon):") 625b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->active_anon; 626b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Inactive(anon):") 627b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->inactive_anon; 628b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Active(file):") 629b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->active_file; 630b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Inactive(file):") 631b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->inactive_file; 632b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "SwapTotal:") 633b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->swap_total; 634b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "SwapFree:") 635b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->swap_free; 636b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Dirty:") 637b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->dirty; 638b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 639b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Chrome OS has a tweaked kernel that allows us to query Shmem, which is 640b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // usually video memory otherwise invisible to the OS. 641b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Shmem:") 642b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->shmem; 643b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else if (tokens[0] == "Slab:") 644b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target = &meminfo->slab; 645b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 646b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (target) 647b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToInt(tokens[1], target); 648b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 649b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 650b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Make sure we got a valid MemTotal. 651b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return meminfo->total > 0; 652b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 653b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 654b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// exposed for testing 655b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ParseProcVmstat(const std::string& vmstat_data, 656b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SystemMemoryInfoKB* meminfo) { 657b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The format of /proc/vmstat is: 658b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 659b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // nr_free_pages 299878 660b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // nr_inactive_anon 239863 661b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // nr_active_anon 1318966 662b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // nr_inactive_file 2015629 663b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ... 664b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 665b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We iterate through the whole file because the position of the 666b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // fields are dependent on the kernel version and configuration. 667b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 668cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (const StringPiece& line : SplitStringPiece( 669cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko vmstat_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) { 670cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<StringPiece> tokens = SplitStringPiece( 671cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko line, " ", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); 672b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (tokens.size() != 2) 673b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat continue; 674b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 675b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (tokens[0] == "pswpin") { 676b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToInt(tokens[1], &meminfo->pswpin); 677b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else if (tokens[0] == "pswpout") { 678b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToInt(tokens[1], &meminfo->pswpout); 679b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else if (tokens[0] == "pgmajfault") { 680b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToInt(tokens[1], &meminfo->pgmajfault); 681b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 682b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 683b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 684b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 685b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 686b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 687b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { 688b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc and /sys are safe. 689b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 690b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 691b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Used memory is: total - free - buffers - caches 692b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath meminfo_file("/proc/meminfo"); 693b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string meminfo_data; 694b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(meminfo_file, &meminfo_data)) { 695b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "Failed to open " << meminfo_file.value(); 696b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 697b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 698b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 699b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ParseProcMeminfo(meminfo_data, meminfo)) { 700b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "Failed to parse " << meminfo_file.value(); 701b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 702b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 703b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 704b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 705b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Report on Chrome OS GEM object graphics memory. /run/debugfs_gpu is a 706b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // bind mount into /sys/kernel/debug and synchronously reading the in-memory 707b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // files in /sys is fast. 708b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(ARCH_CPU_ARM_FAMILY) 709b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath geminfo_file("/run/debugfs_gpu/exynos_gem_objects"); 710b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 711b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath geminfo_file("/run/debugfs_gpu/i915_gem_objects"); 712b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 713b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string geminfo_data; 714b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat meminfo->gem_objects = -1; 715b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat meminfo->gem_size = -1; 716b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (ReadFileToString(geminfo_file, &geminfo_data)) { 717b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int gem_objects = -1; 718b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat long long gem_size = -1; 719b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int num_res = sscanf(geminfo_data.c_str(), 720b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat "%d objects, %lld bytes", 721b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat &gem_objects, &gem_size); 722b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (num_res == 2) { 723b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat meminfo->gem_objects = gem_objects; 724b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat meminfo->gem_size = gem_size; 725b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 726b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 727b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 728b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(ARCH_CPU_ARM_FAMILY) 729b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Incorporate Mali graphics memory if present. 730b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath mali_memory_file("/sys/class/misc/mali0/device/memory"); 731b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string mali_memory_data; 732b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (ReadFileToString(mali_memory_file, &mali_memory_data)) { 733b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat long long mali_size = -1; 734b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int num_res = sscanf(mali_memory_data.c_str(), "%lld bytes", &mali_size); 735b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (num_res == 1) 736b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat meminfo->gem_size += mali_size; 737b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 738b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(ARCH_CPU_ARM_FAMILY) 739b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_CHROMEOS) 740b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 741b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath vmstat_file("/proc/vmstat"); 742b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string vmstat_data; 743b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(vmstat_file, &vmstat_data)) { 744b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "Failed to open " << vmstat_file.value(); 745b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 746b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 747b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ParseProcVmstat(vmstat_data, meminfo)) { 748b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "Failed to parse " << vmstat_file.value(); 749b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 750b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 751b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 752b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 753b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 754b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 755b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratSystemDiskInfo::SystemDiskInfo() { 756b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reads = 0; 757b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reads_merged = 0; 758b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat sectors_read = 0; 759b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat read_time = 0; 760b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat writes = 0; 761b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat writes_merged = 0; 762b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat sectors_written = 0; 763b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat write_time = 0; 764b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat io = 0; 765b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat io_time = 0; 766b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat weighted_io_time = 0; 767b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 768b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 769b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratscoped_ptr<Value> SystemDiskInfo::ToValue() const { 770b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<DictionaryValue> res(new DictionaryValue()); 771b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 772cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // Write out uint64_t variables as doubles. 773b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Note: this may discard some precision, but for JS there's no other option. 774b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("reads", static_cast<double>(reads)); 775b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("reads_merged", static_cast<double>(reads_merged)); 776b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("sectors_read", static_cast<double>(sectors_read)); 777b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("read_time", static_cast<double>(read_time)); 778b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("writes", static_cast<double>(writes)); 779b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("writes_merged", static_cast<double>(writes_merged)); 780b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("sectors_written", static_cast<double>(sectors_written)); 781b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("write_time", static_cast<double>(write_time)); 782b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("io", static_cast<double>(io)); 783b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("io_time", static_cast<double>(io_time)); 784b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("weighted_io_time", static_cast<double>(weighted_io_time)); 785b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 786cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return std::move(res); 787b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 788b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 789b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool IsValidDiskName(const std::string& candidate) { 790b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (candidate.length() < 3) 791b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 792b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (candidate[1] == 'd' && 793b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (candidate[0] == 'h' || candidate[0] == 's' || candidate[0] == 'v')) { 794b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // [hsv]d[a-z]+ case 795b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (size_t i = 2; i < candidate.length(); ++i) { 796b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!islower(candidate[i])) 797b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 798b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 799b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 800b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 801b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 802b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const char kMMCName[] = "mmcblk"; 803b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kMMCNameLen = strlen(kMMCName); 804b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (candidate.length() < kMMCNameLen + 1) 805b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 806b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (candidate.compare(0, kMMCNameLen, kMMCName) != 0) 807b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 808b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 809b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // mmcblk[0-9]+ case 810b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (size_t i = kMMCNameLen; i < candidate.length(); ++i) { 811b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!isdigit(candidate[i])) 812b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 813b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 814b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 815b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 816b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 817b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool GetSystemDiskInfo(SystemDiskInfo* diskinfo) { 818b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /proc does not hit the disk. 819b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 820b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 821b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath diskinfo_file("/proc/diskstats"); 822b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string diskinfo_data; 823b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!ReadFileToString(diskinfo_file, &diskinfo_data)) { 824b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "Failed to open " << diskinfo_file.value(); 825b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 826b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 827b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 828cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<StringPiece> diskinfo_lines = SplitStringPiece( 829cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko diskinfo_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); 830cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (diskinfo_lines.size() == 0) { 831b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(WARNING) << "No lines found"; 832b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 833b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 834b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 835b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->reads = 0; 836b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->reads_merged = 0; 837b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->sectors_read = 0; 838b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->read_time = 0; 839b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->writes = 0; 840b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->writes_merged = 0; 841b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->sectors_written = 0; 842b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->write_time = 0; 843b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->io = 0; 844b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->io_time = 0; 845b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->weighted_io_time = 0; 846b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 847cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t reads = 0; 848cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t reads_merged = 0; 849cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t sectors_read = 0; 850cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t read_time = 0; 851cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t writes = 0; 852cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t writes_merged = 0; 853cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t sectors_written = 0; 854cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t write_time = 0; 855cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t io = 0; 856cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t io_time = 0; 857cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t weighted_io_time = 0; 858cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 859cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (const StringPiece& line : diskinfo_lines) { 860cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<StringPiece> disk_fields = SplitStringPiece( 861cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko line, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); 862b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 863b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Fields may have overflowed and reset to zero. 864cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (IsValidDiskName(disk_fields[kDiskDriveName].as_string())) { 865b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskReads], &reads); 866b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskReadsMerged], &reads_merged); 867b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskSectorsRead], §ors_read); 868b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskReadTime], &read_time); 869b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskWrites], &writes); 870b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskWritesMerged], &writes_merged); 871b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskSectorsWritten], §ors_written); 872b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskWriteTime], &write_time); 873b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskIO], &io); 874b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskIOTime], &io_time); 875b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringToUint64(disk_fields[kDiskWeightedIOTime], &weighted_io_time); 876b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 877b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->reads += reads; 878b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->reads_merged += reads_merged; 879b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->sectors_read += sectors_read; 880b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->read_time += read_time; 881b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->writes += writes; 882b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->writes_merged += writes_merged; 883b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->sectors_written += sectors_written; 884b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->write_time += write_time; 885b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->io += io; 886b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->io_time += io_time; 887b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat diskinfo->weighted_io_time += weighted_io_time; 888b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 889b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 890b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 891b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 892b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 893b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 894b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 895b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratscoped_ptr<Value> SwapInfo::ToValue() const { 896b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<DictionaryValue> res(new DictionaryValue()); 897b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 898cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // Write out uint64_t variables as doubles. 899b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Note: this may discard some precision, but for JS there's no other option. 900b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("num_reads", static_cast<double>(num_reads)); 901b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("num_writes", static_cast<double>(num_writes)); 902b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("orig_data_size", static_cast<double>(orig_data_size)); 903b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("compr_data_size", static_cast<double>(compr_data_size)); 904b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("mem_used_total", static_cast<double>(mem_used_total)); 905b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (compr_data_size > 0) 906b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("compression_ratio", static_cast<double>(orig_data_size) / 907b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static_cast<double>(compr_data_size)); 908b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else 909b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat res->SetDouble("compression_ratio", 0); 910b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 911cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return std::move(res); 912b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 913b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 914b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid GetSwapInfo(SwapInfo* swap_info) { 915b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Synchronously reading files in /sys/block/zram0 does not hit the disk. 916b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadRestrictions::ScopedAllowIO allow_io; 917b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 918b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FilePath zram_path("/sys/block/zram0"); 919cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t orig_data_size = 920cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko ReadFileToUint64(zram_path.Append("orig_data_size")); 921b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (orig_data_size <= 4096) { 922b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // A single page is compressed at startup, and has a high compression 923b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ratio. We ignore this as it doesn't indicate any real swapping. 924b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->orig_data_size = 0; 925b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->num_reads = 0; 926b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->num_writes = 0; 927b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->compr_data_size = 0; 928b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->mem_used_total = 0; 929b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 930b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 931b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->orig_data_size = orig_data_size; 932b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->num_reads = ReadFileToUint64(zram_path.Append("num_reads")); 933b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->num_writes = ReadFileToUint64(zram_path.Append("num_writes")); 934b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->compr_data_size = 935b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ReadFileToUint64(zram_path.Append("compr_data_size")); 936b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat swap_info->mem_used_total = 937b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ReadFileToUint64(zram_path.Append("mem_used_total")); 938b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 939b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_CHROMEOS) 940b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 941b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_LINUX) 942b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint ProcessMetrics::GetIdleWakeupsPerSecond() { 943cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko uint64_t wake_ups; 944b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const char kWakeupStat[] = "se.statistics.nr_wakeups"; 945b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ReadProcSchedAndGetFieldAsUint64(process_, kWakeupStat, &wake_ups) ? 946b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CalculateIdleWakeupsPerSecond(wake_ups) : 0; 947b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 948b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_LINUX) 949b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 950b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 951