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 <cstdio>
16 #include <thread>
17 #include <cstring>
18 #include <iterator>
19 #include "unistd.h"
20 #include "include/heartbeat.h"
21 #include "include/sp_utils.h"
22 #include "include/sp_csv_util.h"
23 #include "include/sp_profiler_factory.h"
24 #include "include/sp_thread_socket.h"
25 #include "include/startup_delay.h"
26 #include "include/ByTrace.h"
27 #include "include/smartperf_command.h"
28 #include "include/sp_log.h"
29 #include "include/RAM.h"
30 #include "include/common.h"
31 #include "include/FPS.h"
32 #include "include/sp_task.h"
33
34 namespace OHOS {
35 namespace SmartPerf {
SmartPerfCommand(std::vector<std::string> argv)36 SmartPerfCommand::SmartPerfCommand(std::vector<std::string> argv)
37 {
38 LOGD("SmartPerfCommand::SmartPerfCommand size(%u)", argv.size());
39 if (argv.size() == oneParam) {
40 EnableWriteLogAndDeleteOldLogFiles();
41 OHOS::SmartPerf::StartUpDelay sd;
42 sd.GetSpTcp();
43 std::string pidStr = sd.GetPidByPkg("SP_daemon");
44 std::string cmdStr = CMD_COMMAND_MAP.at(CmdCommand::TASKSET);
45 std::string result = "";
46 SPUtils::LoadCmd(cmdStr + pidStr, result);
47 daemon(0, 0);
48 CreateSocketThread();
49 }
50 if (argv.size() == twoParam) {
51 auto iterator = COMMAND_HELP_MAP.begin();
52 while (iterator != COMMAND_HELP_MAP.end()) {
53 if (iterator->second.compare(argv[1]) == 0) {
54 HelpCommand(iterator->first, "");
55 break;
56 }
57 if (argv[1].find("-editorServer") != std::string::npos) {
58 WLOGI("############################# Found '-editorServer' argument in argv");
59 const size_t tokenStartPosition = 14;
60 std::string token = argv[1].substr(tokenStartPosition, argv[1].length() - tokenStartPosition);
61 HelpCommand(CommandHelp::EDITORSERVER, token);
62 }
63 ++iterator;
64 }
65 }
66 if (argv.size() >= threeParamMore) {
67 for (int i = 1; i <= static_cast<int>(argv.size()) - 1; i++) {
68 std::string argStr = argv[i];
69 std::string argStr1;
70 if (i < static_cast<int>(argv.size()) - 1) {
71 argStr1 = argv[i + 1];
72 }
73 if (COMMAND_MAP.count(argStr) > 0) {
74 HandleCommand(argStr, argStr1);
75 }
76 }
77 }
78 LOGD("SmartPerfCommand::SmartPerfCommand complete");
79 }
HelpCommand(CommandHelp type,std::string token) const80 void SmartPerfCommand::HelpCommand(CommandHelp type, std::string token) const
81 {
82 LOGD("SmartPerfCommand::HelpCommand type(%d)", type);
83 if (type == CommandHelp::HELP) {
84 std::cout << smartPerfMsg << std::endl;
85 }
86 if (type == CommandHelp::VERSION) {
87 std::cout << "Version: " << SPUtils::GetVersion() << std::endl;
88 }
89 if (type == CommandHelp::SCREEN) {
90 std::string result = SPUtils::GetScreen();
91 std::cout << result << std::endl;
92 }
93 OHOS::SmartPerf::StartUpDelay sd;
94 if (type == CommandHelp::CLEAR) {
95 sd.GetSpClear();
96 }
97 if (type == CommandHelp::SERVER || type == CommandHelp::EDITORSERVER) {
98 sd.ClearOldServer();
99 std::string pidStr = sd.GetPidByPkg("SP_daemon");
100 std::string cmdStr = CMD_COMMAND_MAP.at(CmdCommand::TASKSET);
101 std::string result = "";
102 SPUtils::LoadCmd(cmdStr + pidStr, result);
103 if (type == CommandHelp::SERVER) {
104 daemon(0, 0);
105 } else {
106 EnableWriteLogAndDeleteOldLogFiles();
107 if (token.empty()) {
108 WLOGE("Error: token is empty when setting TCP token.");
109 return;
110 } else {
111 WLOGI("############################# Setting TCP token...");
112 SPTask::GetInstance().SetTcpToken(token);
113 WLOGI("############################# EditorServer Socket Create Start, Ready to Start Collector...");
114 }
115 }
116 CreateSocketThread();
117 }
118 }
119
CreateSocketThread() const120 void SmartPerfCommand::CreateSocketThread() const
121 {
122 InitSomething();
123 SpThreadSocket &udpThreadSocket = SpThreadSocket::GetInstance();
124 SpThreadSocket &udpExThreadSocket = SpThreadSocket::GetInstance();
125 SpThreadSocket &tcpThreadSocket = SpThreadSocket::GetInstance();
126 auto tcpSocket = std::thread([&tcpThreadSocket]() { tcpThreadSocket.Process(ProtoType::TCP); });
127 sleep(1);
128 auto udpSocket = std::thread([&udpThreadSocket]() { udpThreadSocket.Process(ProtoType::UDP); });
129 sleep(1);
130 auto udpexSocket = std::thread([&udpExThreadSocket]() { udpExThreadSocket.Process(ProtoType::UDPEX); });
131 Heartbeat &heartbeat = Heartbeat::GetInstance();
132 heartbeat.UpdatestartTime();
133 std::thread threadHeartbeat([&heartbeat]() {heartbeat.HeartbeatRule(); });
134 threadHeartbeat.detach();
135 tcpSocket.join();
136 udpSocket.join();
137 udpexSocket.join();
138 }
HandleCommand(std::string argStr,const std::string & argStr1)139 void SmartPerfCommand::HandleCommand(std::string argStr, const std::string &argStr1)
140 {
141 LOGD("SmartPerfCommand::HandleCommand argStr(%s) argStr1(%s)", argStr.c_str(), argStr1.c_str());
142 switch (COMMAND_MAP.at(argStr)) {
143 case CommandType::CT_N:
144 num = SPUtilesTye::StringToSometype<int>(argStr1.c_str());
145 break;
146 case CommandType::CT_PKG:
147 pkgName = argStr1;
148 if (pkgName.length() > 0) {
149 SpProfilerFactory::SetProfilerPkg(pkgName);
150 FPS &fps = FPS::GetInstance();
151 fps.isGameApp = SPUtils::GetIsGameApp(pkgName);
152 fps.firstDump = true;
153 }
154 break;
155 case CommandType::CT_VIEW:
156 layerName = argStr1;
157 if (layerName.length() > 0) {
158 SpProfilerFactory::SetProfilerLayer(layerName);
159 }
160 break;
161 case CommandType::CT_OUT:
162 outPathParam = argStr1;
163 if (strcmp(outPathParam.c_str(), "") != 0) {
164 outPath = outPathParam;
165 }
166 break;
167 case CommandType::CT_C:
168 case CommandType::CT_G:
169 case CommandType::CT_D:
170 case CommandType::CT_F:
171 case CommandType::CT_T:
172 case CommandType::CT_P:
173 case CommandType::CT_R:
174 case CommandType::CT_NET:
175 case CommandType::CT_TTRACE:
176 case CommandType::CT_SNAPSHOT:
177 case CommandType::CT_HW:
178 case CommandType::CT_GC:
179 case CommandType::CT_NAV:
180 case CommandType::CT_AS:
181 configs.push_back(argStr);
182 break;
183 default:
184 std::cout << "other unknown args:" << argStr << std::endl;
185 break;
186 }
187 }
188
GetItemInfo(std::multimap<std::string,std::string,decltype(SPUtils::Cmp) * > & spMap)189 int SmartPerfCommand::GetItemInfo(std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> &spMap)
190 {
191 int rc = 0;
192 std::string errInfo;
193 if (!pkgName.empty()) {
194 std::string processId = "";
195 OHOS::SmartPerf::StartUpDelay sp;
196 processId = sp.GetPidByPkg(pkgName);
197 LOGD("The cmd pid = %s", processId.c_str());
198 SpProfilerFactory::SetProfilerPidByPkg(processId);
199 }
200 for (size_t j = 0; j < configs.size(); j++) {
201 std::string curParam = configs[j];
202
203 if (curParam.find("-gc") != std::string::npos) {
204 continue;
205 }
206
207 SpProfiler *profiler = SpProfilerFactory::GetCmdProfilerItem(COMMAND_MAP.at(curParam), true);
208 if (profiler != nullptr) {
209 std::map<std::string, std::string> data = profiler->ItemData();
210 spMap.insert(data.cbegin(), data.cend());
211 }
212 }
213
214 if (!errInfo.empty()) { // GPU Counter init failed
215 printf("%s\n", errInfo.c_str());
216 LOGE("%s", errInfo.c_str());
217 return -1;
218 }
219
220 return rc;
221 }
222
SaveGpuCounter() const223 void SmartPerfCommand::SaveGpuCounter() const
224 {
225 std::string outGpuCounterDataPath = "/data/local/tmp";
226 gpuCounter.SaveData(outGpuCounterDataPath);
227 gpuCounter.StopCollect();
228 }
StartGpuCounterCollect(std::string config,bool & flag) const229 void SmartPerfCommand::StartGpuCounterCollect(std::string config, bool &flag) const
230 {
231 if (config.find("-gc") != std::string::npos) {
232 gpuCounter.StartCollect(GpuCounter::GC_START);
233 flag = true;
234 }
235 }
ExecCommand()236 std::string SmartPerfCommand::ExecCommand()
237 {
238 RAM &ram = RAM::GetInstance();
239 ram.SetFirstFlag();
240 int rc = 0;
241 int index = 0;
242 std::vector<SPData> vmap;
243 const long long freq = 1000;
244 num = num + 1;
245 bool gcFlag = false;
246 for (std::string itConfig : configs) {
247 if (itConfig.find("-aischedule") != std::string::npos) {
248 return std::string("Command not support param aischedule");
249 }
250 StartGpuCounterCollect(itConfig, gcFlag);
251 }
252 while (index < num) {
253 std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> spMap(SPUtils::Cmp);
254 long long lastTime = SPUtils::GetCurTime();
255 spMap.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(lastTime)));
256 rc = GetItemInfo(spMap);
257 if (rc == -1) {
258 break;
259 }
260 std::map<std::string, std::string> gpuCounterDataMap;
261 gpuCounter.GetGpuRealtimeData(gpuCounterDataMap);
262 spMap.insert(gpuCounterDataMap.begin(), gpuCounterDataMap.end());
263 std::cout << std::endl;
264 PrintMap(spMap, index);
265 std::cout << std::endl;
266 SPData spdata;
267 if (index != 0) {
268 spdata.values.insert(spMap.cbegin(), spMap.cend());
269 vmap.push_back(spdata);
270 }
271 long long nextTime = SPUtils::GetCurTime();
272 long long costTime = nextTime - lastTime;
273 if (costTime < freq) {
274 std::this_thread::sleep_for(std::chrono::milliseconds(freq - costTime));
275 }
276 index++;
277 }
278 if (gcFlag) {
279 SaveGpuCounter();
280 }
281 std::this_thread::sleep_for(std::chrono::milliseconds(freq));
282 SpCsvUtil::WriteCsv(std::string(outPath.c_str()), vmap);
283 return std::string("command exec finished!");
284 }
PrintfExecCommand(const std::map<std::string,std::string> data) const285 void SmartPerfCommand::PrintfExecCommand(const std::map<std::string, std::string> data) const
286 {
287 int i = 0;
288 for (auto a = data.cbegin(); a != data.cend(); ++a) {
289 printf("order:%d %s=%s\n", i++, a->first.c_str(), a->second.c_str());
290 }
291 }
292
PrintMap(std::multimap<std::string,std::string,decltype(SPUtils::Cmp) * > & spMap,int index) const293 void SmartPerfCommand::PrintMap(std::multimap<std::string, std::string,
294 decltype(SPUtils::Cmp) *> &spMap, int index) const
295 {
296 int i = 0;
297 for (auto iter = spMap.cbegin(); iter != spMap.cend(); ++iter) {
298 if (index != 0) {
299 printf("order:%d %s=%s\n", i++, iter->first.c_str(), iter->second.c_str());
300 }
301 }
302 }
303
InitSomething()304 void SmartPerfCommand::InitSomething()
305 {
306 std::string cmdResult;
307 std::string stat = CMD_COMMAND_MAP.at(CmdCommand::PROC_STAT);
308 if (SPUtils::LoadCmd(stat, cmdResult)) {
309 LOGE("SmartPerfCommand::InitSomething Privilege escalation!");
310 };
311 }
312 }
313 }
314