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 // Returns the number of average idle cpu wakeups per second since the last 172 // call. 173 int GetIdleWakeupsPerSecond(); 174 175 // Same as GetCPUUsage(), but will return consistent values on all platforms 176 // (cancelling the Windows exception mentioned above) by returning a value in 177 // the range of 0 to (100 * numCPUCores) everywhere. 178 double GetPlatformIndependentCPUUsage(); 179 180 // Retrieves accounting information for all I/O operations performed by the 181 // process. 182 // If IO information is retrieved successfully, the function returns true 183 // and fills in the IO_COUNTERS passed in. The function returns false 184 // otherwise. 185 bool GetIOCounters(IoCounters* io_counters) const; 186 187 private: 188 #if !defined(OS_MACOSX) || defined(OS_IOS) 189 explicit ProcessMetrics(ProcessHandle process); 190 #else 191 ProcessMetrics(ProcessHandle process, PortProvider* port_provider); 192 #endif // !defined(OS_MACOSX) || defined(OS_IOS) 193 194 #if defined(OS_LINUX) || defined(OS_ANDROID) 195 bool GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) const; 196 #endif 197 198 #if defined(OS_CHROMEOS) 199 bool GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) const; 200 #endif 201 202 ProcessHandle process_; 203 204 int processor_count_; 205 206 // Used to store the previous times and CPU usage counts so we can 207 // compute the CPU usage between calls. 208 TimeTicks last_cpu_time_; 209 int64 last_system_time_; 210 211 // Same thing for idle wakeups. 212 TimeTicks last_idle_wakeups_time_; 213 int64 last_absolute_idle_wakeups_; 214 215 #if !defined(OS_IOS) 216 #if defined(OS_MACOSX) 217 // Queries the port provider if it's set. 218 mach_port_t TaskForPid(ProcessHandle process) const; 219 220 PortProvider* port_provider_; 221 #elif defined(OS_POSIX) 222 // Jiffie count at the last_cpu_time_ we updated. 223 int last_cpu_; 224 #endif // defined(OS_POSIX) 225 #endif // !defined(OS_IOS) 226 227 DISALLOW_COPY_AND_ASSIGN(ProcessMetrics); 228 }; 229 230 // Returns the memory committed by the system in KBytes. 231 // Returns 0 if it can't compute the commit charge. 232 BASE_EXPORT size_t GetSystemCommitCharge(); 233 234 #if defined(OS_POSIX) 235 // Returns the maximum number of file descriptors that can be open by a process 236 // at once. If the number is unavailable, a conservative best guess is returned. 237 size_t GetMaxFds(); 238 239 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard 240 // limit, whichever is lower. 241 BASE_EXPORT void SetFdLimit(unsigned int max_descriptors); 242 #endif // defined(OS_POSIX) 243 244 #if defined(OS_LINUX) || defined(OS_ANDROID) 245 // Parse the data found in /proc/<pid>/stat and return the sum of the 246 // CPU-related ticks. Returns -1 on parse error. 247 // Exposed for testing. 248 BASE_EXPORT int ParseProcStatCPU(const std::string& input); 249 250 // Get the number of threads of |process| as available in /proc/<pid>/stat. 251 // This should be used with care as no synchronization with running threads is 252 // done. This is mostly useful to guarantee being single-threaded. 253 // Returns 0 on failure. 254 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process); 255 256 // /proc/self/exe refers to the current executable. 257 BASE_EXPORT extern const char kProcSelfExe[]; 258 259 // Data from /proc/meminfo about system-wide memory consumption. 260 // Values are in KB. 261 struct BASE_EXPORT SystemMemoryInfoKB { 262 SystemMemoryInfoKB(); 263 264 // Serializes the platform specific fields to value. 265 scoped_ptr<Value> ToValue() const; 266 267 int total; 268 int free; 269 int buffers; 270 int cached; 271 int active_anon; 272 int inactive_anon; 273 int active_file; 274 int inactive_file; 275 int swap_total; 276 int swap_free; 277 int dirty; 278 279 // vmstats data. 280 int pswpin; 281 int pswpout; 282 int pgmajfault; 283 284 #ifdef OS_CHROMEOS 285 int shmem; 286 int slab; 287 // Gem data will be -1 if not supported. 288 int gem_objects; 289 long long gem_size; 290 #endif 291 }; 292 293 // Parses a string containing the contents of /proc/meminfo 294 // returns true on success or false for a parsing error 295 BASE_EXPORT bool ParseProcMeminfo(const std::string& input, 296 SystemMemoryInfoKB* meminfo); 297 298 // Parses a string containing the contents of /proc/vmstat 299 // returns true on success or false for a parsing error 300 BASE_EXPORT bool ParseProcVmstat(const std::string& input, 301 SystemMemoryInfoKB* meminfo); 302 303 // Retrieves data from /proc/meminfo and /proc/vmstat 304 // about system-wide memory consumption. 305 // Fills in the provided |meminfo| structure. Returns true on success. 306 // Exposed for memory debugging widget. 307 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo); 308 309 // Data from /proc/diskstats about system-wide disk I/O. 310 struct BASE_EXPORT SystemDiskInfo { 311 SystemDiskInfo(); 312 313 // Serializes the platform specific fields to value. 314 scoped_ptr<Value> ToValue() const; 315 316 uint64 reads; 317 uint64 reads_merged; 318 uint64 sectors_read; 319 uint64 read_time; 320 uint64 writes; 321 uint64 writes_merged; 322 uint64 sectors_written; 323 uint64 write_time; 324 uint64 io; 325 uint64 io_time; 326 uint64 weighted_io_time; 327 }; 328 329 // Checks whether the candidate string is a valid disk name, [sh]d[a-z]+ 330 // for a generic disk or mmcblk[0-9]+ for the MMC case. 331 // Names of disk partitions (e.g. sda1) are not valid. 332 BASE_EXPORT bool IsValidDiskName(const std::string& candidate); 333 334 // Retrieves data from /proc/diskstats about system-wide disk I/O. 335 // Fills in the provided |diskinfo| structure. Returns true on success. 336 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo); 337 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 338 339 #if defined(OS_CHROMEOS) 340 // Data from files in directory /sys/block/zram0 about ZRAM usage. 341 struct BASE_EXPORT SwapInfo { SwapInfoSwapInfo342 SwapInfo() 343 : num_reads(0), 344 num_writes(0), 345 compr_data_size(0), 346 orig_data_size(0), 347 mem_used_total(0) { 348 } 349 350 // Serializes the platform specific fields to value. 351 scoped_ptr<Value> ToValue() const; 352 353 uint64 num_reads; 354 uint64 num_writes; 355 uint64 compr_data_size; 356 uint64 orig_data_size; 357 uint64 mem_used_total; 358 }; 359 360 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data. 361 // Fills in the provided |swap_data| structure. 362 BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info); 363 #endif // defined(OS_CHROMEOS) 364 365 // Collects and holds performance metrics for system memory and disk. 366 // Provides functionality to retrieve the data on various platforms and 367 // to serialize the stored data. 368 class SystemMetrics { 369 public: 370 SystemMetrics(); 371 372 static SystemMetrics Sample(); 373 374 // Serializes the system metrics to value. 375 scoped_ptr<Value> ToValue() const; 376 377 private: 378 FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics); 379 380 size_t committed_memory_; 381 #if defined(OS_LINUX) || defined(OS_ANDROID) 382 SystemMemoryInfoKB memory_info_; 383 SystemDiskInfo disk_info_; 384 #endif 385 #if defined(OS_CHROMEOS) 386 SwapInfo swap_info_; 387 #endif 388 }; 389 390 } // namespace base 391 392 #endif // BASE_PROCESS_PROCESS_METRICS_H_ 393