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 #include "base/process/process_metrics.h"
6
7 #include <utility>
8
9 #include "base/check.h"
10 #include "base/notimplemented.h"
11 #include "base/numerics/safe_conversions.h"
12 #include "base/values.h"
13 #include "build/build_config.h"
14
15 namespace base {
16
17 namespace {
18
19 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
20 BUILDFLAG(IS_AIX)
CalculateEventsPerSecond(uint64_t event_count,uint64_t * last_event_count,base::TimeTicks * last_calculated)21 int CalculateEventsPerSecond(uint64_t event_count,
22 uint64_t* last_event_count,
23 base::TimeTicks* last_calculated) {
24 const base::TimeTicks time = base::TimeTicks::Now();
25
26 int events_per_second = 0;
27 if (*last_event_count != 0) {
28 const uint64_t events_delta = event_count - *last_event_count;
29 const base::TimeDelta time_delta = time - *last_calculated;
30 DCHECK(!time_delta.is_zero());
31 events_per_second = ClampRound(events_delta / time_delta.InSecondsF());
32 }
33
34 *last_calculated = time;
35 *last_event_count = event_count;
36 return events_per_second;
37 }
38 #endif
39
40 } // namespace
41
42 SystemMemoryInfoKB::SystemMemoryInfoKB() = default;
43
44 SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB&) = default;
45
46 SystemMemoryInfoKB& SystemMemoryInfoKB::operator=(const SystemMemoryInfoKB&) =
47 default;
48
SystemMetrics()49 SystemMetrics::SystemMetrics() {
50 committed_memory_ = 0;
51 }
52
Sample()53 SystemMetrics SystemMetrics::Sample() {
54 SystemMetrics system_metrics;
55
56 system_metrics.committed_memory_ = GetSystemCommitCharge();
57 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
58 GetSystemMemoryInfo(&system_metrics.memory_info_);
59 GetVmStatInfo(&system_metrics.vmstat_info_);
60 GetSystemDiskInfo(&system_metrics.disk_info_);
61 #endif
62 #if BUILDFLAG(IS_CHROMEOS)
63 GetSwapInfo(&system_metrics.swap_info_);
64 GetGraphicsMemoryInfo(&system_metrics.gpu_memory_info_);
65 #endif
66 #if BUILDFLAG(IS_WIN)
67 GetSystemPerformanceInfo(&system_metrics.performance_);
68 #endif
69 return system_metrics;
70 }
71
ToDict() const72 Value::Dict SystemMetrics::ToDict() const {
73 Value::Dict res;
74
75 res.Set("committed_memory", static_cast<int>(committed_memory_));
76 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
77 Value::Dict meminfo = memory_info_.ToDict();
78 meminfo.Merge(vmstat_info_.ToDict());
79 res.Set("meminfo", std::move(meminfo));
80 res.Set("diskinfo", disk_info_.ToDict());
81 #endif
82 #if BUILDFLAG(IS_CHROMEOS)
83 res.Set("swapinfo", swap_info_.ToDict());
84 res.Set("gpu_meminfo", gpu_memory_info_.ToDict());
85 #endif
86 #if BUILDFLAG(IS_WIN)
87 res.Set("perfinfo", performance_.ToDict());
88 #endif
89
90 return res;
91 }
92
93 ProcessMetrics::~ProcessMetrics() = default;
94
CreateCurrentProcessMetrics()95 std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() {
96 #if !BUILDFLAG(IS_MAC)
97 return CreateProcessMetrics(base::GetCurrentProcessHandle());
98 #else
99 return CreateProcessMetrics(base::GetCurrentProcessHandle(), nullptr);
100 #endif // !BUILDFLAG(IS_MAC)
101 }
102
103 #if !BUILDFLAG(IS_FREEBSD) || !BUILDFLAG(IS_POSIX)
GetPlatformIndependentCPUUsage(TimeDelta cumulative_cpu)104 double ProcessMetrics::GetPlatformIndependentCPUUsage(
105 TimeDelta cumulative_cpu) {
106 TimeTicks time = TimeTicks::Now();
107
108 if (last_cumulative_cpu_.is_zero()) {
109 // First call, just set the last values.
110 last_cumulative_cpu_ = cumulative_cpu;
111 last_cpu_time_ = time;
112 return 0;
113 }
114
115 TimeDelta cpu_time_delta = cumulative_cpu - last_cumulative_cpu_;
116 TimeDelta time_delta = time - last_cpu_time_;
117 if (time_delta.is_zero())
118 return 0;
119
120 last_cumulative_cpu_ = cumulative_cpu;
121 last_cpu_time_ = time;
122
123 return 100.0 * cpu_time_delta / time_delta;
124 }
125
126 base::expected<double, ProcessCPUUsageError>
GetPlatformIndependentCPUUsage()127 ProcessMetrics::GetPlatformIndependentCPUUsage() {
128 return GetCumulativeCPUUsage().transform([this](base::TimeDelta cpu_usage) {
129 return GetPlatformIndependentCPUUsage(cpu_usage);
130 });
131 }
132 #endif
133
134 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
135 BUILDFLAG(IS_AIX)
CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups)136 int ProcessMetrics::CalculateIdleWakeupsPerSecond(
137 uint64_t absolute_idle_wakeups) {
138 return CalculateEventsPerSecond(absolute_idle_wakeups,
139 &last_absolute_idle_wakeups_,
140 &last_idle_wakeups_time_);
141 }
142 #else
GetIdleWakeupsPerSecond()143 int ProcessMetrics::GetIdleWakeupsPerSecond() {
144 NOTIMPLEMENTED(); // http://crbug.com/120488
145 return 0;
146 }
147 #endif // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
148 // || BUILDFLAG(IS_AIX)
149
150 #if BUILDFLAG(IS_APPLE)
CalculatePackageIdleWakeupsPerSecond(uint64_t absolute_package_idle_wakeups)151 int ProcessMetrics::CalculatePackageIdleWakeupsPerSecond(
152 uint64_t absolute_package_idle_wakeups) {
153 return CalculateEventsPerSecond(absolute_package_idle_wakeups,
154 &last_absolute_package_idle_wakeups_,
155 &last_package_idle_wakeups_time_);
156 }
157
158 #endif // BUILDFLAG(IS_APPLE)
159
160 } // namespace base
161