• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "rs_profiler_telemetry.h"
17 
18 #include "rs_profiler_settings.h"
19 
20 namespace OHOS::Rosen {
21 
22 static const StringParameter TERMAL("paths.termal");
23 static const StringParameter CURRENT("paths.current");
24 static const StringParameter VOLTAGE("paths.voltage");
25 static const StringParameter MEMORY("paths.memory");
26 // cpu
27 static const StringParameter CPU_USAGE("paths.cpu.time");
28 static const StringParameter CPU_CORES("paths.cpu.cores");
29 static const StringParameter CPU_FREQUENCY("paths.cpu.frequency");
30 static const StringParameter CPU_FREQUENCY_POLICY("paths.cpu.frequency.policy");
31 // gpu
32 static const StringParameter GPU_FREQUENCY("paths.gpu.frequency");
33 static const StringParameter GPU_FREQUENCY_MIN("paths.gpu.frequency.min");
34 static const StringParameter GPU_FREQUENCY_MAX("paths.gpu.frequency.max");
35 static const StringParameter GPU_LOAD("paths.gpu.load");
36 
37 struct CpuTime final {
38     static const uint32_t COUNT = 7;
39     double times[COUNT] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
40     double total = 0;
41 };
42 
GetTemperaturePath()43 static std::string GetTemperaturePath()
44 {
45     std::vector<std::string> directories;
46     Utils::IterateDirectory(*TERMAL, directories);
47 
48     std::string type;
49     for (const std::string& directory : directories) {
50         Utils::LoadContent(Utils::MakePath(directory, "type"), type);
51         if (type.find("soc_thermal") != std::string::npos) {
52             return Utils::MakePath(directory, "temp");
53         }
54     }
55 
56     return {};
57 }
58 
59 // cpufreq
GetCpuFrequencyPath(uint32_t cpu)60 static std::string GetCpuFrequencyPath(uint32_t cpu)
61 {
62     return Utils::MakePath(*CPU_FREQUENCY + std::to_string(cpu), "cpufreq");
63 }
64 
GetCpuCurrentFrequencyPath(uint32_t cpu)65 static std::string GetCpuCurrentFrequencyPath(uint32_t cpu)
66 {
67     return Utils::MakePath(GetCpuFrequencyPath(cpu), "scaling_cur_freq");
68 }
69 
70 // cpupolicy
GetCpuFrequencyPolicyPath(uint32_t cpu)71 static std::string GetCpuFrequencyPolicyPath(uint32_t cpu)
72 {
73     return *CPU_FREQUENCY_POLICY + std::to_string(cpu);
74 }
75 
GetCpuCurrentFrequencyPolicyPath(uint32_t cpu)76 static std::string GetCpuCurrentFrequencyPolicyPath(uint32_t cpu)
77 {
78     return Utils::MakePath(GetCpuFrequencyPolicyPath(cpu), "scaling_cur_freq");
79 }
80 
GetCpuMinFrequencyPolicyPath(uint32_t cpu)81 static std::string GetCpuMinFrequencyPolicyPath(uint32_t cpu)
82 {
83     return Utils::MakePath(GetCpuFrequencyPolicyPath(cpu), "scaling_min_freq");
84 }
85 
GetCpuMaxFrequencyPolicyPath(uint32_t cpu)86 static std::string GetCpuMaxFrequencyPolicyPath(uint32_t cpu)
87 {
88     return Utils::MakePath(GetCpuFrequencyPolicyPath(cpu), "scaling_max_freq");
89 }
90 
TemperatureToString(float temperature)91 static std::string TemperatureToString(float temperature)
92 {
93     return std::to_string(temperature) + " °C";
94 }
95 
CurrentToString(float current)96 static std::string CurrentToString(float current)
97 {
98     return std::to_string(current) + " mA";
99 }
100 
VoltageToString(float voltage)101 static std::string VoltageToString(float voltage)
102 {
103     return std::to_string(voltage) + " V";
104 }
105 
MemoryToString(uint64_t memory)106 static std::string MemoryToString(uint64_t memory)
107 {
108     return std::to_string(memory * Utils::MICRO) + " GB";
109 }
110 
FrequencyToString(float frequency)111 static std::string FrequencyToString(float frequency)
112 {
113     return std::to_string(frequency) + " GHz";
114 }
115 
LoadToString(float load)116 static std::string LoadToString(float load)
117 {
118     return std::to_string(load) + " %";
119 }
120 
FrequencyLoadToString(const FrequencyLoadInfo & info)121 static std::string FrequencyLoadToString(const FrequencyLoadInfo& info)
122 {
123     return FrequencyToString(info.current) + "(min: " + FrequencyToString(info.min) +
124            " max: " + FrequencyToString(info.max) + " load: " + LoadToString(info.load) + ")";
125 }
126 
GetMetric(const std::string & name)127 static std::string GetMetric(const std::string& name)
128 {
129     std::string metric("0");
130     Utils::LoadContent(name, metric);
131     return metric;
132 }
133 
GetMetricFloat(const std::string & name)134 static float GetMetricFloat(const std::string& name)
135 {
136     return Utils::ToFp32(GetMetric(name));
137 }
138 
GetCPUTemperature(CPUInfo & cpu)139 static void GetCPUTemperature(CPUInfo& cpu)
140 {
141     cpu.temperature = GetMetricFloat(GetTemperaturePath()) * Utils::MILLI;
142 }
143 
GetBattery(CPUInfo & cpu)144 static void GetBattery(CPUInfo& cpu)
145 {
146     cpu.current = GetMetricFloat(*CURRENT) * Utils::MICRO;
147     cpu.voltage = GetMetricFloat(*VOLTAGE) * Utils::MICRO;
148 }
149 
GetValue(const std::string & name,const std::vector<std::string> & lines,uint64_t & value)150 static void GetValue(const std::string& name, const std::vector<std::string>& lines, uint64_t& value)
151 {
152     for (const std::string& line : lines) {
153         if (line.find(name) != std::string::npos) {
154             value = Utils::ToUint64(Utils::ExtractNumber(line));
155             return;
156         }
157     }
158 }
159 
GetCPUMemory(CPUInfo & cpu)160 static void GetCPUMemory(CPUInfo& cpu)
161 {
162     std::vector<std::string> lines;
163     Utils::LoadLines(*MEMORY, lines);
164 
165     if (!lines.empty()) {
166         GetValue("MemTotal", lines, cpu.ramTotal);
167         GetValue("MemFree", lines, cpu.ramFree);
168     }
169 }
170 
GetCpuTime(const std::vector<std::string> & args,CpuTime & info)171 static uint32_t GetCpuTime(const std::vector<std::string>& args, CpuTime& info)
172 {
173     constexpr size_t cpuWordSize = 3;
174     if (args[0].size() == cpuWordSize) {
175         // this is cpu total line
176         return UINT_MAX;
177     }
178 
179     info.total = 0;
180     for (uint32_t i = 0; i < CpuTime::COUNT; i++) {
181         info.times[i] = Utils::ToUint64(args[i + 1]);
182         info.total += info.times[i];
183     }
184 
185     return Utils::ToUint64(args[0].data() + cpuWordSize);
186 }
187 
IsCpuLine(const std::vector<std::string> & args)188 static bool IsCpuLine(const std::vector<std::string>& args)
189 {
190     constexpr size_t required = 11;
191     return (args.size() == required) && (args[0].find("cpu") == 0);
192 }
193 
GetCpuTime(std::vector<CpuTime> & infos)194 static void GetCpuTime(std::vector<CpuTime>& infos)
195 {
196     std::vector<std::string> lines;
197     Utils::LoadLines(*CPU_USAGE, lines);
198     if (lines.empty()) {
199         return;
200     }
201 
202     size_t processed = 0u;
203     for (const auto& line : lines) {
204         const std::vector<std::string> args = Utils::Split(line);
205         if (!IsCpuLine(args) || (processed == infos.size())) {
206             // either there are no more cpu lines in the file
207             // or all cpus were processed
208             return;
209         }
210 
211         CpuTime info;
212         const size_t id = GetCpuTime(args, info);
213         if (id < infos.size()) {
214             infos[id] = info;
215             processed++;
216         }
217     }
218 }
219 
GetCpuTotalUsage(const CpuTime & info,const CpuTime & lastInfo)220 static float GetCpuTotalUsage(const CpuTime& info, const CpuTime& lastInfo)
221 {
222     const double deltaTotal = info.total - lastInfo.total;
223     if (deltaTotal <= 0.0) {
224         return 0.0;
225     }
226 
227     double usage = 0.0;
228     for (uint32_t i = 0; i < CpuTime::COUNT; i++) {
229         usage += std::max(info.times[i] - lastInfo.times[i], 0.0);
230     }
231 
232     constexpr double ratioToPercent = 100.0;
233     return static_cast<float>(usage * ratioToPercent / deltaTotal);
234 }
235 
GetCoreCount()236 static uint32_t GetCoreCount()
237 {
238     std::string line;
239     Utils::LoadLine(*CPU_CORES, line);
240 
241     if (line.empty()) {
242         return 0;
243     }
244 
245     if (line.size() == 1) {
246         return 1;
247     }
248 
249     constexpr size_t multiCoreLineLength = 3;
250     if (line.size() >= multiCoreLineLength) {
251         constexpr uint32_t maxCoreIndex = 2;
252         return Utils::ToUint32(line.substr(maxCoreIndex)) + 1;
253     }
254 
255     return 0;
256 }
257 
GetCPUCores(CPUInfo & cpu)258 static void GetCPUCores(CPUInfo& cpu)
259 {
260     const uint32_t cores = GetCoreCount();
261     cpu.cores = std::min(CPUInfo::MAX_CORES, cores);
262 
263     for (uint32_t i = 0; i < cpu.cores; i++) {
264         cpu.coreFrequencyLoad[i].current = GetMetricFloat(GetCpuCurrentFrequencyPath(i)) * Utils::MICRO;
265     }
266 
267     std::vector<CpuTime> cpuTime(cpu.cores);
268     GetCpuTime(cpuTime);
269 
270     static std::mutex mutex;
271     static std::vector<CpuTime> lastCpuTime;
272 
273     const std::lock_guard<std::mutex> guard(mutex);
274     if (lastCpuTime.size() < cpu.cores) {
275         lastCpuTime.resize(cpu.cores);
276     }
277 
278     for (size_t i = 0; i < cpu.cores; i++) {
279         cpu.coreFrequencyLoad[i].load = GetCpuTotalUsage(cpuTime[i], lastCpuTime[i]);
280     }
281 
282     lastCpuTime = cpuTime;
283 }
284 
GetGPUFrequencyLoad(GPUInfo & gpu)285 static void GetGPUFrequencyLoad(GPUInfo& gpu)
286 {
287     gpu.frequencyLoad.current = GetMetricFloat(*GPU_FREQUENCY) * Utils::NANO;
288     gpu.frequencyLoad.min = GetMetricFloat(*GPU_FREQUENCY_MIN) * Utils::NANO;
289     gpu.frequencyLoad.max = GetMetricFloat(*GPU_FREQUENCY_MAX) * Utils::NANO;
290     gpu.frequencyLoad.load = GetMetricFloat(*GPU_LOAD);
291 }
292 
GetDeviceInfo()293 DeviceInfo RSTelemetry::GetDeviceInfo()
294 {
295     DeviceInfo info;
296     GetBattery(info.cpu);
297     GetCPUTemperature(info.cpu);
298     GetCPUMemory(info.cpu);
299     GetCPUCores(info.cpu);
300     GetGPUFrequencyLoad(info.gpu);
301     return info;
302 }
303 
GetDeviceInfoString()304 std::string RSTelemetry::GetDeviceInfoString()
305 {
306     const DeviceInfo info = GetDeviceInfo();
307 
308     std::string out;
309     for (size_t i = 0; i < info.cpu.cores; i++) {
310         out += +"\nCPU" + std::to_string(i) + ": " + FrequencyLoadToString(info.cpu.coreFrequencyLoad[i]);
311     }
312 
313     out += "\nTemperature: " + TemperatureToString(info.cpu.temperature);
314     out += "\nCurrent: " + CurrentToString(info.cpu.current) + "\nVoltage: " + VoltageToString(info.cpu.voltage);
315     out += "\nRAM Total: " + MemoryToString(info.cpu.ramTotal) + "\nRAM Free: " + MemoryToString(info.cpu.ramFree);
316     out += "\nGPU: " + FrequencyLoadToString(info.gpu.frequencyLoad);
317     return out;
318 }
319 
GetDeviceFrequencyString()320 std::string RSTelemetry::GetDeviceFrequencyString()
321 {
322     std::string out;
323 
324     constexpr int32_t count = 3;
325     for (int32_t i = 0; i < count; i++) {
326         const auto current = GetMetricFloat(GetCpuCurrentFrequencyPolicyPath(i)) * Utils::MICRO;
327         const auto max = GetMetricFloat(GetCpuMaxFrequencyPolicyPath(i)) * Utils::MICRO;
328         const auto min = GetMetricFloat(GetCpuMinFrequencyPolicyPath(i)) * Utils::MICRO;
329         out += "CPU" + std::to_string(i) + ": " + FrequencyToString(current) + "(min=" + FrequencyToString(min) +
330                " max=" + FrequencyToString(max) + ")\n";
331     }
332 
333     const DeviceInfo info = GetDeviceInfo();
334     out += "GPU: " + FrequencyLoadToString(info.gpu.frequencyLoad);
335 
336     return out;
337 }
338 
GetCpuAffinityString()339 std::string RSTelemetry::GetCpuAffinityString()
340 {
341     std::string out = "Cpu affinity mask: ";
342     const uint32_t cores = GetCoreCount();
343     for (uint32_t i = 0; i < cores; i++) {
344         out += Utils::GetCpuAffinity(i) ? "1" : "0";
345     }
346 
347     return out;
348 }
349 } // namespace OHOS::Rosen