• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include <iostream>
16 #include <thread>
17 #include <string>
18 #include <climits>
19 #include "include/sp_task.h"
20 #include "include/sp_profiler_factory.h"
21 #include "include/sp_utils.h"
22 #include "include/FPS.h"
23 #include "include/RAM.h"
24 #include "include/Capture.h"
25 #include "include/startup_delay.h"
26 #include "include/sp_log.h"
27 #include "ByTrace.h"
28 #include <cstdio>
29 #include <ios>
30 #include <vector>
31 #include <fstream>
32 #include <sstream>
33 #include <regex>
34 #include "unistd.h"
35 #include <future>
36 
37 namespace OHOS {
38 namespace SmartPerf {
39 const long long RM_0 = 0;
40 const long long RM_5000 = 5000;
41 const long long RM_1000000 = 1000000;
42 // init::-SESSIONID 12345678 -INTERVAL 1000 -PKG ohos.samples.ecg -c -g -t -p -f -r -fl 30
ParseToTask(std::string command,TaskInfo & taskInfo)43 static ExceptionMsg ParseToTask(std::string command, TaskInfo &taskInfo)
44 {
45     std::vector<std::string> args;
46     size_t pos = 0;
47     while ((pos = command.find(" ")) != std::string::npos) {
48         args.push_back(command.substr(0, pos));
49         command.erase(0, pos + 1);
50     }
51     args.push_back(command);
52     StuckNotification snf;
53     snf.isEffective = false;
54     std::string sessionId;
55     long long interval = 1000;
56     std::string pkg;
57     bool isFPS = false;
58     std::vector<std::string> configs;
59     for (size_t i = 0; i < args.size(); i++) {
60         if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_SESSIONID)) {
61             sessionId = args[++i];
62         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_INTERVAL)) {
63             interval = std::stoll(args[++i]);
64         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_PKG)) {
65             pkg = args[++i];
66         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_FL)) { // 获取用户fps的值,并赋给snf.   CT_FL
67             snf.fps = std::stoi(args[++i]);
68             snf.isEffective = true;
69         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_FTL)) { // 获取frameTime的值      CT_FTL
70             snf.frameTime = std::stoi(args[++i]);
71             snf.isEffective = true;
72         } else {
73             if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_F)) { // 判断用户设置是否有-f
74                 isFPS = true;
75             }
76             if (COMMAND_MAP.end() != COMMAND_MAP.find(args[i])) {
77                 configs.push_back(args[i]);
78             }
79         }
80     }
81     if (snf.isEffective && (!isFPS)) {
82         return ExceptionMsg::TASK_CONFIG_NULL;
83     }
84     if (sessionId.empty()) {
85         LOGE("ExceptionMsg ParseToTask sessoin id is null");
86         return ExceptionMsg::SESSION_ID_NULL;
87     } else if (configs.size() == 0) {
88         LOGE("ExceptionMsg ParseToTask configs size is 0");
89         return ExceptionMsg::TASK_CONFIG_NULL;
90     }
91     taskInfo = { sessionId, pkg, configs, interval, snf };
92     return ExceptionMsg::NO_ERR;
93 }
94 
MapToString(std::map<std::string,std::string> myMap)95 static std::string MapToString(std::map<std::string, std::string> myMap)
96 {
97     // 将Map转换为字符串
98     std::string str = "{ ";
99     for (auto it = myMap.begin(); it != myMap.end(); ++it) {
100         str += "\"" + it->first + "\": " + it->second + ", ";
101     }
102     const int subLen = 2;
103     str.erase(str.end() - subLen, str.end());
104     str += " }";
105     return str;
106 }
107 
InitTask(const std::string & recvStr)108 ErrCode SPTask::InitTask(const std::string &recvStr)
109 {
110     LOGI("SPTask::InitTask start param(%s)", recvStr.c_str());
111     std::string result = "";
112     SPUtils::LoadCmd("rm -f /data/local/tmp/hiprofiler_[0-9]*.htrace", result);
113     result.clear();
114     SPUtils::LoadCmd("rm -f /data/local/tmp/perf_[0-9]*.data", result);
115     std::cout << recvStr << std::endl;
116     ExceptionMsg exMsg = ParseToTask(recvStr, curTaskInfo);
117     if (exMsg == ExceptionMsg::NO_ERR) {
118         isInit = true;
119         LOGI("SPTask::InitTask Ok");
120         return ErrCode::OK;
121     }
122 
123     std::string errInfo = EXCEPTION_MSG_MAP.at(exMsg);
124     LOGI("SPTask::InitTask error(%s)", errInfo.c_str());
125     std::cout << "ExceptionMsg:" << errInfo << std::endl;
126     return ErrCode::FAILED;
127 }
128 
AsyncCollectRam()129 std::future<std::map<std::string, std::string>> SPTask::AsyncCollectRam()
130 {
131     std::future<std::map<std::string, std::string>> futureResult;
132     for (std::string ramConfig : curTaskInfo.taskConfig) {
133         if (ramConfig.find("-r") != std::string::npos) {
134             futureResult = std::async(std::launch::async, []() {
135                 return RAM::GetInstance().ItemData();
136             });
137         }
138     }
139     return futureResult;
140 }
141 
AsyncCollectFps()142 std::future<std::map<std::string, std::string>> SPTask::AsyncCollectFps()
143 {
144     std::future<std::map<std::string, std::string>> futureResult;
145     for (std::string fpsConfig : curTaskInfo.taskConfig) {
146         if (fpsConfig.find("-f") != std::string::npos) {
147             futureResult = std::async(std::launch::async, []() {
148                 return FPS::GetInstance().ItemData();
149             });
150         }
151     }
152     return futureResult;
153 }
154 
CheckFutureRam(std::future<std::map<std::string,std::string>> & ramResult,std::map<std::string,std::string> & dataMap)155 void SPTask::CheckFutureRam(std::future<std::map<std::string, std::string>> &ramResult,
156     std::map<std::string, std::string> &dataMap)
157 {
158     if (ramResult.valid()) {
159         std::map<std::string, std::string> result = ramResult.get();
160         dataMap.insert(result.begin(), result.end());
161     }
162 }
163 
CheckFutureFps(std::future<std::map<std::string,std::string>> & fpsResult,std::map<std::string,std::string> & dataMap)164 void SPTask::CheckFutureFps(std::future<std::map<std::string, std::string>> &fpsResult,
165     std::map<std::string, std::string> &dataMap)
166 {
167     if (fpsResult.valid()) {
168         std::map<std::string, std::string> result = fpsResult.get();
169         dataMap.insert(result.begin(), result.end());
170     }
171 }
172 
GetItemData(std::map<std::string,std::string> & dataMap)173 void SPTask::GetItemData(std::map<std::string, std::string> &dataMap)
174 {
175     for (std::string itConfig : curTaskInfo.taskConfig) {
176         if (itConfig.find("-snapshot") != std::string::npos) {
177             Capture::GetInstance().SocketMessage();
178             std::map<std::string, std::string> captureMap = Capture::GetInstance().ItemData();
179             dataMap.insert(captureMap.begin(), captureMap.end());
180         }
181         SpProfiler *profiler = SpProfilerFactory::GetCmdProfilerItem(COMMAND_MAP.at(itConfig), false);
182         if (profiler != nullptr) {
183             std::map<std::string, std::string> itemMap = profiler->ItemData();
184             dataMap.insert(itemMap.begin(), itemMap.end());
185         }
186     }
187 }
188 
StartTask(std::function<void (std::string data)> msgTask)189 ErrCode SPTask::StartTask(std::function<void(std::string data)> msgTask)
190 {
191     LOGI("SPTask::StartTask start ");
192     if (!isInit) {
193         LOGW("SPTask::StartTask initialization failed");
194         return ErrCode::FAILED;
195     }
196     isRunning = true;
197     startTime = SPUtils::GetCurTime();
198     if (!curTaskInfo.packageName.empty()) {
199         SpProfilerFactory::SetProfilerPkg(curTaskInfo.packageName);
200     }
201     thread = std::thread([this, msgTask]() {
202         while (isRunning) {
203             long long lastTime = SPUtils::GetCurTime();
204             std::lock_guard<std::mutex> lock(mtx);
205             std::map<std::string, std::string> dataMap;
206             dataMap.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(lastTime)));
207             std::future<std::map<std::string, std::string>> ramResult = AsyncCollectRam();
208             std::future<std::map<std::string, std::string>> fpsResult = AsyncCollectFps();
209             GetItemData(dataMap);
210             CheckFutureRam(ramResult, dataMap);
211             CheckFutureFps(fpsResult, dataMap);
212             if (curTaskInfo.stuckInfo.isEffective) {
213                 std::map<std::string, std::string> timeUsedMap = DetectionAndGrab();
214                 if (!timeUsedMap.empty()) {
215                     dataMap.insert(timeUsedMap.begin(), timeUsedMap.end());
216                 }
217             }
218             SPData spdata;
219             spdata.values.insert(dataMap.begin(), dataMap.end());
220             vmap.push_back(spdata);
221 
222             msgTask(MapToString(dataMap));
223             long long nextTime = SPUtils::GetCurTime();
224             long long costTime = nextTime - lastTime;
225             if (costTime < curTaskInfo.freq) {
226                 std::this_thread::sleep_for(std::chrono::milliseconds(curTaskInfo.freq - costTime));
227             }
228         }
229     });
230     LOGI("SPTask::StartTask complete");
231     return ErrCode::OK;
232 }
StopTask()233 void SPTask::StopTask()
234 {
235     LOGI("SPTask::StopTask start");
236     isRunning = false;
237     if (isInit) {
238         KillHiperfCmd();
239 
240         std::string thisBasePath = baseOutPath + "/" + curTaskInfo.sessionId;
241         if (!SPUtils::FileAccess(thisBasePath)) {
242             std::string cmdResult;
243             SPUtils::LoadCmd("mkdir -p " + thisBasePath, cmdResult);
244         }
245         std::string outGeneralPath = thisBasePath + "/t_general_info.csv";
246         std::string outIndexpath = thisBasePath + "/t_index_info.csv";
247         long long endTime = SPUtils::GetCurTime();
248         long long testDuration = (endTime - startTime) / 1000;
249         std::string screenStr = SPUtils::GetScreen();
250         int pos3 = screenStr.find("=");
251         std::string refreshrate = screenStr.substr(pos3 + 1);
252         std::map<std::string, std::string> taskInfoMap = {
253             { "sessionId", curTaskInfo.sessionId },
254             { "taskId", curTaskInfo.sessionId },
255             { "appName", curTaskInfo.packageName },
256             { "packageName", curTaskInfo.packageName },
257             { "startTime", std::to_string(startTime) },
258             { "endTime", std::to_string(endTime) },
259             { "testDuration", std::to_string(testDuration) },
260             { "taskName", "testtask" },
261             { "board", "hw" },
262             { "target_fps", refreshrate },
263         };
264         std::map<std::string, std::string> deviceInfo = SPUtils::GetDeviceInfo();
265         std::map<std::string, std::string> cpuInfo = SPUtils::GetCpuInfo();
266         std::map<std::string, std::string> gpuInfo = SPUtils::GetGpuInfo();
267         std::map<std::string, std::string> destMap;
268         destMap.insert(taskInfoMap.begin(), taskInfoMap.end());
269         destMap.insert(deviceInfo.begin(), deviceInfo.end());
270         destMap.insert(cpuInfo.begin(), cpuInfo.end());
271         destMap.insert(gpuInfo.begin(), gpuInfo.end());
272         OHOS::SmartPerf::SpCsvUtil::WriteCsvH(outGeneralPath, destMap);
273         OHOS::SmartPerf::SpCsvUtil::WriteCsv(outIndexpath, vmap);
274     }
275 
276     isInit = false;
277     vmap.clear();
278     if (thread.joinable()) {
279         thread.join();
280     }
281 
282     LOGI("SPTask::StopTask complete");
283 }
284 
DetectionAndGrab()285 std::map<std::string, std::string> SPTask::DetectionAndGrab()
286 {
287     std::map<std::string, std::string> templateMap;
288     if (!curTaskInfo.stuckInfo.isEffective) {
289         return templateMap;
290     }
291 
292     FpsCurrentFpsTime fcf = FPS::GetInstance().GetFpsCurrentFpsTime();
293     long long curframeTime = fcf.currentFpsTime / RM_1000000; // Convert to milliseconds
294     std::cout << "start::" << startCaptuerTime << std::endl;
295     if (curTaskInfo.stuckInfo.fps > fcf.fps || curTaskInfo.stuckInfo.frameTime < curframeTime) {
296         if (!isCaptureTrace) {
297             isCaptureTrace = true;
298             startCaptuerTime = SPUtils::GetCurTime();
299             std::cout << "ThreadGetHiperf::" << startCaptuerTime << std::endl;
300             ThreadGetHiperf(startCaptuerTime);
301         } else {
302             long long nowTime = SPUtils::GetCurTime();
303             long long diff = startCaptuerTime > nowTime ? (LLONG_MAX - startCaptuerTime + nowTime) :
304                 (nowTime - startCaptuerTime);
305             std::cout << "else::" << startCaptuerTime << std::endl;
306             if (diff > RM_5000 && (!CheckCounterId())) {
307                 isCaptureTrace = false;
308                 startCaptuerTime = RM_0;
309             }
310             std::cout << "end::" << startCaptuerTime << std::endl;
311         }
312     }
313     templateMap["fpsWarn"] = std::to_string(fcf.fps);
314     templateMap["FrameTimeWarn"] = std::to_string(fcf.currentFpsTime);
315     templateMap["TraceTime"] = std::to_string(startCaptuerTime);
316     return templateMap;
317 }
318 
CheckCounterId()319 bool SPTask::CheckCounterId()
320 {
321     std::string result;
322 
323     SPUtils::LoadCmd("ps -ef |grep hiprofiler_cmd |grep -v grep", result);
324     if (result.empty()) {
325         return false;
326     }
327 
328     if (result.find("-k") != std::string::npos) {
329         return true;
330     }
331 
332     return false;
333 }
ThreadGetHiperf(long long ts)334 std::thread SPTask::ThreadGetHiperf(long long ts)
335 {
336     std::thread thGetTrace(&SPTask::GetHiperf, this, std::to_string(ts));
337     thGetTrace.detach();
338     return thGetTrace;
339 }
340 
GetHiperf(const std::string & traceName)341 void SPTask::GetHiperf(const std::string &traceName)
342 {
343     std::string result;
344     std::string tmp = SetHiperf(traceName);
345     std::cout << tmp << std::endl;
346     LOGI("hiprofiler exec (%s)", tmp.c_str());
347     SPUtils::LoadCmd(tmp, result);
348     LOGI("hiprofiler exec end (%s)", result.c_str());
349 }
350 
351 
CheckTcpParam(std::string str,std::string & errorInfo)352 bool SPTask::CheckTcpParam(std::string str, std::string &errorInfo)
353 {
354     std::set<std::string> keys;
355     for (auto a : COMMAND_MAP) {
356         keys.insert(a.first.substr(1)); // 不需要前面的'-'
357     }
358 
359     return SPUtils::VeriyParameter(keys, str, errorInfo);
360 }
361 
KillHiperfCmd()362 void SPTask::KillHiperfCmd()
363 {
364     std::string killCmd = "kill -9 ";
365     std::string result;
366     std::vector<std::string> out;
367 
368     std::cout << "pidof hiprofiler_cmd=" << killCmd << std::endl;
369     SPUtils::LoadCmd("pidof hiprofiler_cmd", result);
370     SPUtils::StrSplit(result, " ", out);
371 
372     for (auto it = out.begin(); out.end() != it; ++it) {
373         result.clear();
374         SPUtils::LoadCmd(killCmd + (*it), result);
375     }
376 
377     return;
378 }
379 
SetHiperf(const std::string & traceName)380 std::string SPTask::SetHiperf(const std::string &traceName)
381 {
382     std::string hiPrefix = "hiprofiler_";
383     std::string dataPrefix = "perf_";
384     requestId++;
385     std::string trtmp = strOne + hiPrefix + traceName + strTwo + "\n" + strThree + std::to_string(requestId) + "\n" +
386         strFour + "\n" + strFive + hiPrefix + traceName + strSix + "\n" + strNine + strEleven + "\n" + strSeven +
387         dataPrefix + traceName + strEight + strTen + "\n" + conFig;
388     return trtmp;
389 }
390 }
391 }
392