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