xref: /aosp_15_r20/external/cronet/base/process/process_metrics.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
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 <memory>
15 #include <string_view>
16 
17 #include "base/base_export.h"
18 #include "base/gtest_prod_util.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/process/process_handle.h"
21 #include "base/time/time.h"
22 #include "base/types/expected.h"
23 #include "base/values.h"
24 #include "build/build_config.h"
25 
26 #if BUILDFLAG(IS_APPLE)
27 #include <mach/mach.h>
28 #include "base/process/port_provider_mac.h"
29 
30 #if !BUILDFLAG(IS_IOS)
31 #include <mach/mach_vm.h>
32 #endif
33 #endif
34 
35 #if BUILDFLAG(IS_WIN)
36 #include "base/win/scoped_handle.h"
37 #include "base/win/windows_types.h"
38 #endif
39 
40 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
41     BUILDFLAG(IS_AIX)
42 #include <string>
43 #include <utility>
44 #include <vector>
45 
46 #include "base/threading/platform_thread.h"
47 #endif
48 
49 namespace base {
50 
51 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
52 // Minor and major page fault counts since the process creation.
53 // Both counts are process-wide, and exclude child processes.
54 //
55 // minor: Number of page faults that didn't require disk IO.
56 // major: Number of page faults that required disk IO.
57 struct PageFaultCounts {
58   int64_t minor;
59   int64_t major;
60 };
61 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
62         // BUILDFLAG(IS_ANDROID)
63 
64 // Convert a POSIX timeval to microseconds.
65 BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv);
66 
67 enum class ProcessCPUUsageError {
68   // The OS returned an error while measuring the CPU usage. The possible causes
69   // vary by platform.
70   kSystemError,
71 
72   // Process CPU usage couldn't be measured because the process wasn't running.
73   // Some platforms may return kSystemError instead in this situation.
74   kProcessNotFound,
75 
76   // CPU usage measurement isn't implemented on this platform.
77   kNotImplemented,
78 };
79 
80 // Provides performance metrics for a specified process (CPU usage and IO
81 // counters). Use CreateCurrentProcessMetrics() to get an instance for the
82 // current process, or CreateProcessMetrics() to get an instance for an
83 // arbitrary process. Then, access the information with the different get
84 // methods.
85 //
86 // This class exposes a few platform-specific APIs for parsing memory usage, but
87 // these are not intended to generalize to other platforms, since the memory
88 // models differ substantially.
89 //
90 // To obtain consistent memory metrics, use the memory_instrumentation service.
91 //
92 // For further documentation on memory, see
93 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/README.md#Memory
94 class BASE_EXPORT ProcessMetrics {
95  public:
96   ProcessMetrics(const ProcessMetrics&) = delete;
97   ProcessMetrics& operator=(const ProcessMetrics&) = delete;
98 
99   ~ProcessMetrics();
100 
101   // Creates a ProcessMetrics for the specified process.
102 #if !BUILDFLAG(IS_MAC)
103   static std::unique_ptr<ProcessMetrics> CreateProcessMetrics(
104       ProcessHandle process);
105 #else
106 
107   // The port provider needs to outlive the ProcessMetrics object returned by
108   // this function. If NULL is passed as provider, the returned object
109   // only returns valid metrics if |process| is the current process.
110   static std::unique_ptr<ProcessMetrics> CreateProcessMetrics(
111       ProcessHandle process,
112       PortProvider* port_provider);
113 #endif  // !BUILDFLAG(IS_MAC)
114 
115   // Creates a ProcessMetrics for the current process. This a cross-platform
116   // convenience wrapper for CreateProcessMetrics().
117   static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics();
118 
119 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
120   // Resident Set Size is a Linux/Android specific memory concept. Do not
121   // attempt to extend this to other platforms.
122   BASE_EXPORT size_t GetResidentSetSize() const;
123 #endif
124 
125   // Returns the percentage of time spent executing, across all threads of the
126   // process, in the interval since the last time the method was called, using
127   // the current |cumulative_cpu|. Since this considers the total execution time
128   // across all threads in a process, the result can easily exceed 100% in
129   // multi-thread processes running on multi-core systems. In general the result
130   // is therefore a value in the range 0% to
131   // SysInfo::NumberOfProcessors() * 100%.
132   //
133   // To obtain the percentage of total available CPU resources consumed by this
134   // process over the interval, the caller must divide by NumberOfProcessors().
135   //
136   // Since this API measures usage over an interval, it will return zero on the
137   // first call, and an actual value only on the second and subsequent calls.
138   [[nodiscard]] double GetPlatformIndependentCPUUsage(TimeDelta cumulative_cpu);
139 
140   // Same as the above, but automatically calls GetCumulativeCPUUsage() to
141   // determine the current cumulative CPU. Returns nullopt if
142   // GetCumulativeCPUUsage() fails.
143   base::expected<double, ProcessCPUUsageError> GetPlatformIndependentCPUUsage();
144 
145   // Returns the cumulative CPU usage across all threads of the process since
146   // process start, or nullopt on error. In case of multi-core processors, a
147   // process can consume CPU at a rate higher than wall-clock time, e.g. two
148   // cores at full utilization will result in a time delta of 2 seconds/per 1
149   // wall-clock second.
150   base::expected<TimeDelta, ProcessCPUUsageError> GetCumulativeCPUUsage();
151 
152 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
153     BUILDFLAG(IS_AIX)
154   // Emits the cumulative CPU usage for all currently active threads since they
155   // were started into the output parameter (replacing its current contents).
156   // Threads that have already terminated will not be reported. Thus, the sum of
157   // these times may not equal the value returned by GetCumulativeCPUUsage().
158   // Returns false on failure. We return the usage via an output parameter to
159   // allow reuse of CPUUsagePerThread's std::vector by the caller, e.g. to avoid
160   // allocations between repeated calls to this method.
161   // NOTE: Currently only supported on Linux/Android.
162   using CPUUsagePerThread = std::vector<std::pair<PlatformThreadId, TimeDelta>>;
163   bool GetCumulativeCPUUsagePerThread(CPUUsagePerThread&);
164 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
165         // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX)
166 
167   // Returns the number of average idle cpu wakeups per second since the last
168   // call.
169   int GetIdleWakeupsPerSecond();
170 
171 #if BUILDFLAG(IS_APPLE)
172   // Returns the number of average "package idle exits" per second, which have
173   // a higher energy impact than a regular wakeup, since the last call.
174   //
175   // From the powermetrics man page:
176   // "With the exception of some Mac Pro systems, Mac and
177   // iOS systems are typically single package systems, wherein all CPUs are
178   // part of a single processor complex (typically a single IC die) with shared
179   // logic that can include (depending on system specifics) shared last level
180   // caches, an integrated memory controller etc. When all CPUs in the package
181   // are idle, the hardware can power-gate significant portions of the shared
182   // logic in addition to each individual processor's logic, as well as take
183   // measures such as placing DRAM in to self-refresh (also referred to as
184   // auto-refresh), place interconnects into lower-power states etc"
185   int GetPackageIdleWakeupsPerSecond();
186 #endif
187 
188 #if BUILDFLAG(IS_POSIX)
189   // Returns the number of file descriptors currently open by the process, or
190   // -1 on error.
191   int GetOpenFdCount() const;
192 
193   // Returns the soft limit of file descriptors that can be opened by the
194   // process, or -1 on error.
195   int GetOpenFdSoftLimit() const;
196 #endif  // BUILDFLAG(IS_POSIX)
197 
198 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
199   // Bytes of swap as reported by /proc/[pid]/status.
200   uint64_t GetVmSwapBytes() const;
201 
202   // Minor and major page fault count as reported by /proc/[pid]/stat.
203   // Returns true for success.
204   bool GetPageFaultCounts(PageFaultCounts* counts) const;
205 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
206         // BUILDFLAG(IS_ANDROID)
207 
208   // Returns total memory usage of malloc.
209   size_t GetMallocUsage();
210 
211  private:
212 #if !BUILDFLAG(IS_MAC)
213   explicit ProcessMetrics(ProcessHandle process);
214 #else
215   ProcessMetrics(ProcessHandle process, PortProvider* port_provider);
216 #endif  // !BUILDFLAG(IS_MAC)
217 
218 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
219     BUILDFLAG(IS_AIX)
220   int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups);
221 #endif
222 #if BUILDFLAG(IS_APPLE)
223   // The subset of wakeups that cause a "package exit" can be tracked on macOS.
224   // See |GetPackageIdleWakeupsForSecond| comment for more info.
225   int CalculatePackageIdleWakeupsPerSecond(
226       uint64_t absolute_package_idle_wakeups);
227 
228   // Queries the port provider if it's set.
229   mach_port_t TaskForHandle(ProcessHandle process_handle) const;
230 #endif
231 
232 #if BUILDFLAG(IS_WIN)
233   win::ScopedHandle process_;
234 #else
235   ProcessHandle process_;
236 #endif
237 
238   // Used to store the previous times and CPU usage counts so we can
239   // compute the CPU usage between calls.
240   TimeTicks last_cpu_time_;
241 #if !BUILDFLAG(IS_FREEBSD) || !BUILDFLAG(IS_POSIX)
242   TimeDelta last_cumulative_cpu_;
243 #endif
244 
245 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
246     BUILDFLAG(IS_AIX)
247   // Same thing for idle wakeups.
248   TimeTicks last_idle_wakeups_time_;
249   uint64_t last_absolute_idle_wakeups_;
250 #endif
251 
252 #if BUILDFLAG(IS_APPLE)
253   // And same thing for package idle exit wakeups.
254   TimeTicks last_package_idle_wakeups_time_;
255   uint64_t last_absolute_package_idle_wakeups_;
256 
257   // Works around a race condition when combining two task_info() calls to
258   // measure CPU time.
259   TimeDelta last_measured_cpu_;
260 #endif
261 
262 #if BUILDFLAG(IS_MAC)
263   raw_ptr<PortProvider> port_provider_;
264 #endif  // BUILDFLAG(IS_MAC)
265 };
266 
267 // Returns the memory committed by the system in KBytes.
268 // Returns 0 if it can't compute the commit charge.
269 BASE_EXPORT size_t GetSystemCommitCharge();
270 
271 // Returns the maximum number of file descriptors that can be open by a process
272 // at once. If the number is unavailable, a conservative best guess is returned.
273 BASE_EXPORT size_t GetMaxFds();
274 
275 // Returns the maximum number of handles that can be open at once per process.
276 BASE_EXPORT size_t GetHandleLimit();
277 
278 #if BUILDFLAG(IS_POSIX)
279 // Increases the file descriptor soft limit to |max_descriptors| or the OS hard
280 // limit, whichever is lower. If the limit is already higher than
281 // |max_descriptors|, then nothing happens.
282 BASE_EXPORT void IncreaseFdLimitTo(unsigned int max_descriptors);
283 #endif  // BUILDFLAG(IS_POSIX)
284 
285 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) ||      \
286     BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX) || \
287     BUILDFLAG(IS_FUCHSIA)
288 // Data about system-wide memory consumption. Values are in KB. Available on
289 // Windows, Mac, Linux, Android and Chrome OS.
290 //
291 // Total memory are available on all platforms that implement
292 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms
293 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/
294 // inactive_file/dirty/reclaimable/pswpin/pswpout/pgmajfault are available on
295 // Linux/Android/Chrome OS. Shmem/slab are Chrome OS only.
296 // Speculative/file_backed/purgeable are Mac and iOS only.
297 // Free is absent on Windows (see "avail_phys" below).
298 struct BASE_EXPORT SystemMemoryInfoKB {
299   SystemMemoryInfoKB();
300   SystemMemoryInfoKB(const SystemMemoryInfoKB& other);
301   SystemMemoryInfoKB& operator=(const SystemMemoryInfoKB& other);
302 
303   // Serializes the platform specific fields to value.
304   Value::Dict ToDict() const;
305 
306   int total = 0;
307 
308 #if !BUILDFLAG(IS_WIN)
309   int free = 0;
310 #endif
311 
312 #if BUILDFLAG(IS_WIN)
313   // "This is the amount of physical memory that can be immediately reused
314   // without having to write its contents to disk first. It is the sum of the
315   // size of the standby, free, and zero lists." (MSDN).
316   // Standby: not modified pages of physical ram (file-backed memory) that are
317   // not actively being used.
318   int avail_phys = 0;
319 #endif
320 
321 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
322     BUILDFLAG(IS_AIX)
323   // This provides an estimate of available memory as described here:
324   // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
325   // NOTE: this is ONLY valid in kernels 3.14 and up.  Its value will always
326   // be 0 in earlier kernel versions.
327   // Note: it includes _all_ file-backed memory (active + inactive).
328   int available = 0;
329 #endif
330 
331 #if !BUILDFLAG(IS_APPLE)
332   int swap_total = 0;
333   int swap_free = 0;
334 #endif
335 
336 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
337     BUILDFLAG(IS_AIX) || BUILDFLAG(IS_FUCHSIA)
338   int buffers = 0;
339   int cached = 0;
340   int active_anon = 0;
341   int inactive_anon = 0;
342   int active_file = 0;
343   int inactive_file = 0;
344   int dirty = 0;
345   int reclaimable = 0;
346 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
347         // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX) BUILDFLAG(IS_FUCHSIA)
348 
349 #if BUILDFLAG(IS_CHROMEOS)
350   int shmem = 0;
351   int slab = 0;
352 #endif  // BUILDFLAG(IS_CHROMEOS)
353 
354 #if BUILDFLAG(IS_APPLE)
355   int speculative = 0;
356   int file_backed = 0;
357   int purgeable = 0;
358 #endif  // BUILDFLAG(IS_APPLE)
359 };
360 
361 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed
362 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using
363 // system API calls.
364 //
365 // Fills in the provided |meminfo| structure. Returns true on success.
366 // Exposed for memory debugging widget.
367 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
368 
369 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) ||
370         // BUILDFLAG(IS_CHROMEOS) BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX) ||
371         // BUILDFLAG(IS_FUCHSIA)
372 
373 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
374     BUILDFLAG(IS_AIX)
375 // Parse the data found in /proc/<pid>/stat and return the sum of the
376 // CPU-related ticks.  Returns -1 on parse error.
377 // Exposed for testing.
378 BASE_EXPORT int ParseProcStatCPU(std::string_view input);
379 
380 // Get the number of threads of |process| as available in /proc/<pid>/stat.
381 // This should be used with care as no synchronization with running threads is
382 // done. This is mostly useful to guarantee being single-threaded.
383 // Returns 0 on failure.
384 BASE_EXPORT int64_t GetNumberOfThreads(ProcessHandle process);
385 
386 // /proc/self/exe refers to the current executable.
387 BASE_EXPORT extern const char kProcSelfExe[];
388 
389 // Parses a string containing the contents of /proc/meminfo
390 // returns true on success or false for a parsing error
391 // Exposed for testing.
392 BASE_EXPORT bool ParseProcMeminfo(std::string_view input,
393                                   SystemMemoryInfoKB* meminfo);
394 
395 // Returns the memory committed by the system in KBytes, as from
396 // GetSystemCommitCharge(), using data from `meminfo` instead of /proc/meminfo.
397 // Exposed for testing.
398 BASE_EXPORT size_t
399 GetSystemCommitChargeFromMeminfo(const SystemMemoryInfoKB& meminfo);
400 
401 // Data from /proc/vmstat.
402 struct BASE_EXPORT VmStatInfo {
403   // Serializes the platform specific fields to value.
404   Value::Dict ToDict() const;
405 
406   uint64_t pswpin = 0;
407   uint64_t pswpout = 0;
408   uint64_t pgmajfault = 0;
409   uint64_t oom_kill = 0;
410 };
411 
412 // Retrieves data from /proc/vmstat about system-wide vm operations.
413 // Fills in the provided |vmstat| structure. Returns true on success.
414 BASE_EXPORT bool GetVmStatInfo(VmStatInfo* vmstat);
415 
416 // Parses a string containing the contents of /proc/vmstat
417 // returns true on success or false for a parsing error
418 // Exposed for testing.
419 BASE_EXPORT bool ParseProcVmstat(std::string_view input, VmStatInfo* vmstat);
420 
421 // Data from /proc/diskstats about system-wide disk I/O.
422 struct BASE_EXPORT SystemDiskInfo {
423   SystemDiskInfo();
424   SystemDiskInfo(const SystemDiskInfo&);
425   SystemDiskInfo& operator=(const SystemDiskInfo&);
426 
427   // Serializes the platform specific fields to value.
428   Value::Dict ToDict() const;
429 
430   uint64_t reads = 0;
431   uint64_t reads_merged = 0;
432   uint64_t sectors_read = 0;
433   uint64_t read_time = 0;
434   uint64_t writes = 0;
435   uint64_t writes_merged = 0;
436   uint64_t sectors_written = 0;
437   uint64_t write_time = 0;
438   uint64_t io = 0;
439   uint64_t io_time = 0;
440   uint64_t weighted_io_time = 0;
441 };
442 
443 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+
444 // for a generic disk or mmcblk[0-9]+ for the MMC case.
445 // Names of disk partitions (e.g. sda1) are not valid.
446 BASE_EXPORT bool IsValidDiskName(std::string_view candidate);
447 
448 // Retrieves data from /proc/diskstats about system-wide disk I/O.
449 // Fills in the provided |diskinfo| structure. Returns true on success.
450 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo);
451 
452 // Returns the amount of time spent in user space since boot across all CPUs.
453 BASE_EXPORT TimeDelta GetUserCpuTimeSinceBoot();
454 
455 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
456         // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX)
457 
458 #if BUILDFLAG(IS_CHROMEOS)
459 // Data from files in directory /sys/block/zram0 about ZRAM usage.
460 struct BASE_EXPORT SwapInfo {
SwapInfoSwapInfo461   SwapInfo()
462       : num_reads(0),
463         num_writes(0),
464         compr_data_size(0),
465         orig_data_size(0),
466         mem_used_total(0) {
467   }
468 
469   // Serializes the platform specific fields to value.
470   Value::Dict ToDict() const;
471 
472   uint64_t num_reads = 0;
473   uint64_t num_writes = 0;
474   uint64_t compr_data_size = 0;
475   uint64_t orig_data_size = 0;
476   uint64_t mem_used_total = 0;
477 };
478 
479 // Parses a string containing the contents of /sys/block/zram0/mm_stat.
480 // This should be used for the new ZRAM sysfs interfaces.
481 // Returns true on success or false for a parsing error.
482 // Exposed for testing.
483 BASE_EXPORT bool ParseZramMmStat(std::string_view mm_stat_data,
484                                  SwapInfo* swap_info);
485 
486 // Parses a string containing the contents of /sys/block/zram0/stat
487 // This should be used for the new ZRAM sysfs interfaces.
488 // Returns true on success or false for a parsing error.
489 // Exposed for testing.
490 BASE_EXPORT bool ParseZramStat(std::string_view stat_data, SwapInfo* swap_info);
491 
492 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data.
493 // Fills in the provided |swap_data| structure.
494 // Returns true on success or false for a parsing error.
495 BASE_EXPORT bool GetSwapInfo(SwapInfo* swap_info);
496 
497 // Data about GPU memory usage. These fields will be -1 if not supported.
498 struct BASE_EXPORT GraphicsMemoryInfoKB {
499   // Serializes the platform specific fields to value.
500   Value::Dict ToDict() const;
501 
502   int gpu_objects = -1;
503   int64_t gpu_memory_size = -1;
504 };
505 
506 // Report on Chrome OS graphics memory. Returns true on success.
507 // /run/debugfs_gpu is a bind mount into /sys/kernel/debug and synchronously
508 // reading the in-memory files in /sys is fast in most cases. On platform that
509 // reading the graphics memory info is slow, this function returns false.
510 BASE_EXPORT bool GetGraphicsMemoryInfo(GraphicsMemoryInfoKB* gpu_meminfo);
511 
512 #endif  // BUILDFLAG(IS_CHROMEOS)
513 
514 struct BASE_EXPORT SystemPerformanceInfo {
515   SystemPerformanceInfo();
516   SystemPerformanceInfo(const SystemPerformanceInfo& other);
517   SystemPerformanceInfo& operator=(const SystemPerformanceInfo& other);
518 
519   // Serializes the platform specific fields to value.
520   Value::Dict ToDict() const;
521 
522   // Total idle time of all processes in the system (units of 100 ns).
523   uint64_t idle_time = 0;
524   // Number of bytes read.
525   uint64_t read_transfer_count = 0;
526   // Number of bytes written.
527   uint64_t write_transfer_count = 0;
528   // Number of bytes transferred (e.g. DeviceIoControlFile)
529   uint64_t other_transfer_count = 0;
530   // The amount of read operations.
531   uint64_t read_operation_count = 0;
532   // The amount of write operations.
533   uint64_t write_operation_count = 0;
534   // The amount of other operations.
535   uint64_t other_operation_count = 0;
536   // The number of pages written to the system's pagefiles.
537   uint64_t pagefile_pages_written = 0;
538   // The number of write operations performed on the system's pagefiles.
539   uint64_t pagefile_pages_write_ios = 0;
540   // The number of pages of physical memory available to processes running on
541   // the system.
542   uint64_t available_pages = 0;
543   // The number of pages read from disk to resolve page faults.
544   uint64_t pages_read = 0;
545   // The number of read operations initiated to resolve page faults.
546   uint64_t page_read_ios = 0;
547 };
548 
549 // Retrieves performance counters from the operating system.
550 // Fills in the provided |info| structure. Returns true on success.
551 BASE_EXPORT bool GetSystemPerformanceInfo(SystemPerformanceInfo* info);
552 
553 // Collects and holds performance metrics for system memory and disk.
554 // Provides functionality to retrieve the data on various platforms and
555 // to serialize the stored data.
556 class BASE_EXPORT SystemMetrics {
557  public:
558   SystemMetrics();
559 
560   static SystemMetrics Sample();
561 
562   // Serializes the system metrics to value.
563   Value::Dict ToDict() const;
564 
565  private:
566   FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics);
567 
568   size_t committed_memory_;
569 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
570   SystemMemoryInfoKB memory_info_;
571   VmStatInfo vmstat_info_;
572   SystemDiskInfo disk_info_;
573 #endif
574 #if BUILDFLAG(IS_CHROMEOS)
575   SwapInfo swap_info_;
576   GraphicsMemoryInfoKB gpu_memory_info_;
577 #endif
578 #if BUILDFLAG(IS_WIN)
579   SystemPerformanceInfo performance_;
580 #endif
581 };
582 
583 #if BUILDFLAG(IS_APPLE)
584 enum class MachVMRegionResult {
585   // There were no more memory regions between |address| and the end of the
586   // virtual address space.
587   Finished,
588 
589   // All output parameters are invalid.
590   Error,
591 
592   // All output parameters are filled in.
593   Success
594 };
595 
596 // Returns info on the first memory region at or after |address|, including
597 // protection values. On Success, |size| reflects the size of the
598 // memory region.
599 // Returns info on the first memory region at or after |address|, including
600 // resident memory and share mode.
601 // |size| and |info| are output parameters, only valid on Success.
602 BASE_EXPORT MachVMRegionResult GetBasicInfo(mach_port_t task,
603                                             mach_vm_size_t* size,
604                                             mach_vm_address_t* address,
605                                             vm_region_basic_info_64* info);
606 
607 // Returns info on the first memory region at or after |address|, including
608 // resident memory and share mode. On Success, |size| reflects the size of the
609 // memory region.
610 // |size| and |info| are output parameters, only valid on Success.
611 // |address| is an in-out parameter, than represents both the address to start
612 // looking, and the start address of the memory region.
613 BASE_EXPORT MachVMRegionResult GetTopInfo(mach_port_t task,
614                                           mach_vm_size_t* size,
615                                           mach_vm_address_t* address,
616                                           vm_region_top_info_data_t* info);
617 #endif  // BUILDFLAG(IS_APPLE)
618 
619 }  // namespace base
620 
621 #endif  // BASE_PROCESS_PROCESS_METRICS_H_
622