• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stddef.h>
12 #include <stdint.h>
13 
14 #include <string>
15 
16 #include "base/base_export.h"
17 #include "base/gtest_prod_util.h"
18 #include "base/macros.h"
19 #include "base/process/process_handle.h"
20 #include "base/time/time.h"
21 #include "base/values.h"
22 #include "build/build_config.h"
23 
24 #if defined(OS_MACOSX)
25 #include <mach/mach.h>
26 #include "base/process/port_provider_mac.h"
27 #endif
28 
29 namespace base {
30 
31 #if defined(OS_WIN)
32 struct IoCounters : public IO_COUNTERS {
33 };
34 #elif defined(OS_POSIX)
35 struct IoCounters {
36   uint64_t ReadOperationCount;
37   uint64_t WriteOperationCount;
38   uint64_t OtherOperationCount;
39   uint64_t ReadTransferCount;
40   uint64_t WriteTransferCount;
41   uint64_t OtherTransferCount;
42 };
43 #endif
44 
45 // Working Set (resident) memory usage broken down by
46 //
47 // On Windows:
48 // priv (private): These pages (kbytes) cannot be shared with any other process.
49 // shareable:      These pages (kbytes) can be shared with other processes under
50 //                 the right circumstances.
51 // shared :        These pages (kbytes) are currently shared with at least one
52 //                 other process.
53 //
54 // On Linux:
55 // priv:           Pages mapped only by this process.
56 // shared:         PSS or 0 if the kernel doesn't support this.
57 // shareable:      0
58 
59 // On ChromeOS:
60 // priv:           Pages mapped only by this process.
61 // shared:         PSS or 0 if the kernel doesn't support this.
62 // shareable:      0
63 // swapped         Pages swapped out to zram.
64 //
65 // On OS X: TODO(thakis): Revise.
66 // priv:           Memory.
67 // shared:         0
68 // shareable:      0
69 //
70 struct WorkingSetKBytes {
WorkingSetKBytesWorkingSetKBytes71   WorkingSetKBytes() : priv(0), shareable(0), shared(0) {}
72   size_t priv;
73   size_t shareable;
74   size_t shared;
75 #if defined(OS_CHROMEOS)
76   size_t swapped;
77 #endif
78 };
79 
80 // Committed (resident + paged) memory usage broken down by
81 // private: These pages cannot be shared with any other process.
82 // mapped:  These pages are mapped into the view of a section (backed by
83 //          pagefile.sys)
84 // image:   These pages are mapped into the view of an image section (backed by
85 //          file system)
86 struct CommittedKBytes {
CommittedKBytesCommittedKBytes87   CommittedKBytes() : priv(0), mapped(0), image(0) {}
88   size_t priv;
89   size_t mapped;
90   size_t image;
91 };
92 
93 // Convert a POSIX timeval to microseconds.
94 BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv);
95 
96 // Provides performance metrics for a specified process (CPU usage, memory and
97 // IO counters). Use CreateCurrentProcessMetrics() to get an instance for the
98 // current process, or CreateProcessMetrics() to get an instance for an
99 // arbitrary process. Then, access the information with the different get
100 // methods.
101 class BASE_EXPORT ProcessMetrics {
102  public:
103   ~ProcessMetrics();
104 
105   // Creates a ProcessMetrics for the specified process.
106   // The caller owns the returned object.
107 #if !defined(OS_MACOSX) || defined(OS_IOS)
108   static ProcessMetrics* CreateProcessMetrics(ProcessHandle process);
109 #else
110 
111   // The port provider needs to outlive the ProcessMetrics object returned by
112   // this function. If NULL is passed as provider, the returned object
113   // only returns valid metrics if |process| is the current process.
114   static ProcessMetrics* CreateProcessMetrics(ProcessHandle process,
115                                               PortProvider* port_provider);
116 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
117 
118   // Creates a ProcessMetrics for the current process. This a cross-platform
119   // convenience wrapper for CreateProcessMetrics().
120   // The caller owns the returned object.
121   static ProcessMetrics* CreateCurrentProcessMetrics();
122 
123   // Returns the current space allocated for the pagefile, in bytes (these pages
124   // may or may not be in memory).  On Linux, this returns the total virtual
125   // memory size.
126   size_t GetPagefileUsage() const;
127   // Returns the peak space allocated for the pagefile, in bytes.
128   size_t GetPeakPagefileUsage() const;
129   // Returns the current working set size, in bytes.  On Linux, this returns
130   // the resident set size.
131   size_t GetWorkingSetSize() const;
132   // Returns the peak working set size, in bytes.
133   size_t GetPeakWorkingSetSize() const;
134   // Returns private and sharedusage, in bytes. Private bytes is the amount of
135   // memory currently allocated to a process that cannot be shared. Returns
136   // false on platform specific error conditions.  Note: |private_bytes|
137   // returns 0 on unsupported OSes: prior to XP SP2.
138   bool GetMemoryBytes(size_t* private_bytes,
139                       size_t* shared_bytes);
140   // Fills a CommittedKBytes with both resident and paged
141   // memory usage as per definition of CommittedBytes.
142   void GetCommittedKBytes(CommittedKBytes* usage) const;
143   // Fills a WorkingSetKBytes containing resident private and shared memory
144   // usage in bytes, as per definition of WorkingSetBytes. Note that this
145   // function is somewhat expensive on Windows (a few ms per process).
146   bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const;
147 
148 #if defined(OS_MACOSX)
149   // Fills both CommitedKBytes and WorkingSetKBytes in a single operation. This
150   // is more efficient on Mac OS X, as the two can be retrieved with a single
151   // system call.
152   bool GetCommittedAndWorkingSetKBytes(CommittedKBytes* usage,
153                                        WorkingSetKBytes* ws_usage) const;
154 #endif
155 
156   // Returns the CPU usage in percent since the last time this method or
157   // GetPlatformIndependentCPUUsage() was called. The first time this method
158   // is called it returns 0 and will return the actual CPU info on subsequent
159   // calls. On Windows, the CPU usage value is for all CPUs. So if you have
160   // 2 CPUs and your process is using all the cycles of 1 CPU and not the other
161   // CPU, this method returns 50.
162   double GetCPUUsage();
163 
164   // Returns the number of average idle cpu wakeups per second since the last
165   // call.
166   int GetIdleWakeupsPerSecond();
167 
168   // Same as GetCPUUsage(), but will return consistent values on all platforms
169   // (cancelling the Windows exception mentioned above) by returning a value in
170   // the range of 0 to (100 * numCPUCores) everywhere.
171   double GetPlatformIndependentCPUUsage();
172 
173   // Retrieves accounting information for all I/O operations performed by the
174   // process.
175   // If IO information is retrieved successfully, the function returns true
176   // and fills in the IO_COUNTERS passed in. The function returns false
177   // otherwise.
178   bool GetIOCounters(IoCounters* io_counters) const;
179 
180 #if defined(OS_LINUX)
181   // Returns the number of file descriptors currently open by the process, or
182   // -1 on error.
183   int GetOpenFdCount() const;
184 #endif  // defined(OS_LINUX)
185 
186  private:
187 #if !defined(OS_MACOSX) || defined(OS_IOS)
188   explicit ProcessMetrics(ProcessHandle process);
189 #else
190   ProcessMetrics(ProcessHandle process, PortProvider* port_provider);
191 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
192 
193 #if defined(OS_LINUX) || defined(OS_ANDROID)
194   bool GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) const;
195 #endif
196 
197 #if defined(OS_CHROMEOS)
198   bool GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) const;
199 #endif
200 
201 #if defined(OS_MACOSX) || defined(OS_LINUX)
202   int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups);
203 #endif
204 
205   ProcessHandle process_;
206 
207   int processor_count_;
208 
209   // Used to store the previous times and CPU usage counts so we can
210   // compute the CPU usage between calls.
211   TimeTicks last_cpu_time_;
212   int64_t last_system_time_;
213 
214 #if defined(OS_MACOSX) || defined(OS_LINUX)
215   // Same thing for idle wakeups.
216   TimeTicks last_idle_wakeups_time_;
217   uint64_t last_absolute_idle_wakeups_;
218 #endif
219 
220 #if !defined(OS_IOS)
221 #if defined(OS_MACOSX)
222   // Queries the port provider if it's set.
223   mach_port_t TaskForPid(ProcessHandle process) const;
224 
225   PortProvider* port_provider_;
226 #elif defined(OS_POSIX)
227   // Jiffie count at the last_cpu_time_ we updated.
228   int last_cpu_;
229 #endif  // defined(OS_POSIX)
230 #endif  // !defined(OS_IOS)
231 
232   DISALLOW_COPY_AND_ASSIGN(ProcessMetrics);
233 };
234 
235 // Returns the memory committed by the system in KBytes.
236 // Returns 0 if it can't compute the commit charge.
237 BASE_EXPORT size_t GetSystemCommitCharge();
238 
239 // Returns the number of bytes in a memory page.
240 BASE_EXPORT size_t GetPageSize();
241 
242 #if defined(OS_POSIX)
243 // Returns the maximum number of file descriptors that can be open by a process
244 // at once. If the number is unavailable, a conservative best guess is returned.
245 BASE_EXPORT size_t GetMaxFds();
246 
247 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
248 // limit, whichever is lower.
249 BASE_EXPORT void SetFdLimit(unsigned int max_descriptors);
250 #endif  // defined(OS_POSIX)
251 
252 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
253     defined(OS_ANDROID)
254 // Data about system-wide memory consumption. Values are in KB. Available on
255 // Windows, Mac, Linux, Android and Chrome OS.
256 //
257 // Total/free memory are available on all platforms that implement
258 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms
259 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/
260 // inactive_file/dirty/pswpin/pswpout/pgmajfault are available on
261 // Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only.
262 struct BASE_EXPORT SystemMemoryInfoKB {
263   SystemMemoryInfoKB();
264 
265   // Serializes the platform specific fields to value.
266   scoped_ptr<Value> ToValue() const;
267 
268   int total;
269   int free;
270 
271 #if !defined(OS_MACOSX)
272   int swap_total;
273   int swap_free;
274 #endif
275 
276 #if defined(OS_ANDROID) || defined(OS_LINUX)
277   int buffers;
278   int cached;
279   int active_anon;
280   int inactive_anon;
281   int active_file;
282   int inactive_file;
283   int dirty;
284 
285   // vmstats data.
286   int pswpin;
287   int pswpout;
288   int pgmajfault;
289 #endif  // defined(OS_ANDROID) || defined(OS_LINUX)
290 
291 #if defined(OS_CHROMEOS)
292   int shmem;
293   int slab;
294   // Gem data will be -1 if not supported.
295   int gem_objects;
296   long long gem_size;
297 #endif  // defined(OS_CHROMEOS)
298 };
299 
300 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed
301 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using
302 // system API calls.
303 //
304 // Fills in the provided |meminfo| structure. Returns true on success.
305 // Exposed for memory debugging widget.
306 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
307 
308 #endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) ||
309         // defined(OS_ANDROID)
310 
311 #if defined(OS_LINUX) || defined(OS_ANDROID)
312 // Parse the data found in /proc/<pid>/stat and return the sum of the
313 // CPU-related ticks.  Returns -1 on parse error.
314 // Exposed for testing.
315 BASE_EXPORT int ParseProcStatCPU(const std::string& input);
316 
317 // Get the number of threads of |process| as available in /proc/<pid>/stat.
318 // This should be used with care as no synchronization with running threads is
319 // done. This is mostly useful to guarantee being single-threaded.
320 // Returns 0 on failure.
321 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
322 
323 // /proc/self/exe refers to the current executable.
324 BASE_EXPORT extern const char kProcSelfExe[];
325 
326 // Parses a string containing the contents of /proc/meminfo
327 // returns true on success or false for a parsing error
328 BASE_EXPORT bool ParseProcMeminfo(const std::string& input,
329                                   SystemMemoryInfoKB* meminfo);
330 
331 // Parses a string containing the contents of /proc/vmstat
332 // returns true on success or false for a parsing error
333 BASE_EXPORT bool ParseProcVmstat(const std::string& input,
334                                  SystemMemoryInfoKB* meminfo);
335 
336 // Data from /proc/diskstats about system-wide disk I/O.
337 struct BASE_EXPORT SystemDiskInfo {
338   SystemDiskInfo();
339 
340   // Serializes the platform specific fields to value.
341   scoped_ptr<Value> ToValue() const;
342 
343   uint64_t reads;
344   uint64_t reads_merged;
345   uint64_t sectors_read;
346   uint64_t read_time;
347   uint64_t writes;
348   uint64_t writes_merged;
349   uint64_t sectors_written;
350   uint64_t write_time;
351   uint64_t io;
352   uint64_t io_time;
353   uint64_t weighted_io_time;
354 };
355 
356 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+
357 // for a generic disk or mmcblk[0-9]+ for the MMC case.
358 // Names of disk partitions (e.g. sda1) are not valid.
359 BASE_EXPORT bool IsValidDiskName(const std::string& candidate);
360 
361 // Retrieves data from /proc/diskstats about system-wide disk I/O.
362 // Fills in the provided |diskinfo| structure. Returns true on success.
363 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo);
364 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
365 
366 #if defined(OS_CHROMEOS)
367 // Data from files in directory /sys/block/zram0 about ZRAM usage.
368 struct BASE_EXPORT SwapInfo {
SwapInfoSwapInfo369   SwapInfo()
370       : num_reads(0),
371         num_writes(0),
372         compr_data_size(0),
373         orig_data_size(0),
374         mem_used_total(0) {
375   }
376 
377   // Serializes the platform specific fields to value.
378   scoped_ptr<Value> ToValue() const;
379 
380   uint64_t num_reads;
381   uint64_t num_writes;
382   uint64_t compr_data_size;
383   uint64_t orig_data_size;
384   uint64_t mem_used_total;
385 };
386 
387 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data.
388 // Fills in the provided |swap_data| structure.
389 BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info);
390 #endif  // defined(OS_CHROMEOS)
391 
392 // Collects and holds performance metrics for system memory and disk.
393 // Provides functionality to retrieve the data on various platforms and
394 // to serialize the stored data.
395 class SystemMetrics {
396  public:
397   SystemMetrics();
398 
399   static SystemMetrics Sample();
400 
401   // Serializes the system metrics to value.
402   scoped_ptr<Value> ToValue() const;
403 
404  private:
405   FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics);
406 
407   size_t committed_memory_;
408 #if defined(OS_LINUX) || defined(OS_ANDROID)
409   SystemMemoryInfoKB memory_info_;
410   SystemDiskInfo disk_info_;
411 #endif
412 #if defined(OS_CHROMEOS)
413   SwapInfo swap_info_;
414 #endif
415 };
416 
417 }  // namespace base
418 
419 #endif  // BASE_PROCESS_PROCESS_METRICS_H_
420