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 24 namespace base { 25 26 #if defined(OS_WIN) 27 struct IoCounters : public IO_COUNTERS { 28 }; 29 #elif defined(OS_POSIX) 30 struct 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 // 65 struct WorkingSetKBytes { WorkingSetKBytesWorkingSetKBytes66 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) 81 struct CommittedKBytes { CommittedKBytesCommittedKBytes82 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. 93 struct FreeMBytes { 94 size_t total; 95 size_t largest; 96 void* largest_ptr; 97 }; 98 99 // Convert a POSIX timeval to microseconds. 100 BASE_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. 106 class 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: ~PortProvider()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. 224 BASE_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. 229 size_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. 236 BASE_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. 242 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process); 243 244 // /proc/self/exe refers to the current executable. 245 BASE_EXPORT extern const char kProcSelfExe[]; 246 247 // Data from /proc/meminfo about system-wide memory consumption. 248 // Values are in KB. 249 struct 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 283 BASE_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 288 BASE_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. 295 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo); 296 297 // Data from /proc/diskstats about system-wide disk I/O. 298 struct 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. 320 BASE_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. 324 BASE_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. 329 struct BASE_EXPORT SwapInfo { SwapInfoSwapInfo330 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. 350 BASE_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. 356 class 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