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 #ifdef HAS_HIPERF
16 #include "perf_collector_impl.h"
17
18 #include <atomic>
19 #include <ctime>
20 #include <fstream>
21
22 #include "hiperf_client.h"
23 #include "hiview_logger.h"
24 #include "perf_decorator.h"
25
26 using namespace OHOS::HiviewDFX::UCollect;
27 using namespace OHOS::Developtools::HiPerf::HiperfClient;
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace UCollectUtil {
31 DEFINE_LOG_TAG("UCollectUtil-PerfCollectorImpl");
32 constexpr uint8_t MAX_PERF_USE_COUNT = 8;
33 constexpr int DEFAULT_PERF_RECORD_TIME = 5;
34 constexpr int DEFAULT_PERF_RECORD_FREQUENCY = 100;
35 const std::string DEFAULT_PERF_RECORD_CALLGRAPH = "fp";
36
37 std::atomic<uint8_t> PerfCollectorImpl::inUseCount_(0);
38 uint8_t PerfCollectorImpl::limitUseCount_ = MAX_PERF_USE_COUNT;
39
PerfCollectorImpl()40 PerfCollectorImpl::PerfCollectorImpl()
41 {
42 opt_.SetFrequency(DEFAULT_PERF_RECORD_FREQUENCY);
43 opt_.SetCallGraph(DEFAULT_PERF_RECORD_CALLGRAPH);
44 opt_.SetOffCPU(false);
45 }
46
SetSelectPids(const std::vector<pid_t> & selectPids)47 void PerfCollectorImpl::SetSelectPids(const std::vector<pid_t> &selectPids)
48 {
49 opt_.SetSelectPids(selectPids);
50 }
51
SetTargetSystemWide(bool enable)52 void PerfCollectorImpl::SetTargetSystemWide(bool enable)
53 {
54 opt_.SetTargetSystemWide(enable);
55 }
56
SetTimeStopSec(int timeStopSec)57 void PerfCollectorImpl::SetTimeStopSec(int timeStopSec)
58 {
59 opt_.SetTimeStopSec(timeStopSec);
60 }
61
SetFrequency(int frequency)62 void PerfCollectorImpl::SetFrequency(int frequency)
63 {
64 opt_.SetFrequency(frequency);
65 }
66
SetOffCPU(bool offCPU)67 void PerfCollectorImpl::SetOffCPU(bool offCPU)
68 {
69 opt_.SetOffCPU(offCPU);
70 }
71
SetOutputFilename(const std::string & outputFilename)72 void PerfCollectorImpl::SetOutputFilename(const std::string &outputFilename)
73 {
74 opt_.SetOutputFilename(outputFilename);
75 }
76
SetCallGraph(const std::string & sampleTypes)77 void PerfCollectorImpl::SetCallGraph(const std::string &sampleTypes)
78 {
79 opt_.SetCallGraph(sampleTypes);
80 }
81
SetSelectEvents(const std::vector<std::string> & selectEvents)82 void PerfCollectorImpl::SetSelectEvents(const std::vector<std::string> &selectEvents)
83 {
84 opt_.SetSelectEvents(selectEvents);
85 }
86
SetCpuPercent(int cpuPercent)87 void PerfCollectorImpl::SetCpuPercent(int cpuPercent)
88 {
89 opt_.SetCpuPercent(cpuPercent);
90 }
91
SetReport(bool enable)92 void PerfCollectorImpl::SetReport(bool enable)
93 {
94 opt_.SetReport(enable);
95 }
96
IncreaseUseCount()97 void PerfCollectorImpl::IncreaseUseCount()
98 {
99 inUseCount_.fetch_add(1);
100 }
101
DecreaseUseCount()102 void PerfCollectorImpl::DecreaseUseCount()
103 {
104 inUseCount_.fetch_sub(1);
105 }
106
Create()107 std::shared_ptr<PerfCollector> PerfCollector::Create()
108 {
109 return std::make_shared<PerfDecorator>(std::make_shared<PerfCollectorImpl>());
110 }
111
CheckUseCount()112 CollectResult<bool> PerfCollectorImpl::CheckUseCount()
113 {
114 HIVIEW_LOGI("current used count : %{public}d", inUseCount_.load());
115 IncreaseUseCount();
116 CollectResult<bool> result;
117 if (inUseCount_ > limitUseCount_) {
118 HIVIEW_LOGI("current used count over limit.");
119 result.data = false;
120 result.retCode = UcError::USAGE_EXCEED_LIMIT;
121 DecreaseUseCount();
122 return result;
123 }
124 result.data = true;
125 result.retCode = UcError::SUCCESS;
126 return result;
127 }
128
StartPerf(const std::string & logDir)129 CollectResult<bool> PerfCollectorImpl::StartPerf(const std::string &logDir)
130 {
131 CollectResult<bool> result = CheckUseCount();
132 if (result.retCode != UCollect::UcError::SUCCESS) {
133 return result;
134 }
135
136 HIVIEW_LOGI("start collecting data");
137 hiperfClient_.Setup(logDir);
138 bool ret = hiperfClient_.Start(opt_);
139 result.data = ret;
140 result.retCode = ret ? UcError::SUCCESS : UcError::PERF_COLLECT_FAILED;
141 HIVIEW_LOGI("finished recording with result : %{public}d", ret);
142 DecreaseUseCount();
143 return result;
144 }
145
Prepare(const std::string & logDir)146 CollectResult<bool> PerfCollectorImpl::Prepare(const std::string &logDir)
147 {
148 CollectResult<bool> result = CheckUseCount();
149 if (result.retCode != UCollect::UcError::SUCCESS) {
150 return result;
151 }
152
153 HIVIEW_LOGI("prepare collecting data");
154 hiperfClient_.Setup(logDir);
155 bool ret = hiperfClient_.PrePare(opt_);
156 result.data = ret;
157 result.retCode = ret ? UcError::SUCCESS : UcError::PERF_COLLECT_FAILED;
158 HIVIEW_LOGI("Prepare result : %{public}d", ret);
159 return result;
160 }
161
StartRun()162 CollectResult<bool> PerfCollectorImpl::StartRun()
163 {
164 HIVIEW_LOGI("bgein");
165 CollectResult<bool> result;
166 bool ret = hiperfClient_.StartRun();
167 result.data = ret;
168 result.retCode = ret ? UcError::SUCCESS : UcError::PERF_COLLECT_FAILED;
169 HIVIEW_LOGI("result : %{public}d", ret);
170 return result;
171 }
172
Pause()173 CollectResult<bool> PerfCollectorImpl::Pause()
174 {
175 HIVIEW_LOGI("begin");
176 CollectResult<bool> result;
177 bool ret = hiperfClient_.Pause();
178 result.data = ret;
179 result.retCode = ret ? UcError::SUCCESS : UcError::PERF_COLLECT_FAILED;
180 HIVIEW_LOGI("result : %{public}d", ret);
181 return result;
182 }
183
Resume()184 CollectResult<bool> PerfCollectorImpl::Resume()
185 {
186 HIVIEW_LOGI("begin");
187 CollectResult<bool> result;
188 bool ret = hiperfClient_.Pause();
189 result.data = ret;
190 result.retCode = ret ? UcError::SUCCESS : UcError::PERF_COLLECT_FAILED;
191 HIVIEW_LOGI("result : %{public}d", ret);
192 return result;
193 }
194
Stop()195 CollectResult<bool> PerfCollectorImpl::Stop()
196 {
197 HIVIEW_LOGI("begin");
198 CollectResult<bool> result;
199 bool ret = hiperfClient_.Stop();
200 result.data = ret;
201 result.retCode = ret ? UcError::SUCCESS : UcError::PERF_COLLECT_FAILED;
202 HIVIEW_LOGI("result : %{public}d", ret);
203 DecreaseUseCount();
204 hiperfClient_.KillChild();
205 return result;
206 }
207 } // UCollectUtil
208 } // HivewDFX
209 } // OHOS
210 #endif // HAS_HIPERF
211