[M120 Migration][VD] Enable direct rendering for TVPlus
[platform/framework/web/chromium-efl.git] / components / power_metrics / resource_coalition_mac.mm
1 // Copyright 2021 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 "components/power_metrics/resource_coalition_mac.h"
6
7 #include <libproc.h>
8
9 #include "base/check_op.h"
10 #include "components/power_metrics/energy_impact_mac.h"
11 #include "components/power_metrics/mach_time_mac.h"
12
13 extern "C" int coalition_info_resource_usage(
14     uint64_t cid,
15     struct coalition_resource_usage* cru,
16     size_t sz);
17
18 namespace power_metrics {
19
20 absl::optional<uint64_t> GetProcessCoalitionId(base::ProcessId pid) {
21   proc_pidcoalitioninfo coalition_info = {};
22   int res = proc_pidinfo(pid, PROC_PIDCOALITIONINFO, 0, &coalition_info,
23                          sizeof(coalition_info));
24
25   if (res != sizeof(coalition_info))
26     return absl::nullopt;
27
28   return coalition_info.coalition_id[COALITION_TYPE_RESOURCE];
29 }
30
31 std::unique_ptr<coalition_resource_usage> GetCoalitionResourceUsage(
32     int64_t coalition_id) {
33   auto cru = std::make_unique<coalition_resource_usage>();
34   uint64_t res = coalition_info_resource_usage(
35       coalition_id, cru.get(), sizeof(coalition_resource_usage));
36   if (res == 0U)
37     return cru;
38   return nullptr;
39 }
40
41 coalition_resource_usage GetCoalitionResourceUsageDifference(
42     const coalition_resource_usage& left,
43     const coalition_resource_usage& right) {
44   DCHECK_GE(left.tasks_started, right.tasks_started);
45   DCHECK_GE(left.tasks_exited, right.tasks_exited);
46   DCHECK_GE(left.time_nonempty, right.time_nonempty);
47   DCHECK_GE(left.cpu_time, right.cpu_time);
48   DCHECK_GE(left.interrupt_wakeups, right.interrupt_wakeups);
49   DCHECK_GE(left.platform_idle_wakeups, right.platform_idle_wakeups);
50   DCHECK_GE(left.bytesread, right.bytesread);
51   DCHECK_GE(left.byteswritten, right.byteswritten);
52   DCHECK_GE(left.gpu_time, right.gpu_time);
53   DCHECK_GE(left.cpu_time_billed_to_me, right.cpu_time_billed_to_me);
54   DCHECK_GE(left.cpu_time_billed_to_others, right.cpu_time_billed_to_others);
55   DCHECK_GE(left.energy, right.energy);
56   DCHECK_GE(left.logical_immediate_writes, right.logical_immediate_writes);
57   DCHECK_GE(left.logical_deferred_writes, right.logical_deferred_writes);
58   DCHECK_GE(left.logical_invalidated_writes, right.logical_invalidated_writes);
59   DCHECK_GE(left.logical_metadata_writes, right.logical_metadata_writes);
60   DCHECK_GE(left.logical_immediate_writes_to_external,
61             right.logical_immediate_writes_to_external);
62   DCHECK_GE(left.logical_deferred_writes_to_external,
63             right.logical_deferred_writes_to_external);
64   DCHECK_GE(left.logical_invalidated_writes_to_external,
65             right.logical_invalidated_writes_to_external);
66   DCHECK_GE(left.logical_metadata_writes_to_external,
67             right.logical_metadata_writes_to_external);
68   DCHECK_GE(left.energy_billed_to_me, right.energy_billed_to_me);
69   DCHECK_GE(left.energy_billed_to_others, right.energy_billed_to_others);
70   DCHECK_GE(left.cpu_ptime, right.cpu_ptime);
71   DCHECK_GE(left.cpu_instructions, right.cpu_instructions);
72   DCHECK_GE(left.cpu_cycles, right.cpu_cycles);
73   DCHECK_GE(left.fs_metadata_writes, right.fs_metadata_writes);
74   DCHECK_GE(left.pm_writes, right.pm_writes);
75
76   coalition_resource_usage ret;
77
78   ret.tasks_started = left.tasks_started - right.tasks_started;
79   ret.tasks_exited = left.tasks_exited - right.tasks_exited;
80   ret.time_nonempty = left.time_nonempty - right.time_nonempty;
81   ret.cpu_time = left.cpu_time - right.cpu_time;
82   ret.interrupt_wakeups = left.interrupt_wakeups - right.interrupt_wakeups;
83   ret.platform_idle_wakeups =
84       left.platform_idle_wakeups - right.platform_idle_wakeups;
85   ret.bytesread = left.bytesread - right.bytesread;
86   ret.byteswritten = left.byteswritten - right.byteswritten;
87   ret.gpu_time = left.gpu_time - right.gpu_time;
88   ret.cpu_time_billed_to_me =
89       left.cpu_time_billed_to_me - right.cpu_time_billed_to_me;
90   ret.cpu_time_billed_to_others =
91       left.cpu_time_billed_to_others - right.cpu_time_billed_to_others;
92   ret.energy = left.energy - right.energy;
93   ret.logical_immediate_writes =
94       left.logical_immediate_writes - right.logical_immediate_writes;
95   ret.logical_deferred_writes =
96       left.logical_deferred_writes - right.logical_deferred_writes;
97   ret.logical_invalidated_writes =
98       left.logical_invalidated_writes - right.logical_invalidated_writes;
99   ret.logical_metadata_writes =
100       left.logical_metadata_writes - right.logical_metadata_writes;
101   ret.logical_immediate_writes_to_external =
102       left.logical_immediate_writes_to_external -
103       right.logical_immediate_writes_to_external;
104   ret.logical_deferred_writes_to_external =
105       left.logical_deferred_writes_to_external -
106       right.logical_deferred_writes_to_external;
107   ret.logical_invalidated_writes_to_external =
108       left.logical_invalidated_writes_to_external -
109       right.logical_invalidated_writes_to_external;
110   ret.logical_metadata_writes_to_external =
111       left.logical_metadata_writes_to_external -
112       right.logical_metadata_writes_to_external;
113   ret.energy_billed_to_me =
114       left.energy_billed_to_me - right.energy_billed_to_me;
115   ret.energy_billed_to_others =
116       left.energy_billed_to_others - right.energy_billed_to_others;
117   ret.cpu_ptime = left.cpu_ptime - right.cpu_ptime;
118
119   DCHECK_EQ(left.cpu_time_eqos_len,
120             static_cast<uint64_t>(COALITION_NUM_THREAD_QOS_TYPES));
121   DCHECK_EQ(right.cpu_time_eqos_len,
122             static_cast<uint64_t>(COALITION_NUM_THREAD_QOS_TYPES));
123
124   ret.cpu_time_eqos_len = left.cpu_time_eqos_len;
125   for (int i = 0; i < COALITION_NUM_THREAD_QOS_TYPES; ++i) {
126     if (right.cpu_time_eqos[i] > left.cpu_time_eqos[i]) {
127       // TODO(fdoray): Investigate why this happens. In the meantime, pretend
128       // that there was no CPU time at this QoS.
129       ret.cpu_time_eqos[i] = 0;
130     } else {
131       ret.cpu_time_eqos[i] = left.cpu_time_eqos[i] - right.cpu_time_eqos[i];
132     }
133   }
134
135   ret.cpu_instructions = left.cpu_instructions - right.cpu_instructions;
136   ret.cpu_cycles = left.cpu_cycles - right.cpu_cycles;
137   ret.fs_metadata_writes = left.fs_metadata_writes - right.fs_metadata_writes;
138   ret.pm_writes = left.pm_writes - right.pm_writes;
139
140   return ret;
141 }
142
143 absl::optional<CoalitionResourceUsageRate> GetCoalitionResourceUsageRate(
144     const coalition_resource_usage& begin,
145     const coalition_resource_usage& end,
146     base::TimeDelta interval_duration,
147     mach_timebase_info_data_t timebase,
148     absl::optional<EnergyImpactCoefficients> energy_impact_coefficients) {
149   // Validate that |end| >= |begin|.
150   bool end_greater_or_equal_begin =
151       std::tie(end.cpu_time, end.interrupt_wakeups, end.platform_idle_wakeups,
152                end.bytesread, end.byteswritten, end.gpu_time, end.energy) >=
153       std::tie(begin.cpu_time, begin.interrupt_wakeups,
154                begin.platform_idle_wakeups, begin.bytesread, begin.byteswritten,
155                begin.gpu_time, begin.energy);
156   for (int i = 0; i < COALITION_NUM_THREAD_QOS_TYPES; ++i) {
157     if (end.cpu_time_eqos[i] < begin.cpu_time_eqos[i])
158       end_greater_or_equal_begin = false;
159   }
160   if (!end_greater_or_equal_begin)
161     return absl::nullopt;
162
163   auto get_rate_per_second = [&interval_duration](uint64_t begin,
164                                                   uint64_t end) -> double {
165     DCHECK_GE(end, begin);
166     uint64_t diff = end - begin;
167     return diff / interval_duration.InSecondsF();
168   };
169
170   auto get_time_rate_per_second = [&interval_duration, &timebase](
171                                       uint64_t begin, uint64_t end) -> double {
172     DCHECK_GE(end, begin);
173     // Compute the delta in s, being careful to avoid truncation due to integral
174     // division.
175     double delta_sample_s =
176         power_metrics::MachTimeToNs(end - begin, timebase) /
177         static_cast<double>(base::Time::kNanosecondsPerSecond);
178     return delta_sample_s / interval_duration.InSecondsF();
179   };
180
181   CoalitionResourceUsageRate result;
182
183   result.cpu_time_per_second =
184       get_time_rate_per_second(begin.cpu_time, end.cpu_time);
185   result.interrupt_wakeups_per_second =
186       get_rate_per_second(begin.interrupt_wakeups, end.interrupt_wakeups);
187   result.platform_idle_wakeups_per_second = get_rate_per_second(
188       begin.platform_idle_wakeups, end.platform_idle_wakeups);
189   result.bytesread_per_second =
190       get_rate_per_second(begin.bytesread, end.bytesread);
191   result.byteswritten_per_second =
192       get_rate_per_second(begin.byteswritten, end.byteswritten);
193   result.gpu_time_per_second =
194       get_time_rate_per_second(begin.gpu_time, end.gpu_time);
195   result.power_nw = get_rate_per_second(begin.energy, end.energy);
196
197   for (int i = 0; i < COALITION_NUM_THREAD_QOS_TYPES; ++i) {
198     result.qos_time_per_second[i] =
199         get_time_rate_per_second(begin.cpu_time_eqos[i], end.cpu_time_eqos[i]);
200   }
201
202   if (energy_impact_coefficients.has_value()) {
203     result.energy_impact_per_second =
204         (ComputeEnergyImpactForResourceUsage(
205              end, energy_impact_coefficients.value(), timebase) -
206          ComputeEnergyImpactForResourceUsage(
207              begin, energy_impact_coefficients.value(), timebase)) /
208         interval_duration.InSecondsF();
209   }
210
211   return result;
212 }
213
214 }  // power_metrics