• 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. Do not use this to compute
240 // the number of pages in a block of memory for calling mincore(). On some
241 // platforms, e.g. iOS, mincore() uses a different page size from what is
242 // returned by GetPageSize().
243 BASE_EXPORT size_t GetPageSize();
244 
245 #if defined(OS_POSIX)
246 // Returns the maximum number of file descriptors that can be open by a process
247 // at once. If the number is unavailable, a conservative best guess is returned.
248 BASE_EXPORT size_t GetMaxFds();
249 
250 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
251 // limit, whichever is lower.
252 BASE_EXPORT void SetFdLimit(unsigned int max_descriptors);
253 #endif  // defined(OS_POSIX)
254 
255 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
256     defined(OS_ANDROID)
257 // Data about system-wide memory consumption. Values are in KB. Available on
258 // Windows, Mac, Linux, Android and Chrome OS.
259 //
260 // Total/free memory are available on all platforms that implement
261 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms
262 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/
263 // inactive_file/dirty/pswpin/pswpout/pgmajfault are available on
264 // Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only.
265 struct BASE_EXPORT SystemMemoryInfoKB {
266   SystemMemoryInfoKB();
267   SystemMemoryInfoKB(const SystemMemoryInfoKB& other);
268 
269   // Serializes the platform specific fields to value.
270   std::unique_ptr<Value> ToValue() const;
271 
272   int total;
273   int free;
274 
275 #if defined(OS_LINUX)
276   // This provides an estimate of available memory as described here:
277   // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
278   // NOTE: this is ONLY valid in kernels 3.14 and up.  Its value will always
279   // be 0 in earlier kernel versions.
280   int available;
281 #endif
282 
283 #if !defined(OS_MACOSX)
284   int swap_total;
285   int swap_free;
286 #endif
287 
288 #if defined(OS_ANDROID) || defined(OS_LINUX)
289   int buffers;
290   int cached;
291   int active_anon;
292   int inactive_anon;
293   int active_file;
294   int inactive_file;
295   int dirty;
296 
297   // vmstats data.
298   int pswpin;
299   int pswpout;
300   int pgmajfault;
301 #endif  // defined(OS_ANDROID) || defined(OS_LINUX)
302 
303 #if defined(OS_CHROMEOS)
304   int shmem;
305   int slab;
306   // Gem data will be -1 if not supported.
307   int gem_objects;
308   long long gem_size;
309 #endif  // defined(OS_CHROMEOS)
310 };
311 
312 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed
313 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using
314 // system API calls.
315 //
316 // Fills in the provided |meminfo| structure. Returns true on success.
317 // Exposed for memory debugging widget.
318 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
319 
320 #endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) ||
321         // defined(OS_ANDROID)
322 
323 #if defined(OS_LINUX) || defined(OS_ANDROID)
324 // Parse the data found in /proc/<pid>/stat and return the sum of the
325 // CPU-related ticks.  Returns -1 on parse error.
326 // Exposed for testing.
327 BASE_EXPORT int ParseProcStatCPU(const std::string& input);
328 
329 // Get the number of threads of |process| as available in /proc/<pid>/stat.
330 // This should be used with care as no synchronization with running threads is
331 // done. This is mostly useful to guarantee being single-threaded.
332 // Returns 0 on failure.
333 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
334 
335 // /proc/self/exe refers to the current executable.
336 BASE_EXPORT extern const char kProcSelfExe[];
337 
338 // Parses a string containing the contents of /proc/meminfo
339 // returns true on success or false for a parsing error
340 BASE_EXPORT bool ParseProcMeminfo(const std::string& input,
341                                   SystemMemoryInfoKB* meminfo);
342 
343 // Parses a string containing the contents of /proc/vmstat
344 // returns true on success or false for a parsing error
345 BASE_EXPORT bool ParseProcVmstat(const std::string& input,
346                                  SystemMemoryInfoKB* meminfo);
347 
348 // Data from /proc/diskstats about system-wide disk I/O.
349 struct BASE_EXPORT SystemDiskInfo {
350   SystemDiskInfo();
351   SystemDiskInfo(const SystemDiskInfo& other);
352 
353   // Serializes the platform specific fields to value.
354   std::unique_ptr<Value> ToValue() const;
355 
356   uint64_t reads;
357   uint64_t reads_merged;
358   uint64_t sectors_read;
359   uint64_t read_time;
360   uint64_t writes;
361   uint64_t writes_merged;
362   uint64_t sectors_written;
363   uint64_t write_time;
364   uint64_t io;
365   uint64_t io_time;
366   uint64_t weighted_io_time;
367 };
368 
369 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+
370 // for a generic disk or mmcblk[0-9]+ for the MMC case.
371 // Names of disk partitions (e.g. sda1) are not valid.
372 BASE_EXPORT bool IsValidDiskName(const std::string& candidate);
373 
374 // Retrieves data from /proc/diskstats about system-wide disk I/O.
375 // Fills in the provided |diskinfo| structure. Returns true on success.
376 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo);
377 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
378 
379 #if defined(OS_CHROMEOS)
380 // Data from files in directory /sys/block/zram0 about ZRAM usage.
381 struct BASE_EXPORT SwapInfo {
SwapInfoSwapInfo382   SwapInfo()
383       : num_reads(0),
384         num_writes(0),
385         compr_data_size(0),
386         orig_data_size(0),
387         mem_used_total(0) {
388   }
389 
390   // Serializes the platform specific fields to value.
391   std::unique_ptr<Value> ToValue() const;
392 
393   uint64_t num_reads;
394   uint64_t num_writes;
395   uint64_t compr_data_size;
396   uint64_t orig_data_size;
397   uint64_t mem_used_total;
398 };
399 
400 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data.
401 // Fills in the provided |swap_data| structure.
402 BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info);
403 #endif  // defined(OS_CHROMEOS)
404 
405 // Collects and holds performance metrics for system memory and disk.
406 // Provides functionality to retrieve the data on various platforms and
407 // to serialize the stored data.
408 class SystemMetrics {
409  public:
410   SystemMetrics();
411 
412   static SystemMetrics Sample();
413 
414   // Serializes the system metrics to value.
415   std::unique_ptr<Value> ToValue() const;
416 
417  private:
418   FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics);
419 
420   size_t committed_memory_;
421 #if defined(OS_LINUX) || defined(OS_ANDROID)
422   SystemMemoryInfoKB memory_info_;
423   SystemDiskInfo disk_info_;
424 #endif
425 #if defined(OS_CHROMEOS)
426   SwapInfo swap_info_;
427 #endif
428 };
429 
430 }  // namespace base
431 
432 #endif  // BASE_PROCESS_PROCESS_METRICS_H_
433