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 27using Result = panda::ecmascript::tooling::Result; 28using Profile = panda::ecmascript::tooling::Profile; 29namespace OHOS::ArkCompiler::Toolchain { 30bool 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 50int 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 70int 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 90int 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 110int 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 130int 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 151void 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 198bool 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 222void ProfilerClient::SetSamplingInterval(int interval) 223{ 224 this->interval_ = interval; 225} 226} // OHOS::ArkCompiler::Toolchain 227