• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 #ifndef PERF_DATA_PARSER_H
16 #define PERF_DATA_PARSER_H
17 #include <linux/perf_event.h>
18 #include <cstddef>
19 #include <cstdint>
20 #include <deque>
21 #include <set>
22 #include "common_types.h"
23 #include "event_parser_base.h"
24 #include "pbreader_file_header.h"
25 #include "htrace_plugin_time_parser.h"
26 #if is_mingw
27 #define unw_word_t uint64_t
28 #endif
29 #include "numerical_to_string.h"
30 #include "perf_events.h"
31 #include "perf_file_format.h"
32 #include "perf_file_reader.h"
33 #include "quatra_map.h"
34 #include "report.h"
35 #include "trace_data_cache.h"
36 #include "trace_streamer_filters.h"
37 
38 namespace SysTuning {
39 namespace TraceStreamer {
40 using namespace OHOS::Developtools::HiPerf;
41 enum class SplitPerfState {
42     STARTING,
43     PARSING_HEAD,
44     WAIT_FOR_ATTR,
45     PARSING_ATTR,
46     WAIT_FOR_DATA,
47     PARSING_DATA,
48     PARSING_FEATURE_SECTION,
49     WAIT_FOR_FINISH
50 };
51 class PerfDataParser : public EventParserBase, public HtracePluginTimeParser {
52 public:
53     PerfDataParser(TraceDataCache *dataCache, const TraceStreamerFilters *ctx);
54     ~PerfDataParser();
55     uint64_t InitPerfDataAndLoad(const std::deque<uint8_t> &dequeBuffer,
56                                  uint64_t size,
57                                  uint64_t offset,
58                                  bool isSplitFile,
59                                  bool isFinish);
60     void Finish();
61     void PerfReloadSymbolFile(const std::unique_ptr<SymbolsFile> &symbolsFile);
62 #ifdef ENABLE_ADDR2LINE
63     void ParseSourceLocation(const std::string &directory, const std::string &fileName);
64 #endif
GetPerfSplitResult()65     const auto &GetPerfSplitResult()
66     {
67         return splitResult_;
68     }
ClearPerfSplitResult()69     void ClearPerfSplitResult()
70     {
71         SplitDataWithdraw();
72         perfSplitError_ = false;
73         if (traceDataCache_->traceStartTime_ == INVALID_UINT64 || traceDataCache_->traceEndTime_ == 0) {
74             traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime());
75         }
76         return;
77     }
SplitDataWithdraw()78     void SplitDataWithdraw()
79     {
80         processedLength_ = 0;
81         splitDataEnd_ = false;
82         perfDataOffset_ = 0;
83         featureSection_.reset();
84         featureSectioSize_ = 0;
85         splitState_ = SplitPerfState::STARTING;
86         splitResult_.clear();
87         splitDataSize_ = 0;
88         return;
89     }
RecordPerfProfilerHeader(uint8_t * buffer,uint32_t len)90     void RecordPerfProfilerHeader(uint8_t *buffer, uint32_t len)
91     {
92         (void)memcpy_s(&profilerHeader_, sizeof(profilerHeader_), buffer, len);
93         hasProfilerHead_ = true;
94     }
95 
96 private:
97     void SetHM();
98     bool Reload();
99     bool LoadPerfData();
100     void UpdateEventConfigInfo();
101     void UpdateCmdlineInfo() const;
102     void LoadEventDesc();
103     void UpdateReportWorkloadInfo() const;
104     void UpdateSymbolAndFilesData();
105     void UpdateClockType();
106     bool RecordCallBack(std::unique_ptr<PerfEventRecord> record);
107     void UpdatePerfSampleData(uint32_t callChainId, std::unique_ptr<PerfRecordSample> &sample);
108     std::tuple<uint64_t, DataIndex> GetFileIdWithLikelyFilePath(const std::string &inputFilePath);
109     bool ReloadPerfFile(const std::unique_ptr<SymbolsFile> &symbolsFile, uint64_t &fileId, DataIndex &filePathIndex);
110     void ReloadPerfCallChain(const std::unique_ptr<SymbolsFile> &symbolsFile, uint64_t fileId, DataIndex filePathIndex);
111     uint32_t UpdateCallChainUnCompressed(const std::unique_ptr<PerfRecordSample> &sample);
112     SplitPerfState DataLengthProcessing(const std::deque<uint8_t> &dequeBuffer,
113                                         perf_event_header &dataHeader,
114                                         uint64_t size,
115                                         uint64_t &processedLen,
116                                         bool &invalid);
117     uint64_t SplitPerfData(const std::deque<uint8_t> &dequeBuffer, uint64_t size, uint64_t offset, bool isFinish);
118 
119     uint64_t DataProcessingLength(const std::deque<uint8_t> &dequeBuffer,
120                                   uint64_t size,
121                                   uint64_t offset,
122                                   bool isFinish);
123     bool SplitPerfStarting(const std::deque<uint8_t> &dequeBuffer,
124                            uint64_t size,
125                            uint64_t &processedLen,
126                            bool &invalid);
127     bool SplitPerfParsingHead(const std::deque<uint8_t> &dequeBuffer,
128                               uint64_t size,
129                               uint64_t &processedLen,
130                               bool &invalid);
131     bool SplitPerfWaitForAttr(const std::deque<uint8_t> &dequeBuffer,
132                               uint64_t size,
133                               uint64_t &processedLen,
134                               bool &invalid);
135     bool SplitPerfParsingAttr(const std::deque<uint8_t> &dequeBuffer,
136                               uint64_t size,
137                               uint64_t &processedLen,
138                               bool &invalid);
139     bool SplitPerfWaitForData(const std::deque<uint8_t> &dequeBuffer,
140                               uint64_t size,
141                               uint64_t &processedLen,
142                               bool &invalid);
143     bool SplitPerfParsingData(const std::deque<uint8_t> &dequeBuffer,
144                               uint64_t size,
145                               uint64_t &processedLen,
146                               bool &invalid);
147     bool SplitPerfParsingFeatureSection(const std::deque<uint8_t> &dequeBuffer,
148                                         uint64_t size,
149                                         uint64_t &processedLen,
150                                         bool &invalid);
151     bool SplitPerfWaitForFinish(const std::deque<uint8_t> &dequeBuffer,
152                                 uint64_t size,
153                                 uint64_t &processedLen,
154                                 bool &invalid);
155 
156     uint32_t callChainId_ = 0;
157     std::unique_ptr<PerfFileReader> recordDataReader_ = nullptr;
158     std::unique_ptr<uint8_t[]> buffer_ = {};
159     size_t bufferSize_ = 0;
160     bool cpuOffMode_ = false;
161     std::unique_ptr<Report> report_ = nullptr;
162     uint32_t useClockId_ = 0;
163     uint32_t clockId_ = 0;
164     enum PerfClockType {
165         PERF_CLOCK_REALTIME = 0,
166         PERF_CLOCK_MONOTONIC,
167         PERF_CLOCK_MONOTONIC_RAW = 4,
168         PERF_CLOCK_BOOTTIME = 7,
169     };
170     DataIndex configNameIndex_ = 0;
171     DataIndex workloaderIndex_ = 0;
172     DataIndex cmdlineIndex_ = 0;
173     DataIndex runingStateIndex_ = 0;
174     DataIndex suspendStatIndex_ = 0;
175     DataIndex unknownStateIndex_ = 0;
176     std::unordered_multimap<uint64_t, uint64_t> tidToPid_ = {};
177     const std::map<uint32_t, uint32_t> perfToTSClockType_ = {{PERF_CLOCK_REALTIME, TS_CLOCK_REALTIME},
178                                                              {PERF_CLOCK_MONOTONIC, TS_MONOTONIC},
179                                                              {PERF_CLOCK_MONOTONIC_RAW, TS_MONOTONIC_RAW},
180                                                              {PERF_CLOCK_BOOTTIME, TS_CLOCK_BOOTTIME}};
181     std::map<uint64_t, uint64_t> fileDataDictIdToFileId_ = {};
182     std::hash<std::string_view> hashFun_;
183     DoubleMap<uint32_t, uint64_t, uint32_t> pidAndStackHashToCallChainId_;
184     std::unordered_map<uint32_t, std::tuple<pid_t, pid_t>> callChainIdToThreadInfo_ = {};
185     const std::string tmpPerfData_ = "ts_tmp.perf.data";
186     const std::string cpuOffEventName_ = "sched:sched_switch";
187     const std::string wakingEventName_ = "sched:sched_waking";
188 
189     ProfilerTraceFileHeader profilerHeader_;
190     bool hasProfilerHead_ = false;
191     perf_file_header perfHeader_;
192     uint32_t featureCount_ = 0;
193     uint64_t sampleType_ = 0;
194     uint32_t sampleTimeOffset_ = 0;
195     uint64_t processedLength_ = 0;
196     bool splitDataEnd_ = false;
197     bool perfSplitError_ = false;
198     int32_t perfDataOffset_ = 0;
199     std::unique_ptr<uint8_t[]> featureSection_ = nullptr;
200     size_t featureSectioSize_ = 0;
201     SplitPerfState splitState_ = SplitPerfState::STARTING;
202     uint64_t splitDataSize_ = 0;
203     std::vector<HtraceSplitResult> splitResult_;
204     bool stackCompressedMode_ = false;
205     std::set<uint32_t> savedCompressedCallChainId_ = {};
206     uint32_t compressFailedCallChainId_ = INVALID_UINT32;
207 };
208 } // namespace TraceStreamer
209 } // namespace SysTuning
210 #endif // PERF_DATA_PARSER_H
211