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