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