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#if defined(OS_MACOSX) || defined(OS_LINUX)
197  int CalculateIdleWakeupsPerSecond(uint64 absolute_idle_wakeups);
198#endif
199
200  ProcessHandle process_;
201
202  int processor_count_;
203
204  // Used to store the previous times and CPU usage counts so we can
205  // compute the CPU usage between calls.
206  TimeTicks last_cpu_time_;
207  int64 last_system_time_;
208
209#if defined(OS_MACOSX) || defined(OS_LINUX)
210  // Same thing for idle wakeups.
211  TimeTicks last_idle_wakeups_time_;
212  uint64 last_absolute_idle_wakeups_;
213#endif
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.
232BASE_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.
237size_t GetMaxFds();
238
239// Sets the file descriptor soft limit to |max_descriptors| or the OS hard
240// limit, whichever is lower.
241BASE_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.
248BASE_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.
254BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
255
256// /proc/self/exe refers to the current executable.
257BASE_EXPORT extern const char kProcSelfExe[];
258
259// Data from /proc/meminfo about system-wide memory consumption.
260// Values are in KB.
261struct 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
295BASE_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
300BASE_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.
307BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
308
309// Data from /proc/diskstats about system-wide disk I/O.
310struct 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, [hsv]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.
332BASE_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.
336BASE_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.
341struct BASE_EXPORT SwapInfo {
342  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.
362BASE_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.
368class 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