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