process_metrics.h revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// This file contains routines for gathering resource statistics for processes 6// running on the system. 7 8#ifndef BASE_PROCESS_PROCESS_METRICS_H_ 9#define BASE_PROCESS_PROCESS_METRICS_H_ 10 11#include <string> 12 13#include "base/base_export.h" 14#include "base/basictypes.h" 15#include "base/gtest_prod_util.h" 16#include "base/process/process_handle.h" 17#include "base/time/time.h" 18#include "base/values.h" 19 20#if defined(OS_MACOSX) 21#include <mach/mach.h> 22#endif 23 24namespace base { 25 26#if defined(OS_WIN) 27struct IoCounters : public IO_COUNTERS { 28}; 29#elif defined(OS_POSIX) 30struct IoCounters { 31 uint64_t ReadOperationCount; 32 uint64_t WriteOperationCount; 33 uint64_t OtherOperationCount; 34 uint64_t ReadTransferCount; 35 uint64_t WriteTransferCount; 36 uint64_t OtherTransferCount; 37}; 38#endif 39 40// Working Set (resident) memory usage broken down by 41// 42// On Windows: 43// priv (private): These pages (kbytes) cannot be shared with any other process. 44// shareable: These pages (kbytes) can be shared with other processes under 45// the right circumstances. 46// shared : These pages (kbytes) are currently shared with at least one 47// other process. 48// 49// On Linux: 50// priv: Pages mapped only by this process. 51// shared: PSS or 0 if the kernel doesn't support this. 52// shareable: 0 53 54// On ChromeOS: 55// priv: Pages mapped only by this process. 56// shared: PSS or 0 if the kernel doesn't support this. 57// shareable: 0 58// swapped Pages swapped out to zram. 59// 60// On OS X: TODO(thakis): Revise. 61// priv: Memory. 62// shared: 0 63// shareable: 0 64// 65struct WorkingSetKBytes { 66 WorkingSetKBytes() : priv(0), shareable(0), shared(0) {} 67 size_t priv; 68 size_t shareable; 69 size_t shared; 70#if defined(OS_CHROMEOS) 71 size_t swapped; 72#endif 73}; 74 75// Committed (resident + paged) memory usage broken down by 76// private: These pages cannot be shared with any other process. 77// mapped: These pages are mapped into the view of a section (backed by 78// pagefile.sys) 79// image: These pages are mapped into the view of an image section (backed by 80// file system) 81struct CommittedKBytes { 82 CommittedKBytes() : priv(0), mapped(0), image(0) {} 83 size_t priv; 84 size_t mapped; 85 size_t image; 86}; 87 88// Free memory (Megabytes marked as free) in the 2G process address space. 89// total : total amount in megabytes marked as free. Maximum value is 2048. 90// largest : size of the largest contiguous amount of memory found. It is 91// always smaller or equal to FreeMBytes::total. 92// largest_ptr: starting address of the largest memory block. 93struct FreeMBytes { 94 size_t total; 95 size_t largest; 96 void* largest_ptr; 97}; 98 99// Convert a POSIX timeval to microseconds. 100BASE_EXPORT int64 TimeValToMicroseconds(const struct timeval& tv); 101 102// Provides performance metrics for a specified process (CPU usage, memory and 103// IO counters). To use it, invoke CreateProcessMetrics() to get an instance 104// for a specific process, then access the information with the different get 105// methods. 106class BASE_EXPORT ProcessMetrics { 107 public: 108 ~ProcessMetrics(); 109 110 // Creates a ProcessMetrics for the specified process. 111 // The caller owns the returned object. 112#if !defined(OS_MACOSX) || defined(OS_IOS) 113 static ProcessMetrics* CreateProcessMetrics(ProcessHandle process); 114#else 115 class PortProvider { 116 public: 117 virtual ~PortProvider() {} 118 119 // Should return the mach task for |process| if possible, or else 120 // |MACH_PORT_NULL|. Only processes that this returns tasks for will have 121 // metrics on OS X (except for the current process, which always gets 122 // metrics). 123 virtual mach_port_t TaskForPid(ProcessHandle process) const = 0; 124 }; 125 126 // The port provider needs to outlive the ProcessMetrics object returned by 127 // this function. If NULL is passed as provider, the returned object 128 // only returns valid metrics if |process| is the current process. 129 static ProcessMetrics* CreateProcessMetrics(ProcessHandle process, 130 PortProvider* port_provider); 131#endif // !defined(OS_MACOSX) || defined(OS_IOS) 132 133 // Returns the current space allocated for the pagefile, in bytes (these pages 134 // may or may not be in memory). On Linux, this returns the total virtual 135 // memory size. 136 size_t GetPagefileUsage() const; 137 // Returns the peak space allocated for the pagefile, in bytes. 138 size_t GetPeakPagefileUsage() const; 139 // Returns the current working set size, in bytes. On Linux, this returns 140 // the resident set size. 141 size_t GetWorkingSetSize() const; 142 // Returns the peak working set size, in bytes. 143 size_t GetPeakWorkingSetSize() const; 144 // Returns private and sharedusage, in bytes. Private bytes is the amount of 145 // memory currently allocated to a process that cannot be shared. Returns 146 // false on platform specific error conditions. Note: |private_bytes| 147 // returns 0 on unsupported OSes: prior to XP SP2. 148 bool GetMemoryBytes(size_t* private_bytes, 149 size_t* shared_bytes); 150 // Fills a CommittedKBytes with both resident and paged 151 // memory usage as per definition of CommittedBytes. 152 void GetCommittedKBytes(CommittedKBytes* usage) const; 153 // Fills a WorkingSetKBytes containing resident private and shared memory 154 // usage in bytes, as per definition of WorkingSetBytes. 155 bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const; 156 157 // Computes the current process available memory for allocation. 158 // It does a linear scan of the address space querying each memory region 159 // for its free (unallocated) status. It is useful for estimating the memory 160 // load and fragmentation. 161 bool CalculateFreeMemory(FreeMBytes* free) const; 162 163 // Returns the CPU usage in percent since the last time this method or 164 // GetPlatformIndependentCPUUsage() was called. The first time this method 165 // is called it returns 0 and will return the actual CPU info on subsequent 166 // calls. On Windows, the CPU usage value is for all CPUs. So if you have 167 // 2 CPUs and your process is using all the cycles of 1 CPU and not the other 168 // CPU, this method returns 50. 169 double GetCPUUsage(); 170 171 // Same as GetCPUUsage(), but will return consistent values on all platforms 172 // (cancelling the Windows exception mentioned above) by returning a value in 173 // the range of 0 to (100 * numCPUCores) everywhere. 174 double GetPlatformIndependentCPUUsage(); 175 176 // Retrieves accounting information for all I/O operations performed by the 177 // process. 178 // If IO information is retrieved successfully, the function returns true 179 // and fills in the IO_COUNTERS passed in. The function returns false 180 // otherwise. 181 bool GetIOCounters(IoCounters* io_counters) const; 182 183 private: 184#if !defined(OS_MACOSX) || defined(OS_IOS) 185 explicit ProcessMetrics(ProcessHandle process); 186#else 187 ProcessMetrics(ProcessHandle process, PortProvider* port_provider); 188#endif // !defined(OS_MACOSX) || defined(OS_IOS) 189 190#if defined(OS_LINUX) || defined(OS_ANDROID) 191 bool GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) const; 192#endif 193 194#if defined(OS_CHROMEOS) 195 bool GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) const; 196#endif 197 198 ProcessHandle process_; 199 200 int processor_count_; 201 202 // Used to store the previous times and CPU usage counts so we can 203 // compute the CPU usage between calls. 204 int64 last_time_; 205 int64 last_system_time_; 206 207#if !defined(OS_IOS) 208#if defined(OS_MACOSX) 209 // Queries the port provider if it's set. 210 mach_port_t TaskForPid(ProcessHandle process) const; 211 212 PortProvider* port_provider_; 213#elif defined(OS_POSIX) 214 // Jiffie count at the last_time_ we updated. 215 int last_cpu_; 216#endif // defined(OS_POSIX) 217#endif // !defined(OS_IOS) 218 219 DISALLOW_COPY_AND_ASSIGN(ProcessMetrics); 220}; 221 222// Returns the memory committed by the system in KBytes. 223// Returns 0 if it can't compute the commit charge. 224BASE_EXPORT size_t GetSystemCommitCharge(); 225 226#if defined(OS_POSIX) 227// Returns the maximum number of file descriptors that can be open by a process 228// at once. If the number is unavailable, a conservative best guess is returned. 229size_t GetMaxFds(); 230#endif // defined(OS_POSIX) 231 232#if defined(OS_LINUX) || defined(OS_ANDROID) 233// Parse the data found in /proc/<pid>/stat and return the sum of the 234// CPU-related ticks. Returns -1 on parse error. 235// Exposed for testing. 236BASE_EXPORT int ParseProcStatCPU(const std::string& input); 237 238// Get the number of threads of |process| as available in /proc/<pid>/stat. 239// This should be used with care as no synchronization with running threads is 240// done. This is mostly useful to guarantee being single-threaded. 241// Returns 0 on failure. 242BASE_EXPORT int GetNumberOfThreads(ProcessHandle process); 243 244// /proc/self/exe refers to the current executable. 245BASE_EXPORT extern const char kProcSelfExe[]; 246 247// Data from /proc/meminfo about system-wide memory consumption. 248// Values are in KB. 249struct BASE_EXPORT SystemMemoryInfoKB { 250 SystemMemoryInfoKB(); 251 252 // Serializes the platform specific fields to value. 253 scoped_ptr<Value> ToValue() const; 254 255 int total; 256 int free; 257 int buffers; 258 int cached; 259 int active_anon; 260 int inactive_anon; 261 int active_file; 262 int inactive_file; 263 int swap_total; 264 int swap_free; 265 int dirty; 266 267 // vmstats data. 268 int pswpin; 269 int pswpout; 270 int pgmajfault; 271 272#ifdef OS_CHROMEOS 273 int shmem; 274 int slab; 275 // Gem data will be -1 if not supported. 276 int gem_objects; 277 long long gem_size; 278#endif 279}; 280 281// Parses a string containing the contents of /proc/meminfo 282// returns true on success or false for a parsing error 283BASE_EXPORT bool ParseProcMeminfo(const std::string& input, 284 SystemMemoryInfoKB* meminfo); 285 286// Parses a string containing the contents of /proc/vmstat 287// returns true on success or false for a parsing error 288BASE_EXPORT bool ParseProcVmstat(const std::string& input, 289 SystemMemoryInfoKB* meminfo); 290 291// Retrieves data from /proc/meminfo and /proc/vmstat 292// about system-wide memory consumption. 293// Fills in the provided |meminfo| structure. Returns true on success. 294// Exposed for memory debugging widget. 295BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo); 296 297// Data from /proc/diskstats about system-wide disk I/O. 298struct BASE_EXPORT SystemDiskInfo { 299 SystemDiskInfo(); 300 301 // Serializes the platform specific fields to value. 302 scoped_ptr<Value> ToValue() const; 303 304 uint64 reads; 305 uint64 reads_merged; 306 uint64 sectors_read; 307 uint64 read_time; 308 uint64 writes; 309 uint64 writes_merged; 310 uint64 sectors_written; 311 uint64 write_time; 312 uint64 io; 313 uint64 io_time; 314 uint64 weighted_io_time; 315}; 316 317// Checks whether the candidate string is a valid disk name, [sh]d[a-z]+ 318// for a generic disk or mmcblk[0-9]+ for the MMC case. 319// Names of disk partitions (e.g. sda1) are not valid. 320BASE_EXPORT bool IsValidDiskName(const std::string& candidate); 321 322// Retrieves data from /proc/diskstats about system-wide disk I/O. 323// Fills in the provided |diskinfo| structure. Returns true on success. 324BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo); 325#endif // defined(OS_LINUX) || defined(OS_ANDROID) 326 327#if defined(OS_CHROMEOS) 328// Data from files in directory /sys/block/zram0 about ZRAM usage. 329struct BASE_EXPORT SwapInfo { 330 SwapInfo() 331 : num_reads(0), 332 num_writes(0), 333 compr_data_size(0), 334 orig_data_size(0), 335 mem_used_total(0) { 336 } 337 338 // Serializes the platform specific fields to value. 339 scoped_ptr<Value> ToValue() const; 340 341 uint64 num_reads; 342 uint64 num_writes; 343 uint64 compr_data_size; 344 uint64 orig_data_size; 345 uint64 mem_used_total; 346}; 347 348// In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data. 349// Fills in the provided |swap_data| structure. 350BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info); 351#endif // defined(OS_CHROMEOS) 352 353// Collects and holds performance metrics for system memory and disk. 354// Provides functionality to retrieve the data on various platforms and 355// to serialize the stored data. 356class SystemMetrics { 357 public: 358 SystemMetrics(); 359 360 static SystemMetrics Sample(); 361 362 // Serializes the system metrics to value. 363 scoped_ptr<Value> ToValue() const; 364 365 private: 366 FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics); 367 368 size_t committed_memory_; 369#if defined(OS_LINUX) || defined(OS_ANDROID) 370 SystemMemoryInfoKB memory_info_; 371 SystemDiskInfo disk_info_; 372#endif 373#if defined(OS_CHROMEOS) 374 SwapInfo swap_info_; 375#endif 376}; 377 378} // namespace base 379 380#endif // BASE_PROCESS_PROCESS_METRICS_H_ 381