1 /*
2 * Copyright (c) 2023 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 "tooling/client/domain/profiler_client.h"
17 #include "tooling/base/pt_types.h"
18 #include "common/log_wrapper.h"
19 #include "tooling/utils/utils.h"
20 #include "tooling/client/session/session.h"
21
22 #include <map>
23 #include <functional>
24 #include <cstring>
25 #include <fstream>
26
27 using Result = panda::ecmascript::tooling::Result;
28 using Profile = panda::ecmascript::tooling::Profile;
29 namespace OHOS::ArkCompiler::Toolchain {
DispatcherCmd(const std::string &cmd)30 bool ProfilerClient::DispatcherCmd(const std::string &cmd)
31 {
32 std::map<std::string, std::function<int()>> dispatcherTable {
33 { "cpuprofile", std::bind(&ProfilerClient::CpuprofileCommand, this)},
34 { "cpuprofile-stop", std::bind(&ProfilerClient::CpuprofileStopCommand, this)},
35 { "cpuprofile-setSamplingInterval", std::bind(&ProfilerClient::SetSamplingIntervalCommand, this)},
36 { "cpuprofile-enable", std::bind(&ProfilerClient::CpuprofileEnableCommand, this)},
37 { "cpuprofile-disable", std::bind(&ProfilerClient::CpuprofileDisableCommand, this)},
38 };
39
40 auto entry = dispatcherTable.find(cmd);
41 if (entry == dispatcherTable.end()) {
42 LOGI("Unknown commond: %{public}s", cmd.c_str());
43 return false;
44 }
45 entry->second();
46 LOGI("DispatcherCmd cmd: %{public}s", cmd.c_str());
47 return true;
48 }
49
CpuprofileEnableCommand()50 int ProfilerClient::CpuprofileEnableCommand()
51 {
52 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
53 uint32_t id = session->GetMessageId();
54
55 idEventMap_.emplace(id, "cpuprofileenable");
56 std::unique_ptr<PtJson> request = PtJson::CreateObject();
57 request->Add("id", id);
58 request->Add("method", "Profiler.enable");
59
60 std::unique_ptr<PtJson> params = PtJson::CreateObject();
61 request->Add("params", params);
62
63 std::string message = request->Stringify();
64 if (session->ClientSendReq(message)) {
65 session->GetDomainManager().SetDomainById(id, "Profiler");
66 }
67 return 0;
68 }
69
CpuprofileDisableCommand()70 int ProfilerClient::CpuprofileDisableCommand()
71 {
72 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
73 uint32_t id = session->GetMessageId();
74
75 idEventMap_.emplace(id, "cpuprofiledisable");
76 std::unique_ptr<PtJson> request = PtJson::CreateObject();
77 request->Add("id", id);
78 request->Add("method", "Profiler.disable");
79
80 std::unique_ptr<PtJson> params = PtJson::CreateObject();
81 request->Add("params", params);
82
83 std::string message = request->Stringify();
84 if (session->ClientSendReq(message)) {
85 session->GetDomainManager().SetDomainById(id, "Profiler");
86 }
87 return 0;
88 }
89
CpuprofileCommand()90 int ProfilerClient::CpuprofileCommand()
91 {
92 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
93 uint32_t id = session->GetMessageId();
94
95 idEventMap_.emplace(id, "cpuprofile");
96 std::unique_ptr<PtJson> request = PtJson::CreateObject();
97 request->Add("id", id);
98 request->Add("method", "Profiler.start");
99
100 std::unique_ptr<PtJson> params = PtJson::CreateObject();
101 request->Add("params", params);
102
103 std::string message = request->Stringify();
104 if (session->ClientSendReq(message)) {
105 session->GetDomainManager().SetDomainById(id, "Profiler");
106 }
107 return 0;
108 }
109
CpuprofileStopCommand()110 int ProfilerClient::CpuprofileStopCommand()
111 {
112 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
113 uint32_t id = session->GetMessageId();
114
115 idEventMap_.emplace(id, "cpuprofilestop");
116 std::unique_ptr<PtJson> request = PtJson::CreateObject();
117 request->Add("id", id);
118 request->Add("method", "Profiler.stop");
119
120 std::unique_ptr<PtJson> params = PtJson::CreateObject();
121 request->Add("params", params);
122
123 std::string message = request->Stringify();
124 if (session->ClientSendReq(message)) {
125 session->GetDomainManager().SetDomainById(id, "Profiler");
126 }
127 return 0;
128 }
129
SetSamplingIntervalCommand()130 int ProfilerClient::SetSamplingIntervalCommand()
131 {
132 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
133 uint32_t id = session->GetMessageId();
134
135 idEventMap_.emplace(id, "setsamplinginterval");
136 std::unique_ptr<PtJson> request = PtJson::CreateObject();
137 request->Add("id", id);
138 request->Add("method", "Profiler.setSamplingInterval");
139
140 std::unique_ptr<PtJson> params = PtJson::CreateObject();
141 params->Add("interval", interval_);
142 request->Add("params", params);
143
144 std::string message = request->Stringify();
145 if (session->ClientSendReq(message)) {
146 session->GetDomainManager().SetDomainById(id, "Profiler");
147 }
148 return 0;
149 }
150
RecvProfilerResult(std::unique_ptr<PtJson> json)151 void ProfilerClient::RecvProfilerResult(std::unique_ptr<PtJson> json)
152 {
153 if (json == nullptr) {
154 LOGE("arkdb: json parse error");
155 return;
156 }
157
158 if (!json->IsObject()) {
159 LOGE("arkdb: json parse format error");
160 json->ReleaseRoot();
161 return;
162 }
163
164 std::unique_ptr<PtJson> result;
165 Result ret = json->GetObject("result", &result);
166 if (ret != Result::SUCCESS) {
167 LOGE("arkdb: find result error");
168 return;
169 }
170
171 std::unique_ptr<PtJson> profile;
172 ret = result->GetObject("profile", &profile);
173 if (ret != Result::SUCCESS) {
174 LOGE("arkdb: the cmd is not cp-stop!");
175 return;
176 }
177
178 char date[16];
179 char time[16];
180 bool res = Utils::GetCurrentTime(date, time, sizeof(date));
181 if (!res) {
182 LOGE("arkdb: get time failed");
183 return;
184 }
185
186 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
187 ProfilerSingleton &pro = session->GetProfilerSingleton();
188 std::string fileName = "CPU-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" +
189 std::string(time) + ".cpuprofile";
190 std::string cpufile = pro.GetAddress() + fileName;
191 std::cout << "session " << sessionId_ << " cpuprofile file name is " << cpufile << std::endl;
192 std::cout << ">>> ";
193 fflush(stdout);
194 WriteCpuProfileForFile(cpufile, profile->Stringify());
195 pro.AddCpuName(fileName);
196 }
197
WriteCpuProfileForFile(const std::string &fileName, const std::string &data)198 bool ProfilerClient::WriteCpuProfileForFile(const std::string &fileName, const std::string &data)
199 {
200 std::ofstream ofs;
201 std::string realPath;
202 bool res = Utils::RealPath(fileName, realPath, false);
203 if (!res) {
204 LOGE("arkdb: path is not realpath!");
205 return false;
206 }
207 ofs.open(fileName.c_str(), std::ios::out);
208 if (!ofs.is_open()) {
209 LOGE("arkdb: file open error!");
210 return false;
211 }
212 size_t strSize = data.size();
213 ofs.write(data.c_str(), strSize);
214 ofs.close();
215 ofs.clear();
216 Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
217 ProfilerSingleton &pro = session->GetProfilerSingleton();
218 pro.SetAddress("/data/");
219 return true;
220 }
221
SetSamplingInterval(int interval)222 void ProfilerClient::SetSamplingInterval(int interval)
223 {
224 this->interval_ = interval;
225 }
226 } // OHOS::ArkCompiler::Toolchain
227