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