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