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