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