• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #include "lite_perf_dumper.h"
17 
18 #include <algorithm>
19 #include <cerrno>
20 #include <cinttypes>
21 #include <securec.h>
22 #include <string>
23 
24 #include "dfx_define.h"
25 #include "dfx_dump_request.h"
26 #include "dfx_dump_res.h"
27 #include "dfx_trace.h"
28 #include "faultloggerd_client.h"
29 #include "lperf_event_record.h"
30 #include "lperf_events.h"
31 #include "lperf_record.h"
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace {
36 #undef LOG_DOMAIN
37 #undef LOG_TAG
38 #define LOG_DOMAIN 0xD002D11
39 #define LOG_TAG "DfxLitePerfDump"
40 }
41 
GetInstance()42 LitePerfDumper &LitePerfDumper::GetInstance()
43 {
44     static LitePerfDumper ins;
45     return ins;
46 }
47 
Perf()48 void LitePerfDumper::Perf()
49 {
50     LitePerfParam lperf;
51     PerfProcess(lperf);
52 }
53 
PerfProcess(LitePerfParam & lperf)54 int LitePerfDumper::PerfProcess(LitePerfParam& lperf)
55 {
56     DFX_TRACE_SCOPED("PerfProcess");
57     int ret = ReadLperfAndCheck(lperf);
58     if (ret < 0) {
59         return ret;
60     }
61 
62     int pipeWriteFd[PIPE_NUM_SZ] = { -1, -1};
63     if (RequestLitePerfPipeFd(FaultLoggerPipeType::PIPE_FD_WRITE, pipeWriteFd, 0) == -1) {
64         DFXLOGE("%{public}s request pipe failed, err:%{public}d", __func__, errno);
65         return -1;
66     }
67 
68     return PerfRecord(pipeWriteFd, lperf);
69 }
70 
PerfRecord(int (& pipeWriteFd)[2],LitePerfParam & lperf)71 int LitePerfDumper::PerfRecord(int (&pipeWriteFd)[2], LitePerfParam& lperf)
72 {
73     SmartFd bufFd(pipeWriteFd[PIPE_BUF_INDEX]);
74     SmartFd resFd(pipeWriteFd[PIPE_RES_INDEX]);
75 
76     std::vector<int> lperfTids;
77     for (auto i = 0; i < MAX_SAMPLE_TIDS; ++i) {
78         if (lperf.tids[i] <= 0) {
79             continue;
80         }
81         DFXLOGI("perf tid(%{public}d).", lperf.tids[i]);
82         lperfTids.emplace_back(lperf.tids[i]);
83     }
84 
85     LperfRecord record;
86     int res = record.StartProcessSampling(lperf.pid, lperfTids, lperf.freq, lperf.durationMs);
87     if (res == 0) {
88         std::string data;
89         if (record.CollectSampleStack(data) == 0) {
90             WriteSampleData(bufFd.GetFd(), data);
91         }
92     }
93     ssize_t nresWrite = OHOS_TEMP_FAILURE_RETRY(write(resFd.GetFd(), &res, sizeof(res)));
94     if (nresWrite != static_cast<ssize_t>(sizeof(res))) {
95         DFXLOGE("%{public}s write res fail, err:%{public}d", __func__, errno);
96         return -1;
97     }
98     record.FinishProcessSampling();
99     return 0;
100 }
101 
WriteSampleData(int bufFd,const std::string & data)102 void LitePerfDumper::WriteSampleData(int bufFd, const std::string& data)
103 {
104     constexpr size_t step = MAX_PIPE_SIZE;
105     for (size_t i = 0; i < data.size(); i += step) {
106         size_t length = (i + step) < data.size() ? step : data.size() - i;
107         DFXLOGI("%{public}s write length: %{public}zu", __func__, length);
108         ssize_t nwrite = OHOS_TEMP_FAILURE_RETRY(write(bufFd, data.substr(i, length).c_str(), length));
109         if (nwrite != static_cast<ssize_t>(length)) {
110             DFXLOGE("%{public}s write fail, err:%{public}d", __func__, errno);
111             return;
112         }
113     }
114 }
115 
ReadLperfAndCheck(LitePerfParam & lperf)116 int32_t LitePerfDumper::ReadLperfAndCheck(LitePerfParam& lperf)
117 {
118     DFX_TRACE_SCOPED("ReadRequestAndCheck");
119     ssize_t readCount = OHOS_TEMP_FAILURE_RETRY(read(STDOUT_FILENO, &lperf, sizeof(LitePerfParam)));
120     if (readCount != static_cast<long>(sizeof(LitePerfParam))) {
121         DFXLOGE("Failed to read LitePerfParam(%{public}d), readCount(%{public}zd).", errno, readCount);
122         return -1;
123     }
124     return 0;
125 }
126 
127 } // namespace HiviewDFX
128 } // namespace OHOS
129