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