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. Do not use this to compute 240 // the number of pages in a block of memory for calling mincore(). On some 241 // platforms, e.g. iOS, mincore() uses a different page size from what is 242 // returned by GetPageSize(). 243 BASE_EXPORT size_t GetPageSize(); 244 245 #if defined(OS_POSIX) 246 // Returns the maximum number of file descriptors that can be open by a process 247 // at once. If the number is unavailable, a conservative best guess is returned. 248 BASE_EXPORT size_t GetMaxFds(); 249 250 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard 251 // limit, whichever is lower. 252 BASE_EXPORT void SetFdLimit(unsigned int max_descriptors); 253 #endif // defined(OS_POSIX) 254 255 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ 256 defined(OS_ANDROID) 257 // Data about system-wide memory consumption. Values are in KB. Available on 258 // Windows, Mac, Linux, Android and Chrome OS. 259 // 260 // Total/free memory are available on all platforms that implement 261 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms 262 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/ 263 // inactive_file/dirty/pswpin/pswpout/pgmajfault are available on 264 // Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only. 265 struct BASE_EXPORT SystemMemoryInfoKB { 266 SystemMemoryInfoKB(); 267 SystemMemoryInfoKB(const SystemMemoryInfoKB& other); 268 269 // Serializes the platform specific fields to value. 270 std::unique_ptr<Value> ToValue() const; 271 272 int total; 273 int free; 274 275 #if defined(OS_LINUX) 276 // This provides an estimate of available memory as described here: 277 // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 278 // NOTE: this is ONLY valid in kernels 3.14 and up. Its value will always 279 // be 0 in earlier kernel versions. 280 int available; 281 #endif 282 283 #if !defined(OS_MACOSX) 284 int swap_total; 285 int swap_free; 286 #endif 287 288 #if defined(OS_ANDROID) || defined(OS_LINUX) 289 int buffers; 290 int cached; 291 int active_anon; 292 int inactive_anon; 293 int active_file; 294 int inactive_file; 295 int dirty; 296 297 // vmstats data. 298 int pswpin; 299 int pswpout; 300 int pgmajfault; 301 #endif // defined(OS_ANDROID) || defined(OS_LINUX) 302 303 #if defined(OS_CHROMEOS) 304 int shmem; 305 int slab; 306 // Gem data will be -1 if not supported. 307 int gem_objects; 308 long long gem_size; 309 #endif // defined(OS_CHROMEOS) 310 }; 311 312 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed 313 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using 314 // system API calls. 315 // 316 // Fills in the provided |meminfo| structure. Returns true on success. 317 // Exposed for memory debugging widget. 318 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo); 319 320 #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || 321 // defined(OS_ANDROID) 322 323 #if defined(OS_LINUX) || defined(OS_ANDROID) 324 // Parse the data found in /proc/<pid>/stat and return the sum of the 325 // CPU-related ticks. Returns -1 on parse error. 326 // Exposed for testing. 327 BASE_EXPORT int ParseProcStatCPU(const std::string& input); 328 329 // Get the number of threads of |process| as available in /proc/<pid>/stat. 330 // This should be used with care as no synchronization with running threads is 331 // done. This is mostly useful to guarantee being single-threaded. 332 // Returns 0 on failure. 333 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process); 334 335 // /proc/self/exe refers to the current executable. 336 BASE_EXPORT extern const char kProcSelfExe[]; 337 338 // Parses a string containing the contents of /proc/meminfo 339 // returns true on success or false for a parsing error 340 BASE_EXPORT bool ParseProcMeminfo(const std::string& input, 341 SystemMemoryInfoKB* meminfo); 342 343 // Parses a string containing the contents of /proc/vmstat 344 // returns true on success or false for a parsing error 345 BASE_EXPORT bool ParseProcVmstat(const std::string& input, 346 SystemMemoryInfoKB* meminfo); 347 348 // Data from /proc/diskstats about system-wide disk I/O. 349 struct BASE_EXPORT SystemDiskInfo { 350 SystemDiskInfo(); 351 SystemDiskInfo(const SystemDiskInfo& other); 352 353 // Serializes the platform specific fields to value. 354 std::unique_ptr<Value> ToValue() const; 355 356 uint64_t reads; 357 uint64_t reads_merged; 358 uint64_t sectors_read; 359 uint64_t read_time; 360 uint64_t writes; 361 uint64_t writes_merged; 362 uint64_t sectors_written; 363 uint64_t write_time; 364 uint64_t io; 365 uint64_t io_time; 366 uint64_t weighted_io_time; 367 }; 368 369 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+ 370 // for a generic disk or mmcblk[0-9]+ for the MMC case. 371 // Names of disk partitions (e.g. sda1) are not valid. 372 BASE_EXPORT bool IsValidDiskName(const std::string& candidate); 373 374 // Retrieves data from /proc/diskstats about system-wide disk I/O. 375 // Fills in the provided |diskinfo| structure. Returns true on success. 376 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo); 377 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 378 379 #if defined(OS_CHROMEOS) 380 // Data from files in directory /sys/block/zram0 about ZRAM usage. 381 struct BASE_EXPORT SwapInfo { SwapInfoSwapInfo382 SwapInfo() 383 : num_reads(0), 384 num_writes(0), 385 compr_data_size(0), 386 orig_data_size(0), 387 mem_used_total(0) { 388 } 389 390 // Serializes the platform specific fields to value. 391 std::unique_ptr<Value> ToValue() const; 392 393 uint64_t num_reads; 394 uint64_t num_writes; 395 uint64_t compr_data_size; 396 uint64_t orig_data_size; 397 uint64_t mem_used_total; 398 }; 399 400 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data. 401 // Fills in the provided |swap_data| structure. 402 BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info); 403 #endif // defined(OS_CHROMEOS) 404 405 // Collects and holds performance metrics for system memory and disk. 406 // Provides functionality to retrieve the data on various platforms and 407 // to serialize the stored data. 408 class SystemMetrics { 409 public: 410 SystemMetrics(); 411 412 static SystemMetrics Sample(); 413 414 // Serializes the system metrics to value. 415 std::unique_ptr<Value> ToValue() const; 416 417 private: 418 FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics); 419 420 size_t committed_memory_; 421 #if defined(OS_LINUX) || defined(OS_ANDROID) 422 SystemMemoryInfoKB memory_info_; 423 SystemDiskInfo disk_info_; 424 #endif 425 #if defined(OS_CHROMEOS) 426 SwapInfo swap_info_; 427 #endif 428 }; 429 430 } // namespace base 431 432 #endif // BASE_PROCESS_PROCESS_METRICS_H_ 433