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