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 29 #if !defined(OS_IOS) 30 #include <mach/mach_vm.h> 31 #endif 32 #endif 33 34 #if defined(OS_WIN) 35 #include "base/win/scoped_handle.h" 36 #include "base/win/windows_types.h" 37 #endif 38 39 namespace base { 40 41 // Full declaration is in process_metrics_iocounters.h. 42 struct IoCounters; 43 44 #if defined(OS_LINUX) || defined(OS_ANDROID) 45 // Minor and major page fault counts since the process creation. 46 // Both counts are process-wide, and exclude child processes. 47 // 48 // minor: Number of page faults that didn't require disk IO. 49 // major: Number of page faults that required disk IO. 50 struct PageFaultCounts { 51 int64_t minor; 52 int64_t major; 53 }; 54 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 55 56 // Convert a POSIX timeval to microseconds. 57 BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv); 58 59 // Provides performance metrics for a specified process (CPU usage and IO 60 // counters). Use CreateCurrentProcessMetrics() to get an instance for the 61 // current process, or CreateProcessMetrics() to get an instance for an 62 // arbitrary process. Then, access the information with the different get 63 // methods. 64 // 65 // This class exposes a few platform-specific APIs for parsing memory usage, but 66 // these are not intended to generalize to other platforms, since the memory 67 // models differ substantially. 68 // 69 // To obtain consistent memory metrics, use the memory_instrumentation service. 70 // 71 // For further documentation on memory, see 72 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/README.md 73 class BASE_EXPORT ProcessMetrics { 74 public: 75 ~ProcessMetrics(); 76 77 // Creates a ProcessMetrics for the specified process. 78 #if !defined(OS_MACOSX) || defined(OS_IOS) 79 static std::unique_ptr<ProcessMetrics> CreateProcessMetrics( 80 ProcessHandle process); 81 #else 82 83 // The port provider needs to outlive the ProcessMetrics object returned by 84 // this function. If NULL is passed as provider, the returned object 85 // only returns valid metrics if |process| is the current process. 86 static std::unique_ptr<ProcessMetrics> CreateProcessMetrics( 87 ProcessHandle process, 88 PortProvider* port_provider); 89 #endif // !defined(OS_MACOSX) || defined(OS_IOS) 90 91 // Creates a ProcessMetrics for the current process. This a cross-platform 92 // convenience wrapper for CreateProcessMetrics(). 93 static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics(); 94 95 #if defined(OS_LINUX) || defined(OS_ANDROID) 96 // Resident Set Size is a Linux/Android specific memory concept. Do not 97 // attempt to extend this to other platforms. 98 BASE_EXPORT size_t GetResidentSetSize() const; 99 #endif 100 101 #if defined(OS_CHROMEOS) 102 // /proc/<pid>/totmaps is a syscall that returns memory summary statistics for 103 // the process. 104 // totmaps is a Linux specific concept, currently only being used on ChromeOS. 105 // Do not attempt to extend this to other platforms. 106 // 107 struct TotalsSummary { 108 size_t private_clean_kb; 109 size_t private_dirty_kb; 110 size_t swap_kb; 111 }; 112 BASE_EXPORT TotalsSummary GetTotalsSummary() const; 113 #endif 114 115 #if defined(OS_MACOSX) 116 struct TaskVMInfo { 117 // Only available on macOS 10.12+. 118 // Anonymous, non-discardable memory, including non-volatile IOKit. 119 // Measured in bytes. 120 uint64_t phys_footprint = 0; 121 122 // Anonymous, non-discardable, non-compressed memory, excluding IOKit. 123 // Measured in bytes. 124 uint64_t internal = 0; 125 126 // Compressed memory measured in bytes. 127 uint64_t compressed = 0; 128 }; 129 TaskVMInfo GetTaskVMInfo() const; 130 #endif 131 132 // Returns the percentage of time spent executing, across all threads of the 133 // process, in the interval since the last time the method was called. Since 134 // this considers the total execution time across all threads in a process, 135 // the result can easily exceed 100% in multi-thread processes running on 136 // multi-core systems. In general the result is therefore a value in the 137 // range 0% to SysInfo::NumberOfProcessors() * 100%. 138 // 139 // To obtain the percentage of total available CPU resources consumed by this 140 // process over the interval, the caller must divide by NumberOfProcessors(). 141 // 142 // Since this API measures usage over an interval, it will return zero on the 143 // first call, and an actual value only on the second and subsequent calls. 144 double GetPlatformIndependentCPUUsage(); 145 146 // Returns the cumulative CPU usage across all threads of the process since 147 // process start. In case of multi-core processors, a process can consume CPU 148 // at a rate higher than wall-clock time, e.g. two cores at full utilization 149 // will result in a time delta of 2 seconds/per 1 wall-clock second. 150 TimeDelta GetCumulativeCPUUsage(); 151 152 // Returns the number of average idle cpu wakeups per second since the last 153 // call. 154 int GetIdleWakeupsPerSecond(); 155 156 #if defined(OS_MACOSX) 157 // Returns the number of average "package idle exits" per second, which have 158 // a higher energy impact than a regular wakeup, since the last call. 159 // 160 // From the powermetrics man page: 161 // "With the exception of some Mac Pro systems, Mac and 162 // iOS systems are typically single package systems, wherein all CPUs are 163 // part of a single processor complex (typically a single IC die) with shared 164 // logic that can include (depending on system specifics) shared last level 165 // caches, an integrated memory controller etc. When all CPUs in the package 166 // are idle, the hardware can power-gate significant portions of the shared 167 // logic in addition to each individual processor's logic, as well as take 168 // measures such as placing DRAM in to self-refresh (also referred to as 169 // auto-refresh), place interconnects into lower-power states etc" 170 int GetPackageIdleWakeupsPerSecond(); 171 #endif 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) || defined(OS_AIX) || defined(OS_ANDROID) 181 // Returns the number of file descriptors currently open by the process, or 182 // -1 on error. 183 int GetOpenFdCount() const; 184 185 // Returns the soft limit of file descriptors that can be opened by the 186 // process, or -1 on error. 187 int GetOpenFdSoftLimit() const; 188 #endif // defined(OS_LINUX) || defined(OS_AIX) || defined(OS_ANDROID) 189 190 #if defined(OS_LINUX) || defined(OS_ANDROID) 191 // Bytes of swap as reported by /proc/[pid]/status. 192 uint64_t GetVmSwapBytes() const; 193 194 // Minor and major page fault count as reported by /proc/[pid]/stat. 195 // Returns true for success. 196 bool GetPageFaultCounts(PageFaultCounts* counts) const; 197 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 198 199 // Returns total memory usage of malloc. 200 size_t GetMallocUsage(); 201 202 private: 203 #if !defined(OS_MACOSX) || defined(OS_IOS) 204 explicit ProcessMetrics(ProcessHandle process); 205 #else 206 ProcessMetrics(ProcessHandle process, PortProvider* port_provider); 207 #endif // !defined(OS_MACOSX) || defined(OS_IOS) 208 209 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) 210 int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups); 211 #endif 212 #if defined(OS_MACOSX) 213 // The subset of wakeups that cause a "package exit" can be tracked on macOS. 214 // See |GetPackageIdleWakeupsForSecond| comment for more info. 215 int CalculatePackageIdleWakeupsPerSecond( 216 uint64_t absolute_package_idle_wakeups); 217 #endif 218 219 #if defined(OS_WIN) 220 win::ScopedHandle process_; 221 #else 222 ProcessHandle process_; 223 #endif 224 225 // Used to store the previous times and CPU usage counts so we can 226 // compute the CPU usage between calls. 227 TimeTicks last_cpu_time_; 228 #if !defined(OS_FREEBSD) || !defined(OS_POSIX) 229 TimeDelta last_cumulative_cpu_; 230 #endif 231 232 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) 233 // Same thing for idle wakeups. 234 TimeTicks last_idle_wakeups_time_; 235 uint64_t last_absolute_idle_wakeups_; 236 #endif 237 238 #if defined(OS_MACOSX) 239 // And same thing for package idle exit wakeups. 240 TimeTicks last_package_idle_wakeups_time_; 241 uint64_t last_absolute_package_idle_wakeups_; 242 #endif 243 244 #if !defined(OS_IOS) 245 #if defined(OS_MACOSX) 246 // Queries the port provider if it's set. 247 mach_port_t TaskForPid(ProcessHandle process) const; 248 249 PortProvider* port_provider_; 250 #endif // defined(OS_MACOSX) 251 #endif // !defined(OS_IOS) 252 253 DISALLOW_COPY_AND_ASSIGN(ProcessMetrics); 254 }; 255 256 // Returns the memory committed by the system in KBytes. 257 // Returns 0 if it can't compute the commit charge. 258 BASE_EXPORT size_t GetSystemCommitCharge(); 259 260 // Returns the number of bytes in a memory page. Do not use this to compute 261 // the number of pages in a block of memory for calling mincore(). On some 262 // platforms, e.g. iOS, mincore() uses a different page size from what is 263 // returned by GetPageSize(). 264 BASE_EXPORT size_t GetPageSize(); 265 266 // Returns the maximum number of file descriptors that can be open by a process 267 // at once. If the number is unavailable, a conservative best guess is returned. 268 BASE_EXPORT size_t GetMaxFds(); 269 270 #if defined(OS_POSIX) 271 // Increases the file descriptor soft limit to |max_descriptors| or the OS hard 272 // limit, whichever is lower. If the limit is already higher than 273 // |max_descriptors|, then nothing happens. 274 BASE_EXPORT void IncreaseFdLimitTo(unsigned int max_descriptors); 275 #endif // defined(OS_POSIX) 276 277 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ 278 defined(OS_ANDROID) || defined(OS_AIX) || defined(OS_FUCHSIA) 279 // Data about system-wide memory consumption. Values are in KB. Available on 280 // Windows, Mac, Linux, Android and Chrome OS. 281 // 282 // Total memory are available on all platforms that implement 283 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms 284 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/ 285 // inactive_file/dirty/reclaimable/pswpin/pswpout/pgmajfault are available on 286 // Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only. 287 // Speculative/file_backed/purgeable are Mac and iOS only. 288 // Free is absent on Windows (see "avail_phys" below). 289 struct BASE_EXPORT SystemMemoryInfoKB { 290 SystemMemoryInfoKB(); 291 SystemMemoryInfoKB(const SystemMemoryInfoKB& other); 292 293 // Serializes the platform specific fields to value. 294 std::unique_ptr<DictionaryValue> ToValue() const; 295 296 int total = 0; 297 298 #if !defined(OS_WIN) 299 int free = 0; 300 #endif 301 302 #if defined(OS_WIN) 303 // "This is the amount of physical memory that can be immediately reused 304 // without having to write its contents to disk first. It is the sum of the 305 // size of the standby, free, and zero lists." (MSDN). 306 // Standby: not modified pages of physical ram (file-backed memory) that are 307 // not actively being used. 308 int avail_phys = 0; 309 #endif 310 311 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX) 312 // This provides an estimate of available memory as described here: 313 // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 314 // NOTE: this is ONLY valid in kernels 3.14 and up. Its value will always 315 // be 0 in earlier kernel versions. 316 // Note: it includes _all_ file-backed memory (active + inactive). 317 int available = 0; 318 #endif 319 320 #if !defined(OS_MACOSX) 321 int swap_total = 0; 322 int swap_free = 0; 323 #endif 324 325 #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_AIX) || \ 326 defined(OS_FUCHSIA) 327 int buffers = 0; 328 int cached = 0; 329 int active_anon = 0; 330 int inactive_anon = 0; 331 int active_file = 0; 332 int inactive_file = 0; 333 int dirty = 0; 334 int reclaimable = 0; 335 #endif // defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_AIX) || 336 // defined(OS_FUCHSIA) 337 338 #if defined(OS_CHROMEOS) 339 int shmem = 0; 340 int slab = 0; 341 // Gem data will be -1 if not supported. 342 int gem_objects = -1; 343 long long gem_size = -1; 344 #endif // defined(OS_CHROMEOS) 345 346 #if defined(OS_MACOSX) 347 int speculative = 0; 348 int file_backed = 0; 349 int purgeable = 0; 350 #endif // defined(OS_MACOSX) 351 }; 352 353 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed 354 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using 355 // system API calls. 356 // 357 // Fills in the provided |meminfo| structure. Returns true on success. 358 // Exposed for memory debugging widget. 359 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo); 360 361 #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || 362 // defined(OS_ANDROID) || defined(OS_AIX) || defined(OS_FUCHSIA) 363 364 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX) 365 // Parse the data found in /proc/<pid>/stat and return the sum of the 366 // CPU-related ticks. Returns -1 on parse error. 367 // Exposed for testing. 368 BASE_EXPORT int ParseProcStatCPU(StringPiece input); 369 370 // Get the number of threads of |process| as available in /proc/<pid>/stat. 371 // This should be used with care as no synchronization with running threads is 372 // done. This is mostly useful to guarantee being single-threaded. 373 // Returns 0 on failure. 374 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process); 375 376 // /proc/self/exe refers to the current executable. 377 BASE_EXPORT extern const char kProcSelfExe[]; 378 379 // Parses a string containing the contents of /proc/meminfo 380 // returns true on success or false for a parsing error 381 // Exposed for testing. 382 BASE_EXPORT bool ParseProcMeminfo(StringPiece input, 383 SystemMemoryInfoKB* meminfo); 384 385 // Data from /proc/vmstat. 386 struct BASE_EXPORT VmStatInfo { 387 // Serializes the platform specific fields to value. 388 std::unique_ptr<DictionaryValue> ToValue() const; 389 390 unsigned long pswpin = 0; 391 unsigned long pswpout = 0; 392 unsigned long pgmajfault = 0; 393 }; 394 395 // Retrieves data from /proc/vmstat about system-wide vm operations. 396 // Fills in the provided |vmstat| structure. Returns true on success. 397 BASE_EXPORT bool GetVmStatInfo(VmStatInfo* vmstat); 398 399 // Parses a string containing the contents of /proc/vmstat 400 // returns true on success or false for a parsing error 401 // Exposed for testing. 402 BASE_EXPORT bool ParseProcVmstat(StringPiece input, VmStatInfo* vmstat); 403 404 // Data from /proc/diskstats about system-wide disk I/O. 405 struct BASE_EXPORT SystemDiskInfo { 406 SystemDiskInfo(); 407 SystemDiskInfo(const SystemDiskInfo& other); 408 409 // Serializes the platform specific fields to value. 410 std::unique_ptr<Value> ToValue() const; 411 412 uint64_t reads = 0; 413 uint64_t reads_merged = 0; 414 uint64_t sectors_read = 0; 415 uint64_t read_time = 0; 416 uint64_t writes = 0; 417 uint64_t writes_merged = 0; 418 uint64_t sectors_written = 0; 419 uint64_t write_time = 0; 420 uint64_t io = 0; 421 uint64_t io_time = 0; 422 uint64_t weighted_io_time = 0; 423 }; 424 425 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+ 426 // for a generic disk or mmcblk[0-9]+ for the MMC case. 427 // Names of disk partitions (e.g. sda1) are not valid. 428 BASE_EXPORT bool IsValidDiskName(StringPiece candidate); 429 430 // Retrieves data from /proc/diskstats about system-wide disk I/O. 431 // Fills in the provided |diskinfo| structure. Returns true on success. 432 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo); 433 434 // Returns the amount of time spent in user space since boot across all CPUs. 435 BASE_EXPORT TimeDelta GetUserCpuTimeSinceBoot(); 436 437 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 438 439 #if defined(OS_CHROMEOS) 440 // Data from files in directory /sys/block/zram0 about ZRAM usage. 441 struct BASE_EXPORT SwapInfo { SwapInfoSwapInfo442 SwapInfo() 443 : num_reads(0), 444 num_writes(0), 445 compr_data_size(0), 446 orig_data_size(0), 447 mem_used_total(0) { 448 } 449 450 // Serializes the platform specific fields to value. 451 std::unique_ptr<Value> ToValue() const; 452 453 uint64_t num_reads = 0; 454 uint64_t num_writes = 0; 455 uint64_t compr_data_size = 0; 456 uint64_t orig_data_size = 0; 457 uint64_t mem_used_total = 0; 458 }; 459 460 // Parses a string containing the contents of /sys/block/zram0/mm_stat. 461 // This should be used for the new ZRAM sysfs interfaces. 462 // Returns true on success or false for a parsing error. 463 // Exposed for testing. 464 BASE_EXPORT bool ParseZramMmStat(StringPiece mm_stat_data, SwapInfo* swap_info); 465 466 // Parses a string containing the contents of /sys/block/zram0/stat 467 // This should be used for the new ZRAM sysfs interfaces. 468 // Returns true on success or false for a parsing error. 469 // Exposed for testing. 470 BASE_EXPORT bool ParseZramStat(StringPiece stat_data, SwapInfo* swap_info); 471 472 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data. 473 // Fills in the provided |swap_data| structure. 474 // Returns true on success or false for a parsing error. 475 BASE_EXPORT bool GetSwapInfo(SwapInfo* swap_info); 476 #endif // defined(OS_CHROMEOS) 477 478 // Collects and holds performance metrics for system memory and disk. 479 // Provides functionality to retrieve the data on various platforms and 480 // to serialize the stored data. 481 class SystemMetrics { 482 public: 483 SystemMetrics(); 484 485 static SystemMetrics Sample(); 486 487 // Serializes the system metrics to value. 488 std::unique_ptr<Value> ToValue() const; 489 490 private: 491 FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics); 492 493 size_t committed_memory_; 494 #if defined(OS_LINUX) || defined(OS_ANDROID) 495 SystemMemoryInfoKB memory_info_; 496 VmStatInfo vmstat_info_; 497 SystemDiskInfo disk_info_; 498 #endif 499 #if defined(OS_CHROMEOS) 500 SwapInfo swap_info_; 501 #endif 502 }; 503 504 #if defined(OS_MACOSX) && !defined(OS_IOS) 505 enum class MachVMRegionResult { 506 // There were no more memory regions between |address| and the end of the 507 // virtual address space. 508 Finished, 509 510 // All output parameters are invalid. 511 Error, 512 513 // All output parameters are filled in. 514 Success 515 }; 516 517 // Returns info on the first memory region at or after |address|, including 518 // resident memory and share mode. On Success, |size| reflects the size of the 519 // memory region. 520 // |size| and |info| are output parameters, only valid on Success. 521 // |address| is an in-out parameter, than represents both the address to start 522 // looking, and the start address of the memory region. 523 BASE_EXPORT MachVMRegionResult GetTopInfo(mach_port_t task, 524 mach_vm_size_t* size, 525 mach_vm_address_t* address, 526 vm_region_top_info_data_t* info); 527 528 // Returns info on the first memory region at or after |address|, including 529 // protection values. On Success, |size| reflects the size of the 530 // memory region. 531 // Returns info on the first memory region at or after |address|, including 532 // resident memory and share mode. 533 // |size| and |info| are output parameters, only valid on Success. 534 BASE_EXPORT MachVMRegionResult GetBasicInfo(mach_port_t task, 535 mach_vm_size_t* size, 536 mach_vm_address_t* address, 537 vm_region_basic_info_64* info); 538 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 539 540 } // namespace base 541 542 #endif // BASE_PROCESS_PROCESS_METRICS_H_ 543