diff --git a/trace_streamer/src/rpc/ffrt_converter.cpp b/trace_streamer/src/rpc/ffrt_converter.cpp index 6da27f8a5e2c142a5a5a59f04bdb3e6cc3cd7d25..dc353b1fb4e18c50f5d8c1c502543520abd6cf94 100644 --- a/trace_streamer/src/rpc/ffrt_converter.cpp +++ b/trace_streamer/src/rpc/ffrt_converter.cpp @@ -12,511 +12,1345 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include +#include +#include +#include +#include +#include #include "ffrt_converter.h" namespace SysTuning { namespace TraceStreamer { -bool FfrtConverter::RecoverTraceAndGenerateNewFile(const std::string &ffrtFileName, std::ofstream &outFile) +constexpr uint64_t INITIAL_TEXT_LINE_NUM = 2000000; +constexpr uint64_t MAX_MOCK_TID = 4294967295; +constexpr size_t BUFFER_SIZE = 1024 * 1024; // 1MB buffer + +using PidMap = std::unordered_map>; +using FfrtTidMap = std::unordered_map>>; +using FfrtPids = std::unordered_map; +using WakeLogs = std::unordered_map>; +using FfrtWakeLogs = std::unordered_map; +using Info = const std::pair>; +using ConVecStr = const std::vector; + +static bool WriteOutputFile(std::ofstream &outfile, std::vector &context_) +{ + if (!outfile.is_open()) { + TS_LOGE("outFile is invalid."); + return false; + } + + std::vector file_buffer(BUFFER_SIZE); + outfile.rdbuf()->pubsetbuf(file_buffer.data(), file_buffer.size()); + + for (const auto& line : context_) { + outfile.write(line.c_str(), line.size()); + outfile.put('\n'); + } + + outfile.close(); + context_.clear(); + return true; +} + +bool FfrtConverter::RecoverTraceAndGenerateNewFile(ConStr &ffrtFileName, std::ofstream &outFile) { std::ifstream ffrtFile(ffrtFileName); if (!ffrtFile.is_open() || !outFile.is_open()) { TS_LOGE("ffrtFile or outFile is invalid."); return false; } + + // reserve initial line size + context_.reserve(INITIAL_TEXT_LINE_NUM); std::string line; - while (std::getline(ffrtFile, line)) + while (std::getline(ffrtFile, line)) { context_.emplace_back(line); + } ffrtFile.close(); - InitTracingMarkerKey(); - ClassifyContextForFfrtWorker(); - ConvertFfrtThreadToFfrtTask(); - for (const std::string &oneLine : context_) { - outFile << oneLine << std::endl; + + FfrtPids ffrtPids; + FfrtWakeLogs ffrtWakeLogs; + ClassifyLogsForFfrtWorker(ffrtPids, ffrtWakeLogs); + + if (tracingMarkerKey_.empty()) { + tracingMarkerKey_ = "tracing_mark_write: "; } - Clear(); - return true; -} -void FfrtConverter::Clear() -{ - context_.clear(); - ffrtPidMap_.clear(); - taskLabels_.clear(); + + if (osPlatformKet_ == "ohos") { + ConvertFrrtThreadToFfrtTaskOhos(ffrtPids, ffrtWakeLogs); + } else { + ConvertFrrtThreadToFfrtTaskNohos(ffrtPids, ffrtWakeLogs); + } + + return WriteOutputFile(outFile, context_); } -void FfrtConverter::InitTracingMarkerKey() + +static uint32_t ExtractProcessId(ConStr& log) { - for (auto line : context_) { - if (line.find(" tracing_mark_write: ") != std::string::npos) { - tracingMarkerKey_ = "tracing_mark_write: "; - break; + size_t leftParen = log.find('('); + size_t rightParen = log.find(')', leftParen); + if (leftParen == std::string::npos || rightParen == std::string::npos || leftParen >= rightParen) { + return 0; + } + + std::string processIdStr = log.substr(leftParen + 1, rightParen - leftParen - 1); + processIdStr.erase(0, processIdStr.find_first_not_of(" \t")); + size_t lastNonSpace = processIdStr.find_last_not_of(" \t"); + if (lastNonSpace != std::string::npos) { + processIdStr.erase(lastNonSpace + 1); + } + + if (processIdStr.find('-') != std::string::npos || processIdStr.empty()) { + return 0; + } + + uint32_t processId = 0; + const int base = 10; + for (char c : processIdStr) { + if (!std::isdigit(c)) { + return 0; } - if (line.find(" print: ") != std::string::npos) { - tracingMarkerKey_ = "print: "; - break; + processId = processId * base + (static_cast(c) - static_cast('0')); + if (processId > UINT32_MAX) { + return 0; } } + return processId; } -int FfrtConverter::ExtractProcessId(const size_t index) + +static int ExtractThreadId(ConStr& log) { + static const std::regex pattern(R"( \(.+\)\s+\[\d)"); std::smatch match; - static const std::regex pidPattern = std::regex(R"(\(\s*\d+\) \[)"); - if (!std::regex_search(context_[index], match, pidPattern)) { - return 0; + if (std::regex_search(log, match, pattern)) { + std::string prefix = log.substr(0, match.position()); + return std::stoull(prefix.substr(prefix.find_last_of('-') + 1)); } - for (size_t i = 0; i < match.size(); i++) { - if (match[i] == '-') { - return 0; + return INT_MAX; +} + +static std::string TrimRight(ConStr& str) +{ + auto end = std::find_if_not(str.rbegin(), str.rend(), [](unsigned char ch) { + return std::isspace(ch); + }).base(); + + return std::string(str.begin(), end); +} + +static void ExtraceFfrtThreadInfoFromSchedSwitch(ConStr &log, std::string &tName, int& tid) +{ + static std::string prevComm = "prev_comm"; + static std::string prevPid = "prev_pid="; + size_t prevCommPos = log.find(prevComm); + size_t prevPidPos = log.find(prevPid); + if (prevCommPos != std::string::npos && prevPidPos != std::string::npos) { + if (prevCommPos < prevPidPos) { + std::string containName = log.substr(prevCommPos, prevPidPos - prevCommPos); + size_t tNameStartIndex = containName.find_first_of("=") + 1; + tName = containName.substr(tNameStartIndex, containName.size() - tNameStartIndex); + size_t startPos = prevPidPos + prevComm.size(); + size_t tidLen = log.find(" ", prevPidPos) - prevPidPos - prevPid.size(); + tid = std::stoull(log.substr(startPos, tidLen)); } + } else { + tName = ""; + tid = -1; } - auto beginPos = match.str().find('(') + 1; - auto endPos = match.str().find(')'); - return std::stoi(match.str().substr(beginPos, endPos - beginPos)); } -std::string FfrtConverter::ExtractTimeStr(const std::string &log) +static std::string ExtractTimeStr(ConStr &log) { std::smatch match; + static const int spaceNum = 2; static const std::regex timePattern = std::regex(R"( (\d+)\.(\d+):)"); if (std::regex_search(log, match, timePattern)) { - return match.str().substr(1, match.str().size() - STR_LEGH); + return match.str().substr(1, match.str().size() - spaceNum); } return ""; } -std::string FfrtConverter::ExtractCpuId(const std::string &log) +static std::string ExtractCpuId(ConStr &log) { std::smatch match; - static const std::regex cpuIdPattern = std::regex(R"(\) \[.*?\])"); - if (std::regex_search(log, match, cpuIdPattern)) { - auto beginPos = match.str().find('[') + 1; - auto endPos = match.str().find(']'); - return match.str().substr(beginPos, endPos - beginPos); + static const int spaceNum = 3; + static const std::regex cpuidpattern = std::regex(R"(\) \[.*?\])"); + if (std::regex_search(log, match, cpuidpattern)) { + return log.substr(match.position() + spaceNum, spaceNum); } return ""; } -std::string FfrtConverter::MakeBeginFakeLog(const std::string &mark, - const long long gid, - const int prio, - const ThreadInfo &threadInfo) -{ - auto beginTimeStamp = ExtractTimeStr(mark); - auto cpuId = ExtractCpuId(mark); - std::unique_ptr result = std::make_unique(MAX_LEN); - auto taskId = GetTaskId(threadInfo.pid, gid); - (void)sprintf_s( - result.get(), MAX_LEN, - "\n %s-%d (%7d) [%s] .... %s: sched_switch: prev_comm=%s prev_pid=%d prev_prio=%d prev_state=S ==> " - "next_comm=%s next_pid=%s next_prio=%d\n", - threadInfo.name.c_str(), threadInfo.tid, threadInfo.pid, cpuId.c_str(), beginTimeStamp.c_str(), - threadInfo.name.c_str(), threadInfo.tid, prio, taskLabels_[threadInfo.pid][gid].c_str(), taskId.c_str(), prio); - return mark + result.get(); -} - -std::string FfrtConverter::MakeEndFakeLog(const std::string &mark, - const long long gid, - const int prio, - const ThreadInfo &threadInfo) -{ - auto endTimeStamp = ExtractTimeStr(mark); - auto cpuId = ExtractCpuId(mark); - std::unique_ptr result = std::make_unique(MAX_LEN); - auto taskId = GetTaskId(threadInfo.pid, gid); - (void)sprintf_s( - result.get(), MAX_LEN, - " %s-%s (%7d) [%s] .... %s: sched_switch: prev_comm=%s prev_pid=%s prev_prio=%d prev_state=S ==> " - "next_comm=%s next_pid=%d next_prio=%d\n", - taskLabels_[threadInfo.pid][gid].c_str(), taskId.c_str(), threadInfo.pid, cpuId.c_str(), endTimeStamp.c_str(), - taskLabels_[threadInfo.pid][gid].c_str(), taskId.c_str(), prio, threadInfo.name.c_str(), threadInfo.tid, prio); - std::string fakeLog = result.get(); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - return fakeLog; +static std::string ExtractTaskLable(ConStr& log) +{ + size_t pos = log.find("|H:FFRT"); + if (pos != std::string::npos) { // ohos + size_t startPos = pos + std::string("|H:FFRT").length(); + size_t endPos = log.find("|", startPos); + if (endPos != std::string::npos) { + return log.substr(startPos, endPos - startPos); + } + } else { + size_t startPos = log.find_last_of("["); + size_t endPos = log.find("]", startPos); + if (startPos != std::string::npos && endPos != std::string::npos) { + return log.substr(startPos + 1, endPos - startPos - 1); + } + } + return ""; // Return empty string if no label found } -std::string FfrtConverter::ReplaceSchedSwitchLog(std::string &fakeLog, - const std::string &mark, - const int pid, - const long long gid, - const int tid) +static void FindPrevAndNextPidForSchedSwitch(ConStr &log, int &prevPid, int &nextPid) { - std::unique_ptr result = std::make_unique(MAX_LEN); - std::smatch match; - auto taskId = GetTaskId(pid, gid); - if (mark.find("prev_pid=" + std::to_string(tid)) != std::string::npos) { - if (regex_search(fakeLog, match, indexPattern_) && fakeLog.find("prev_comm=") != std::string::npos && - fakeLog.find("prev_prio=") != std::string::npos) { - auto beginPos = fakeLog.find(match.str()); - (void)sprintf_s(result.get(), MAX_LEN, " %s-%s ", taskLabels_[pid][gid].c_str(), taskId.c_str()); - fakeLog = result.get() + fakeLog.substr(beginPos); - size_t pcommPos = fakeLog.find("prev_comm="); - size_t pPidPos = fakeLog.find("prev_pid="); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - (void)sprintf_s(result.get(), MAX_LEN, "prev_comm=%s ", taskLabels_[pid][gid].c_str()); - fakeLog = fakeLog.substr(0, pcommPos) + result.get() + fakeLog.substr(pPidPos); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - pPidPos = fakeLog.find("prev_pid="); - size_t pPrioPos = fakeLog.find("prev_prio="); - (void)sprintf_s(result.get(), MAX_LEN, "prev_pid=%s ", taskId.c_str()); - fakeLog = fakeLog.substr(0, pPidPos) + result.get() + fakeLog.substr(pPrioPos); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - } - } else if (mark.find("next_pid=" + std::to_string(tid)) != std::string::npos && - fakeLog.find("next_comm=") != std::string::npos && fakeLog.find("next_prio=") != std::string::npos) { - (void)sprintf_s(result.get(), MAX_LEN, "next_comm=%s ", taskLabels_[pid][gid].c_str()); - size_t nCommPos = fakeLog.find("next_comm="); - size_t nPidPos = fakeLog.find("next_pid="); - fakeLog = fakeLog.substr(0, nCommPos) + result.get() + fakeLog.substr(nPidPos); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - (void)sprintf_s(result.get(), MAX_LEN, "next_pid=%s ", taskId.c_str()); - nPidPos = fakeLog.find("next_pid="); - size_t nPrioPos = fakeLog.find("next_prio="); - fakeLog = fakeLog.substr(0, nPidPos) + result.get() + fakeLog.substr(nPrioPos); + static std::string prevPidStr = "prev_pid="; + static std::string nextPidStr = "next_pid="; + size_t prevPidPos = log.find(prevPidStr); + size_t nextPidPos = log.find(nextPidStr); + size_t startPos = prevPidPos + prevPidStr.size(); + size_t pidLen = log.find(" ", prevPidPos) - prevPidPos - (prevPidStr.size() - 1); + prevPid = std::stoull(log.substr(startPos, pidLen)); + startPos = nextPidPos + nextPidStr.size(); + pidLen = log.find(" ", nextPidPos) - nextPidPos - (nextPidStr.size() - 1); + nextPid = std::stoull(log.substr(startPos, pidLen)); +} + +void FfrtConverter::SetOSPlatformKey(const FfrtTidMap &ffrtTidMap) +{ + for (const auto& tinfo : ffrtTidMap) { + if (tinfo.second.first.find("ffrtwk") != std::string::npos) { + osPlatformKet_ = "nohos"; + return; + } + if (tinfo.second.first.find("OS_FFRT_") != std::string::npos) { + osPlatformKet_ = "ohos"; + return; + } } - return fakeLog; } -std::string FfrtConverter::ReplaceSchedWakeLog(std::string &fakeLog, - const std::string &label, - const int pid, - const long long gid) +static void PushProcessNamePositions(ConStr &log, size_t &hyphenPos, size_t &spacePos, std::vector &indexs) { - std::unique_ptr result = std::make_unique(MAX_LEN); - auto taskId = GetTaskId(pid, gid); - (void)sprintf_s(result.get(), MAX_LEN, "comm=%s ", label.c_str()); - size_t commPos = fakeLog.find("comm="); - size_t pidPos = fakeLog.find("pid="); - if (commPos != std::string::npos && pidPos != std::string::npos) { - fakeLog = fakeLog.substr(0, commPos) + result.get() + fakeLog.substr(pidPos); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - (void)sprintf_s(result.get(), MAX_LEN, "pid=%s ", taskId.c_str()); - pidPos = fakeLog.find("pid="); - size_t prioPos = fakeLog.find("prio="); - if (prioPos != std::string::npos) { - fakeLog = fakeLog.substr(0, pidPos) + result.get() + fakeLog.substr(prioPos); + bool allDigits = true; + for (size_t i = hyphenPos + 1; i < spacePos; ++i) { + if (!isdigit(log[i])) { + allDigits = false; + break; + } + } + + if (allDigits && spacePos > hyphenPos + 1) { + bool foundStart = false; + size_t start = hyphenPos; + while (start > 0) { + if (isspace(log[start - 1])) { + foundStart = true; + break; + } + --start; + } + if (foundStart || start == 0) { + indexs.push_back(start); } } - return fakeLog; } -std::string FfrtConverter::ReplaceSchedBlockLog(std::string &fakeLog, const int pid, const long long gid) +static void FindProcessNamePositions(ConStr &log, std::vector &indexs) { - std::unique_ptr result = std::make_unique(MAX_LEN); - auto taskId = GetTaskId(pid, gid); - (void)sprintf_s(result.get(), MAX_LEN, "pid=%s ", taskId.c_str()); - size_t pidPos = fakeLog.find("pid"); - size_t ioPos = fakeLog.find("iowait="); - if (pidPos != std::string::npos && ioPos != std::string::npos) { - fakeLog = fakeLog.substr(0, pidPos) + result.get() + fakeLog.substr(ioPos); + size_t pos = 0; + const size_t logLength = log.length(); + while (pos < logLength) { + size_t hyphenPos = log.find('-', pos); + if (hyphenPos == std::string::npos) { + break; + } + + size_t spacePos = hyphenPos + 1; + while (spacePos < logLength && !isspace(log[spacePos])) { + spacePos++; + } + if (spacePos < logLength && isspace(log[spacePos])) { + size_t bracketPos = spacePos; + while (bracketPos < logLength && isspace(log[bracketPos])) { + bracketPos++; + } + if (bracketPos < logLength && log[bracketPos] == '(') { + PushProcessNamePositions(log, hyphenPos, spacePos, indexs); + } + } + pos = hyphenPos + 1; } - return fakeLog; } -std::string FfrtConverter::ReplaceTracingMarkLog(std::string &fakeLog, - const std::string &label, - const int pid, - const long long gid) + +static void SplitLogs(std::vector &indexs, std::vector &newLogs, ConStr& log) { - std::unique_ptr result = std::make_unique(MAX_LEN); - std::smatch match; - auto taskId = GetTaskId(pid, gid); - if (regex_search(fakeLog, match, indexPattern_)) { - auto beginPos = fakeLog.find(match.str()); - (void)sprintf_s(result.get(), MAX_LEN, " %s-%s ", label.c_str(), taskId.c_str()); - fakeLog = result.get() + fakeLog.substr(beginPos); + for (int i = 0; i < indexs.size(); i++) { + int begin = indexs[i]; + int end = (i + 1 < indexs.size()) ? indexs[i + 1] : static_cast(log.size()); + std::string logSplit = log.substr(begin, end - begin); + if (i + 1 < indexs.size()) { + logSplit += "\n"; + } + newLogs.emplace_back(logSplit); + } +} + +static void GenFfrtPids(FfrtPids& ffrtPids, Info &info, FfrtTidMap &ffrtTidMap, WakeLogs &traceMap) +{ + for (const auto tid : info.second) { + if (ffrtTidMap.find(tid) != ffrtTidMap.end()) { + if (ffrtPids.find(info.first) == ffrtPids.end()) { + ffrtPids[info.first] = {}; + } + ffrtPids[info.first][tid] = ffrtTidMap[tid]; + ffrtPids[info.first][tid].second = traceMap[tid]; + } + } +} + +void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& ffrtWakeLogs) +{ + PidMap pidMap; + FfrtTidMap ffrtTidMap; + WakeLogs traceMap; + const size_t estimatedSize = context_.size(); + const size_t oneHundred = 100; + const size_t fifty = 50; + const size_t ten = 10; + pidMap.reserve(estimatedSize / oneHundred); + ffrtTidMap.reserve(estimatedSize / fifty); + traceMap.reserve(estimatedSize / fifty); +#ifdef MUL_THREAD_EXEC + std::mutex pidMutex; + std::mutex tidMutex; + std::mutex traceMutex; + std::mutex contextMutex; + const size_t numThreads = std::thread::hardware_concurrency(); + const size_t chunkSize = context_.size() / numThreads + 1; + std::vector threads; + threads.reserve(numThreads); + std::vector> threadUpdates(numThreads); + + auto worker = [&](size_t threadId, size_t start, size_t end) { + std::vector indexs; + indexs.reserve(10); + std::unordered_map> localPidMap; + std::unordered_map>> locFfrtTidMap; + std::unordered_map> locTraceMap; + std::vector& updates = threadUpdates[threadId]; + + for (size_t lineno = start; lineno < end && lineno < context_.size(); ++lineno) { + const std::string& log = context_[lineno]; + indexs.clear(); + FindProcessNamePositions(log, indexs); + + if (indexs.size() > 1) { + ContextUpdate update; + update.position = lineno; + for (size_t i = 0; i < indexs.size(); ++i) { + int begin = indexs[i]; + end = (i + 1 < indexs.size()) ? indexs[i + 1] : static_cast(log.size()); + std::string logSplit = log.substr(begin, end - begin); + if (i + 1 < indexs.size()) { + logSplit += "\n"; + } + update.new_logs.push_back(logSplit); + } + updates.push_back(update); + for (size_t i = 0; i < update.new_logs.size(); ++i) { + auto logInfo = LogInfo{update.new_logs[i], static_cast(lineno + i), 0, 0}; + FindFfrtProcClassifyLogs(logInfo, locTraceMap, localPidMap, locFfrtTidMap, ffrtWakeLogs); + } + } else { + auto logInfo = LogInfo{log, static_cast(lineno), 0, 0}; + FindFfrtProcClassifyLogs(logInfo, locTraceMap, localPidMap, locFfrtTidMap, ffrtWakeLogs); + } + } + { + std::lock_guard lock(pidMutex); + for (const auto& [pid, tid_set] : localPidMap) { + pidMap[pid].insert(tid_set.begin(), tid_set.end()); + } + } + { + std::lock_guard lock(tidMutex); + for (const auto& [tid, info] : locFfrtTidMap) { + if (ffrtTidMap.find(tid) == ffrtTidMap.end()) { + ffrtTidMap[tid] = info; + } + } + } + { + std::lock_guard lock(traceMutex); + for (const auto& [tid, traces] : locTraceMap) { + auto& target = traceMap[tid]; + target.insert(target.end(), traces.begin(), traces.end()); + } + } + }; + for (size_t i = 0; i < numThreads; ++i) { + std::lock_guard lock(contextMutex); + size_t start = i * chunkSize; + size_t end = std::min((i + 1) * chunkSize, context_.size()); + threads.emplace_back(worker, i, start, end); + } + for (auto& thread : threads) { + thread.join(); + } + std::vector allUpdates; + for (const auto& threadUpdate : threadUpdates) { + allUpdates.insert(allUpdates.end(), threadUpdate.begin(), threadUpdate.end()); + } + std::sort(allUpdates.begin(), allUpdates.end(), + [](const ContextUpdate& a, const ContextUpdate& b) { + return a.position > b.position; + }); + for (const auto& update : allUpdates) { + context_.erase(context_.begin() + update.position); + context_.insert(context_.begin() + update.position, + update.new_logs.begin(), update.new_logs.end()); + } +#else + uint64_t lineno = 0; + std::vector indexs; + indexs.reserve(ten); + auto classifyLogs = [this, &traceMap, &pidMap, &ffrtTidMap, &ffrtWakeLogs](ConVecStr& newLogs, size_t startLineNo) { + for (size_t i = 0; i < newLogs.size(); ++i) { + auto logInfo = LogInfo{context_[startLineNo + i], static_cast(startLineNo + i), 0, 0}; + FindFfrtProcClassifyLogs(logInfo, traceMap, pidMap, ffrtTidMap, ffrtWakeLogs); + } + }; + while (lineno < context_.size()) { + ConStr& log = context_[lineno]; + indexs.clear(); + FindProcessNamePositions(log, indexs); + if (indexs.size() > 1) { + std::vector newLogs; + SplitLogs(indexs, newLogs, log); + context_.erase(context_.begin() + lineno); + context_.insert(context_.begin() + lineno, newLogs.begin(), newLogs.end()); + classifyLogs(newLogs, lineno); + lineno += newLogs.size() - 1; + } else { + auto logInfo = LogInfo{context_[lineno], static_cast(lineno), 0, 0}; + FindFfrtProcClassifyLogs(logInfo, traceMap, pidMap, ffrtTidMap, ffrtWakeLogs); + } + ++lineno; + } +#endif + SetOSPlatformKey(ffrtTidMap); + for (auto& info : pidMap) { + GenFfrtPids(ffrtPids, info, ffrtTidMap, traceMap); + } +} + +static size_t FindPatternStart(ConStr &log) +{ + size_t pos = 0; + while (pos < log.size()) { + pos = log.find(" (", pos); + if (pos == std::string::npos) { + return std::string::npos; + } + + size_t rightBracket = log.find(')', pos + 2); + if (rightBracket == std::string::npos) { + return std::string::npos; + } + + size_t bracketEnd = rightBracket + 1; + while (bracketEnd < log.length() && isspace(log[bracketEnd])) { + ++bracketEnd; + } + + if (bracketEnd < log.length() && + log[bracketEnd] == '[' && + bracketEnd + 1 < log.length() && + isdigit(log[bracketEnd + 1])) { + return pos; + } + pos = rightBracket + 1; + } + return std::string::npos; +} + +static size_t FindPatternEnd(ConStr &log) +{ + size_t pos = 0; + static std::string hr = "H:R"; + while (pos < log.size()) { + pos = log.find(" F|", pos); + if (pos == std::string::npos) { + return std::string::npos; + } + + size_t numStart = pos + 3; + size_t pipePos = log.find('|', numStart); + if (pipePos == std::string::npos) { + pos = numStart; + continue; + } + + bool validNum = true; + for (size_t i = numStart; i < pipePos; ++i) { + if (!isdigit(log[i])) { + validNum = false; + break; + } + } + if (!validNum || numStart == pipePos) { + pos = pipePos + 1; + continue; + } + + size_t rPos = pipePos + 1; + if (rPos + hr.size() - 1 < log.length() && log.substr(rPos, hr.size()) == hr) { + rPos += hr.size(); + } else if (rPos < log.length() && log[rPos] == 'R') { + rPos += 1; + } else { + pos = pipePos + 1; + continue; + } + + if (rPos < log.length() && (log[rPos] == '|' || isspace(log[rPos]))) { + size_t finalNum = rPos + 1; + while (finalNum < log.length() && isspace(log[finalNum])) { + finalNum++; + } + + if (finalNum < log.length() && isdigit(log[finalNum])) { + return pos; + } + } + pos = rPos; + } + return std::string::npos; +} + +static void ParseOtherTraceLogs(LogInfo logInfo, WakeLogs &traceMap, FfrtWakeLogs &ffrtWakeLogs) +{ + size_t matchPos = FindPatternStart(logInfo.log); + if (matchPos != std::string::npos) { + std::string tmp = logInfo.log.substr(0, matchPos); + logInfo.tid = std::stoull(tmp.substr(tmp.find_last_of('-') + 1)); + if (traceMap.find(logInfo.tid) == traceMap.end()) { + traceMap[logInfo.tid] = {}; + } + traceMap[logInfo.tid].emplace_back(logInfo.lineno); + + if (FindPatternEnd(logInfo.log) != std::string::npos) { + std::string hStr = logInfo.log.substr(logInfo.log.find_last_of('|') + 1); + if (hStr[0] == 'H') { + hStr = hStr.substr(hStr.find_last_of(' ') + 1); + } + int wakee = std::stoull(hStr); + if (ffrtWakeLogs.find(logInfo.pid) == ffrtWakeLogs.end()) { + ffrtWakeLogs[logInfo.pid] = {}; + } + if (ffrtWakeLogs[logInfo.pid].find(wakee) == ffrtWakeLogs[logInfo.pid].end()) { + ffrtWakeLogs[logInfo.pid][wakee] = {}; + } + ffrtWakeLogs[logInfo.pid][wakee].emplace_back(logInfo.lineno); + } + } +} + +void FfrtConverter::SetTracingMarkerKey(LogInfo logInfo) +{ + if (tracingMarkerKey_.empty()) { + if (logInfo.log.find("tracing_mark_write: ") != std::string::npos) { + tracingMarkerKey_ = "tracing_mark_write: "; + } else if (logInfo.log.find("print: ") != std::string::npos) { + tracingMarkerKey_ = "print: "; + } + } +} + +void FfrtConverter::FindFfrtProcClassifyLogs(LogInfo logInfo, WakeLogs &traceMap, PidMap &pidMap, + FfrtTidMap &ffrtTidMap, FfrtWakeLogs &ffrtWakeLogs) +{ + bool isPrevCommFfrt = logInfo.log.find("prev_comm=ffrt") != std::string::npos; + bool isPrevCommFfrtOs = logInfo.log.find("prev_comm=OS_FFRT") != std::string::npos; + auto pid = ExtractProcessId(logInfo.log); + auto tid = ExtractThreadId(logInfo.log); + if (pidMap.find(pid) == pidMap.end()) { + pidMap[pid] = {}; + } + pidMap[pid].insert(tid); + if (isPrevCommFfrt || isPrevCommFfrtOs) { + std::string tname; + ExtraceFfrtThreadInfoFromSchedSwitch(logInfo.log, tname, tid); + tname = TrimRight(tname); + if (ffrtTidMap.find(tid) == ffrtTidMap.end()) { + ffrtTidMap[tid] = {tname, {}}; + } } + + SetTracingMarkerKey(logInfo); + + if (logInfo.log.find("sched_switch: ") != std::string::npos) { + int prevTid; + int nextTid; + FindPrevAndNextPidForSchedSwitch(logInfo.log, prevTid, nextTid); + if (traceMap.find(prevTid) == traceMap.end()) { + traceMap[prevTid] = {}; + } + traceMap[prevTid].emplace_back(logInfo.lineno); + if (traceMap.find(nextTid) == traceMap.end()) { + traceMap[nextTid] = {}; + } + traceMap[nextTid].emplace_back(logInfo.lineno); + return; + } + static std::string pidStr = "pid="; + if ((logInfo.log.find("sched_wak") != std::string::npos) || + (logInfo.log.find("sched_blocked_reason: ") != std::string::npos)) { + int pidPos = logInfo.log.find(pidStr); + int startStr = pidPos + pidStr.size(); + int tidLen = logInfo.log.find(" ", pidPos) - pidPos - pidStr.size() + 1; + tid = std::stoull(logInfo.log.substr(startStr, tidLen)); + if (traceMap.find(tid) == traceMap.end()) { + traceMap[tid] = {}; + } + traceMap[tid].emplace_back(logInfo.lineno); + return; + } + ParseOtherTraceLogs(LogInfo{logInfo.log, logInfo.lineno, static_cast(pid), tid}, traceMap, ffrtWakeLogs); +} + +static bool IsNumeric(ConStr &str) +{ + bool result = true; + std::for_each(str.begin(), str.end(), [&](char c) { + if (!std::isdigit(c)) { + result = false; + } + }); + return result; +} + +static int GetQid(ConStr &containQid) +{ + size_t oldPos = 0; + size_t newPos = 0; + while ((newPos = containQid.find("_", newPos)) != std::string::npos) { + std::string qidStr = containQid.substr(oldPos, newPos - oldPos); + if (IsNumeric(qidStr)) { + return std::stoull(qidStr); + } + newPos++; + oldPos = newPos; + } + if (oldPos != containQid.size()) { + std::string qidStr = containQid.substr(oldPos, containQid.size() - oldPos); + if (IsNumeric(qidStr)) { + return std::stoull(qidStr); + } + } + return -1; +} + +static std::string GenMockTid(int pid, int gid) +{ + std::string mockTid = std::to_string(pid) + "0" + std::to_string(gid); + while (std::stoull(mockTid) > MAX_MOCK_TID) { + mockTid = mockTid.substr(1); + } + return mockTid; +} + +static std::string MakeCoyieldFakeLog(FakeLogArgs &fakeLogArgs) +{ + std::stringstream ss; + static const int spaceNum = 7; + std::string mockTid = GenMockTid(fakeLogArgs.pid, fakeLogArgs.taskRunning); + ss << " " << fakeLogArgs.taskLabel << "-" << mockTid << " (" << std::setw(spaceNum); + ss << std::right << fakeLogArgs.pid << ") [" << fakeLogArgs.cpuId << "] .... " << fakeLogArgs.timestamp; + ss << ": sched_switch: prev_comm=" << fakeLogArgs.taskLabel << " prev_pid=" << mockTid; + ss << " prev_prio=" << fakeLogArgs.prio << " prev_state=S ==> next_comm=" << fakeLogArgs.tname; + ss << " next_pid=" << fakeLogArgs.tid << " next_prio=" << fakeLogArgs.prio << "\n"; + std::string fakeLog = ss.str(); return fakeLog; } -std::string FfrtConverter::ConvertWorkerLogToTask(const std::string &mark, - const int pid, - const long long gid, - const int tid) + +static std::string MakeCostartFakeLog(FakeLogArgs &fakeLogArgs) +{ + std::string mockTid = GenMockTid(fakeLogArgs.pid, fakeLogArgs.taskRunning); + std::stringstream ss; + static const int spaceNum = 7; + ss << fakeLogArgs.log << "\n " << fakeLogArgs.tname << "-" << fakeLogArgs.tid << " (" << std::setw(spaceNum); + ss << std::right << fakeLogArgs.pid << ") [" << fakeLogArgs.cpuId << "] .... " << fakeLogArgs.timestamp; + ss << ": sched_switch: prev_comm=" << fakeLogArgs.tname << " prev_pid=" << fakeLogArgs.tid << " prev_prio="; + ss << fakeLogArgs.prio << " prev_state=S ==> next_comm=" << fakeLogArgs.taskLabel; + ss << " next_pid=" << mockTid << " next_prio=" << fakeLogArgs.prio << "\n"; + return ss.str(); +} + +static std::string MakeWakeupFakeLog(ConStr &log, const FakeLogArgs &fakeLogArgs, ConStr &tracingMarkerKey) +{ + std::string mockTid = GenMockTid(fakeLogArgs.pid, fakeLogArgs.taskRunning); + std::stringstream fakeLogStrm; + fakeLogStrm << log.substr(0, log.find(tracingMarkerKey)) << "sched_wakeup: comm=" << + fakeLogArgs.taskLabel << " pid=" << mockTid << " prio=" << + fakeLogArgs.prio << " target_cpu=" << fakeLogArgs.cpuId << "\n"; + return fakeLogStrm.str(); +} + +static std::string ReplaceSchedSwitchLog(ConStr &fakeLog, LogInfo logInfo, int gid, ConStr &label) +{ + std::string mockTid = GenMockTid(logInfo.pid, gid); + std::string result = fakeLog; + + if (logInfo.log.find("prev_pid=" + std::to_string(logInfo.tid)) != std::string::npos) { + if (ExtractThreadId(fakeLog) == logInfo.tid) { + size_t index = fakeLog.find("("); + result = " " + label + "-" + mockTid + " " + fakeLog.substr(index); + } + result = result.substr(0, result.find("prev_comm=")) + + "prev_comm=" + label + + " " + result.substr(result.find("prev_pid=")); + result = result.substr(0, result.find("prev_pid=")) + + "prev_pid=" + mockTid + + " " + result.substr(result.find("prev_prio=")); + } else if (logInfo.log.find("next_pid=" + std::to_string(logInfo.tid)) != std::string::npos) { + result = result.substr(0, result.find("next_comm=")) + + "next_comm=" + label + + " " + result.substr(result.find("next_pid=")); + result = result.substr(0, result.find("next_pid=")) + + "next_pid=" + mockTid + + " " + result.substr(result.find("next_prio=")); + } + return result; +} + +static std::string ReplaceSchedWakeLog(ConStr &fakeLog, ConStr &label, int pid, int gid) +{ + std::string result = fakeLog; + result = result.substr(0, result.find("comm=")) + "comm=" + label + " " + result.substr(result.find("pid=")); + // Replace "pid=" part + std::string mockTid = GenMockTid(pid, gid); + result = result.substr(0, result.find("pid=")) + "pid=" + mockTid + " " + result.substr(result.find("prio=")); + return result; +} + +static std::string ReplaceTracingMarkLog(ConStr &fakeLog, ConStr &label, int pid, int gid) +{ + size_t index = fakeLog.find("("); + std::string mockTid = GenMockTid(pid, gid); + std::string result = " " + label + "-" + mockTid + " " + fakeLog.substr(index); + return result; +} + +static std::string ReplaceSchedBlockLog(ConStr &fakeLog, int pid, int gid) +{ + std::string mockTid = GenMockTid(pid, gid); + std::string::size_type pos = fakeLog.find("pid="); + std::string result; + if (pos != std::string::npos) { + pos = fakeLog.find("iowait=", pos); + if (pos != std::string::npos) { + result = fakeLog.substr(0, fakeLog.find("pid=")) + "pid=" + + mockTid + " " + fakeLog.substr(pos); + } else { + result = fakeLog.substr(0, fakeLog.find("pid=")) + "pid=" + + mockTid + " " + fakeLog.substr(fakeLog.find("io_wait=")); + } + } + return result; +} + +static std::string ConvertWorkerLogToTask(ConStr &mark, int pid, int tid, int gid, ConStr &label) { std::string fakeLog = mark; if (mark.find("sched_switch: ") != std::string::npos) { - return ReplaceSchedSwitchLog(fakeLog, mark, pid, gid, tid); + LogInfo logInfo = LogInfo{mark, -1, pid, tid}; + return ReplaceSchedSwitchLog(fakeLog, logInfo, gid, label); } if (mark.find(": sched_wak") != std::string::npos) { - return ReplaceSchedWakeLog(fakeLog, taskLabels_[pid][gid], pid, gid); + if (mark.find("pid=" + std::to_string(tid)) != std::string::npos) { + return ReplaceSchedWakeLog(fakeLog, label, pid, gid); + } else { + return ReplaceTracingMarkLog(fakeLog, label, pid, gid); + } } if (mark.find("sched_blocked_reason: ") != std::string::npos) { return ReplaceSchedBlockLog(fakeLog, pid, gid); } - return ReplaceTracingMarkLog(fakeLog, taskLabels_[pid][gid], pid, gid); + return ReplaceTracingMarkLog(fakeLog, label, pid, gid); } -int FfrtConverter::FindIntNumberAfterStr(const size_t index, const string &str) + +static int FindGreaterThan(const std::vector &vec, int target) { - auto beginPos = context_[index].find(str); - if (beginPos != std::string::npos) { - beginPos = beginPos + str.length(); - auto endPos = context_[index].find_first_of(" ", beginPos); - return stoi(context_[index].substr(beginPos, endPos - beginPos)); + if (vec.size() == 0) { + return 0; } - return -1; + if (target >= vec.back()) { + return vec.size(); + } + auto it = std::lower_bound(vec.begin(), vec.end(), target + 1); + if (it != vec.end() && *it > target) { + return std::distance(vec.begin(), it); + } + return vec.size(); } -std::string FfrtConverter::FindSubStrAfterStr(const size_t index, const string &str) + +static bool HandleQueTaskInfoIn(ConStr &log, int lineno, int pid, QueueTaskInfo &queueTaskInfo) { - auto beginPos = context_[index].find(str) + str.length(); - auto endPos = context_[index].find_first_of(" ", beginPos); - return context_[index].substr(beginPos, endPos - beginPos); + static std::string sqStr = "sq_"; + size_t sqPos = log.find("H:FFRTsq_"); + if (sqPos != std::string::npos) { + size_t sqStart = log.find(sqStr); + std::string containInfo = log.substr(sqStart + sqStr.size()); + size_t firstPipePos = containInfo.find_first_of("|"); + if (firstPipePos != std::string::npos) { + std::string containQid = containInfo.substr(0, firstPipePos); + int qid = GetQid(containQid); + if (qid == -1) { + return true; + } + size_t gidStart = containQid.size() + 1; + int gid = std::stoull(containInfo.substr(gidStart, containInfo.find("|", gidStart) - gidStart)); + if (queueTaskInfo[pid].find(gid) == queueTaskInfo[pid].end()) { + queueTaskInfo[pid][gid] = tidInfo{{lineno}, -1, gid, qid}; + } else { + queueTaskInfo[pid][gid].begin.emplace_back(lineno); + } + } + } + return false; } -void FfrtConverter::ClassifySchedSwitchData(const size_t index, std::unordered_map> &traceMap) + +static void HandleQueTaskInfoOut(ConStr &log, int lineno, int pid, QueueTaskInfo &queueTaskInfo) { - auto prevTid = FindIntNumberAfterStr(index, "prev_pid="); - auto nextTid = FindIntNumberAfterStr(index, "next_pid="); - // update sched_switch prev_pid and next_pid corresponding line number - if (prevTid != -1 && traceMap.count(prevTid) == 0) { - traceMap[prevTid] = std::vector(); + static std::string fStr = " F|"; + size_t fPos = log.find(fStr); + if (fPos == std::string::npos) { + return; } - if (nextTid != -1 && traceMap.count(nextTid) == 0) { - traceMap[nextTid] = std::vector(); + size_t hPos = log.find("|H:F ", fPos); + if (hPos == std::string::npos) { + return; } - traceMap[prevTid].push_back(index); - traceMap[nextTid].push_back(index); - - // Get thread name as ffrtxxx or OS_FFRTxxx - if (context_[index].find("prev_comm=ffrt") != std::string::npos || - context_[index].find("prev_comm=OS_FFRT") != std::string::npos) { - auto pid = ExtractProcessId(index); - if (ffrtPidMap_.count(pid) == 0 || ffrtPidMap_[pid].count(prevTid) == 0) { - ffrtPidMap_[pid][prevTid].name = FindSubStrAfterStr(index, "prev_comm="); + std::string pidStr = log.substr(fPos + fStr.size(), hPos - (fPos + fStr.size())); + if (!pidStr.empty() && std::all_of(pidStr.begin(), pidStr.end(), ::isdigit)) { + int spacePos = hPos + fStr.size() + 1; + while (log[spacePos] == ' ') { + spacePos++; + } + bool spaceFlage = spacePos != std::string::npos && spacePos < log.length(); + if (!spaceFlage) { + return; + } + std::string gidStr = log.substr(spacePos); + if (!gidStr.empty() && std::all_of(gidStr.begin(), gidStr.end(), ::isdigit)) { + int gid = std::stoull(gidStr); + if (queueTaskInfo[pid].find(gid) != queueTaskInfo[pid].end()) { + queueTaskInfo[pid][gid].end = lineno; + } } } - return; } -void FfrtConverter::FindFfrtProcessAndClassify(const size_t index, std::unordered_map> &traceMap) + +void FfrtConverter::ExceQueTaskInfoPreLog(std::vector &linenos, int pid, QueueTaskInfo &queueTaskInfo) { - if (context_[index].find("sched_switch") != std::string::npos) { - ClassifySchedSwitchData(index, traceMap); - return; + for (auto lineno : linenos) { + std::string &log = context_[lineno]; + + if (HandleQueTaskInfoIn(log, lineno, pid, queueTaskInfo)) { + continue; + } + HandleQueTaskInfoOut(log, lineno, pid, queueTaskInfo); } - if (context_[index].find(": sched_wak") != std::string::npos || - (context_[index].find("sched_blocked_reason:") != std::string::npos)) { - auto tid = FindIntNumberAfterStr(index, "pid="); - if (traceMap.find(tid) == traceMap.end()) { - traceMap[tid] = std::vector(); +} + +void FfrtConverter::FindQueueTaskInfo(FfrtPids &ffrtPids, QueueTaskInfo &queueTaskInfo) +{ + for (auto &pidItem : ffrtPids) { + int pid = pidItem.first; + queueTaskInfo[pid] = {}; // Initialize map for this pid + + for (auto &tidItem : pidItem.second) { + std::vector &linenos = tidItem.second.second; + std::sort(linenos.begin(), linenos.end()); + ExceQueTaskInfoPreLog(linenos, pid, queueTaskInfo); } - traceMap[tid].push_back(index); - return; } - static std::smatch match; - if (std::regex_search(context_[index], match, matchPattern_)) { - auto endPos = context_[index].find(match.str()); - std::string res = context_[index].substr(0, endPos); - std::string begin = "-"; - auto beginPos = res.find_last_of(begin); - if (beginPos != std::string::npos) { - beginPos = beginPos + begin.length(); - auto tid = stoi(context_[index].substr(beginPos, endPos - beginPos)); - if (traceMap.find(tid) == traceMap.end()) { - traceMap[tid] = std::vector(); +} + +void GenFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, QueueTaskInfo &queueTaskInfo) +{ + for (auto &pidItem : queueTaskInfo) { + int pid = pidItem.first; + ffrtQueueTasks[pid] = {}; + for (auto &qidItem : pidItem.second) { + std::sort(qidItem.second.begin.begin(), qidItem.second.begin.end()); + int qid = qidItem.second.qid; + if (ffrtQueueTasks[pid].find(qid) == ffrtQueueTasks[pid].end()) { + ffrtQueueTasks[pid][qid] = {}; } - traceMap[tid].push_back(index); + ffrtQueueTasks[pid][qid].push_back(qidItem.second); } } - return; } -std::string FfrtConverter::GetTaskId(int pid, long long gid) +static void GenTaskGroups(std::vector> &taskGroups, std::pair> qidItem) { - stringstream ss; - ss << pid << "0" << gid; - auto str = ss.str(); - while (str.size() > uint32MaxLength_) { - str.erase(0, 1); + for (auto &task : qidItem.second) { + if (task.end == -1) { + taskGroups.push_back({task}); + continue; + } + bool inserted = false; + for (auto &group : taskGroups) { + if (group.back().end != -1 && task.begin[0] > group.back().end) { + group.emplace_back(task); + inserted = true; + break; + } + } + if (!inserted) { + taskGroups.push_back({task}); + } } - auto result = stoll(str); - if (result > INVALID_UINT32) { - str.erase(0, 1); +} + +void FfrtConverter::ExceTaskGroups(std::vector &group, WakeLogs &wakeLogs, int firstGid) +{ + for (int i = 1; i < group.size(); i++) { + if (wakeLogs.find(group[i].gid) != wakeLogs.end()) { + int gid = group[i].gid; + wakeLogs[firstGid].insert(wakeLogs[firstGid].end(), wakeLogs[gid].begin(), wakeLogs[gid].end()); + for (auto& lineno : group[i].begin) { + size_t strLen = context_[lineno].find_last_of("|") + 1; + context_[lineno] = context_[lineno].substr(0, strLen) + std::to_string(firstGid) + "\n"; + } + } } - return str; } -bool FfrtConverter::IsDigit(const std::string &str) +void FfrtConverter::HandleTaskGroups(std::vector> &taskGroups, WakeLogs &wakeLogs) { - auto endPos = str.find_last_not_of(" "); - string newStr = str; - newStr.erase(endPos + 1); - if (newStr.back() == '\r') { - newStr.pop_back(); + for (auto& group : taskGroups) { + if (group.size() > 1) { + int firstGid = group[0].gid; + if (wakeLogs.find(firstGid) == wakeLogs.end()) { + wakeLogs[firstGid] = {}; + } + ExceTaskGroups(group, wakeLogs, firstGid); + std::sort(wakeLogs[firstGid].begin(), wakeLogs[firstGid].end()); + } } - for (int i = 0; i < newStr.length(); i++) { - if (!std::isdigit(newStr[i])) { - return false; +} + +void FfrtConverter::HandleFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, FfrtWakeLogs& ffrtWakeLogs) +{ + for (auto &pidItem : ffrtQueueTasks) { + WakeLogs tmp = {}; + WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) ? + ffrtWakeLogs[pidItem.first] : tmp; + + for (auto &qidItem : pidItem.second) { + auto cmp = [](tidInfo& value1, tidInfo& value2) {return value1.begin[0] < value2.begin[0];}; + std::sort(qidItem.second.begin(), qidItem.second.end(), cmp); + + std::vector> taskGroups; + GenTaskGroups(taskGroups, qidItem); + HandleTaskGroups(taskGroups, wakeLogs); } } - return true; } -void FfrtConverter::ClassifyContextForFfrtWorker() +void FfrtConverter::HandleMarks(ConStr &log, int lineno, int pid) { - std::unordered_map> traceMap; - for (auto index = 0; index < context_.size(); index++) { - FindFfrtProcessAndClassify(index, traceMap); + static std::string lostTracingMark = tracingMarkerKey_ + "?"; + static std::string faultTracingMark = tracingMarkerKey_ + ""; + + size_t lostMarkPos = log.find(lostTracingMark); + size_t faultMarkPos = log.find(faultTracingMark); + size_t tracingMarkerPos = log.find(tracingMarkerKey_); + + if (lostMarkPos != std::string::npos || faultMarkPos != std::string::npos) { + if (tracingMarkerPos != std::string::npos) { + context_[lineno] = log.substr(0, tracingMarkerPos + tracingMarkerKey_.size()) + + "E|" + std::to_string(pid) + "\n"; + } } - for (auto &[pid, threads] : ffrtPidMap_) { - for (const auto &thread : threads) { - auto tid = thread.first; - ffrtPidMap_[pid][tid].indices = traceMap[tid]; +} + +void HandleSchedSwitch(ConStr &mark, int tid, int &prio) +{ + if (mark.find("sched_switch: ") != std::string::npos) { + size_t prevPidPos = mark.find("prev_pid=" + std::to_string(tid)); + size_t nextPidPos = mark.find("next_pid=" + std::to_string(tid)); + if (prevPidPos != std::string::npos || nextPidPos != std::string::npos) { + std::string pidTag = (prevPidPos != std::string::npos) ? "prev_prio=" : "next_prio="; + size_t prioPos = mark.find(pidTag); + if (prioPos != std::string::npos) { + std::string prioStr = mark.substr(prioPos + pidTag.size()); + prio = std::stoull(prioStr.substr(0, prioStr.find(" "))); + } } } } -void FfrtConverter::ConvertFfrtThreadToFfrtTask() + +bool FfrtConverter::HandleFfrtTaskCo(ConStr &log, int lineno, bool &switchInFakeLog, bool &switchOutFakeLog) { - int prio; - for (auto &[pid, threads] : ffrtPidMap_) { - taskLabels_[pid] = {}; - for (auto &[tid, ffrtContent] : ffrtPidMap_[pid]) { - ThreadInfo threadInfo; - threadInfo.pid = pid; - threadInfo.tid = tid; - threadInfo.name = ffrtContent.name; - auto switchInFakeLog = false; - auto switchOutFakeLog = false; - auto ffbkMarkRemove = false; - auto gid = WAKE_EVENT_DEFAULT_VALUE; - for (auto index : ffrtContent.indices) { - ProcessMarkWithSchedSwitch(tid, prio, index); - if (context_[index].find("|FFRT") != std::string::npos || - context_[index].find("|H:FFRT") != std::string::npos) { - if (!ProcessMarkWithFFRT(index, prio, gid, threadInfo)) { - continue; - } - switchInFakeLog = true; - continue; - } - if (gid != WAKE_EVENT_DEFAULT_VALUE) { - if (!DeleteRedundance(switchInFakeLog, switchOutFakeLog, index)) { - continue; - } - static const std::regex EndPattern = std::regex(R"( F\|(\d+)\|[BF]\|(\d+))"); - static const std::regex HEndPattern = std::regex(R"( F\|(\d+)\|H:[BF]\s(\d+))"); - if (std::regex_search(context_[index], EndPattern) || - std::regex_search(context_[index], HEndPattern)) { - context_[index] = MakeEndFakeLog(context_[index], gid, prio, threadInfo); - gid = WAKE_EVENT_DEFAULT_VALUE; - switchOutFakeLog = false; - continue; - } - context_[index] = ConvertWorkerLogToTask(context_[index], pid, gid, tid); - continue; - } + static const std::string fPattern = " F|"; + static const std::string hCo = "|H:Co"; + + size_t fPos = log.find(fPattern); + if (fPos == std::string::npos) { + return false; + } + size_t hCoPos = log.find(hCo, fPos + fPattern.size()); + if (hCoPos != std::string::npos && hCoPos > fPos + fPattern.size()) { + bool valid = true; + std::string numStr = log.substr(fPos + fPattern.size(), hCoPos - fPos - fPattern.size()); + int num = 0; + auto [ptr, ec] = std::from_chars(numStr.data(), numStr.data() + numStr.size(), num); + if (ec != std::errc{}) { + valid = false; + } + + if (!valid) { + return false; + } + size_t afterCo = hCoPos + hCo.size(); + while (afterCo < log.length() && isspace(log[afterCo])) { + ++afterCo; + } + if (afterCo < log.length() && isdigit(log[afterCo])) { + context_[lineno] = "\n"; + if (switchInFakeLog) { + switchInFakeLog = false; + } else { + switchOutFakeLog = true; } + return true; } } + return false; } -void FfrtConverter::ProcessMarkWithSchedSwitch(const int tid, int &prio, const size_t index) + +static bool IsFfrtTaskBlockOrFinish(ConStr &log) { - if (context_[index].find("sched_switch:") != std::string::npos) { - if (context_[index].find("prev_pid=" + std::to_string(tid) + " ") != std::string::npos) { - static std::string beginPprio = "prev_prio="; - auto beginPos = context_[index].find(beginPprio); - if (beginPos != std::string::npos) { - beginPos = beginPos + beginPprio.length(); - auto endPos = context_[index].find_first_of(" ", beginPos); - prio = stoi(context_[index].substr(beginPos, endPos - beginPos)); + static const std::string fStr = " F|"; + int fPos = log.find(fStr); + if (fPos == std::string::npos) { + return false; + } + size_t hPos = log.find("|H:", fPos); + if (hPos != std::string::npos) { + size_t typePos = hPos + fStr.size(); + if (typePos < log.length() && + (log[typePos] == 'F' || log[typePos] == 'B')) { + int spacePos = typePos + 1; + while (spacePos < log.length() && isspace(log[spacePos])) { + ++spacePos; } - } else if (context_[index].find("next_pid=" + std::to_string(tid)) != std::string::npos) { - static std::string beginNprio = "next_prio="; - auto beginPos = context_[index].find(beginNprio); - if (beginPos != std::string::npos) { - beginPos = beginPos + beginNprio.length(); - prio = stoi(context_[index].substr(beginPos)); + + if (spacePos < log.length() && isdigit(log[spacePos])) { + return true; } } } + return false; } -std::string FfrtConverter::GetLabel(const string &line) + +bool FfrtConverter::HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wakeLogs, + TaskLabels &taskLabels, std::string &label) { - std::string label; - if (line.find("|H:FFRT") != std::string::npos) { - if (line.find("H:FFRT::") != std::string::npos) { - auto beginPos = line.rfind("["); - auto endPos = line.rfind("]"); - if (beginPos != std::string::npos && endPos != std::string::npos) { - label = line.substr(beginPos + 1, endPos - beginPos - 1); + static const int spaceNum = 7; + if (fakLogArg.log.find("|H:FFRT") != std::string::npos) { + std::string missLog; + if (fakLogArg.taskRunning != -1) { + missLog = MakeCoyieldFakeLog(fakLogArg); + std::stringstream ss; + ss << " " << fakLogArg.tname << "-" << fakLogArg.tid << " (" << + std::setw(spaceNum) << std::right << fakLogArg.pid << ") [" << + fakLogArg.cpuId << "] .... " << fakLogArg.timestamp << + ": " << tracingMarkerKey_ << "E|" << fakLogArg.pid << "\n"; + missLog += ss.str(); + } + if (label.find("ex_task") != std::string::npos) { return true; } + int gid = -1; + size_t pos = fakLogArg.log.find_last_of('|'); + if (pos != std::string::npos) { + if (pos + 1 >= fakLogArg.log.size()) { + return true; } - } else { - static std::string indexHFfrt = "|H:FFRT"; - auto beginPos = line.find(indexHFfrt); - beginPos = beginPos + indexHFfrt.length(); - auto endPos = line.find_first_of("|", beginPos); - if (endPos != std::string::npos) { - label = line.substr(beginPos, endPos - beginPos); + std::string gidStr = fakLogArg.log.substr(pos + 1); + auto [ptr, ec] = std::from_chars(gidStr.data(), gidStr.data() + gidStr.size(), gid); + if (ec != std::errc{}) { + return true; } } - } else { - if (line.find("|FFRT::") != std::string::npos) { - auto beginPos = line.rfind("["); - auto endPos = line.rfind("]"); - if (beginPos != std::string::npos && endPos != std::string::npos) { - label = line.substr(beginPos + 1, endPos - beginPos - 1); + if (taskLabels[fakLogArg.pid].find(gid) == taskLabels[fakLogArg.pid].end()) { + taskLabels[fakLogArg.pid][gid] = label; + } + fakLogArg.taskRunning = gid; + fakLogArg.taskLabel = taskLabels[fakLogArg.pid][fakLogArg.taskRunning]; + std::string fakeLog = MakeCostartFakeLog(fakLogArg); + context_[fakLogArg.lineno] = fakeLog; + if (!missLog.empty()) { + context_[fakLogArg.lineno] = missLog + context_[fakLogArg.lineno]; + } + fakLogArg.switchInFakeLog = true; + fakLogArg.switchOutFakeLog = false; + if (wakeLogs.find(fakLogArg.taskRunning) != wakeLogs.end()) { + int prevIndex = FindGreaterThan(wakeLogs[fakLogArg.taskRunning], fakLogArg.lineno); + if (prevIndex > 0) { + int linenoWake = wakeLogs[fakLogArg.taskRunning][prevIndex - 1]; + context_[linenoWake] = MakeWakeupFakeLog(context_[linenoWake], fakLogArg, tracingMarkerKey_); } - } else { - static std::string indexFfrt = "|FFRT"; - auto beginPos = line.find(indexFfrt); - beginPos = beginPos + indexFfrt.length(); - auto endPos = line.find_first_of("|", beginPos); - if (endPos != std::string::npos) { - label = line.substr(beginPos, endPos - beginPos); + } + return true; + } + return false; +} + +bool FfrtConverter::HandlePreLineno(FakeLogArgs &fakArg, WakeLogs &wakeLogs, + TaskLabels &taskLabels, ConStr traceBeginMark, ConStr traceEndMark) +{ + std::string label = ExtractTaskLable(fakArg.log); + if (HandleFfrtTaskExecute(fakArg, wakeLogs, taskLabels, label)) { + return true; + } + if (fakArg.taskRunning != -1) { + if (HandleFfrtTaskCo(fakArg.log, fakArg.lineno, fakArg.switchInFakeLog, fakArg.switchOutFakeLog)) { + return true; + } + if (fakArg.switchInFakeLog && (fakArg.log.find(traceBeginMark) != std::string::npos)) { + context_[fakArg.lineno] = "\n"; + return true; + } + if (fakArg.switchOutFakeLog && (fakArg.log.find(traceEndMark) != std::string::npos)) { + context_[fakArg.lineno] = "\n"; + return true; + } + if (IsFfrtTaskBlockOrFinish(fakArg.log)) { + std::string fakeLog = MakeCoyieldFakeLog(fakArg); + context_[fakArg.lineno] = fakeLog; + if (fakArg.switchOutFakeLog) { + fakArg.switchOutFakeLog = false; } + fakArg.taskRunning = -1; + return true; } + label = taskLabels[fakArg.pid][fakArg.taskRunning]; + std::string fakeLog = ConvertWorkerLogToTask(fakArg.log, fakArg.pid, fakArg.tid, fakArg.taskRunning, label); + context_[fakArg.lineno] = fakeLog; + return true; } - return label; + return false; } -bool FfrtConverter::ProcessMarkWithFFRT(const int index, int &prio, int32_t &gid, const ThreadInfo &threadInfo) + +void FfrtConverter::ExceTaskLabelOhos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, std::string traceBeginMark, + std::string traceEndMark) { - auto line = context_[index]; - auto label = GetLabel(line); - if (label.find("executor_task") != std::string::npos || label.find("ex_task") != std::string::npos) { + taskLabels[pidItem.first] = {}; + WakeLogs tmp = {}; + WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) + ? ffrtWakeLogs[pidItem.first] : tmp; + + for (auto &tidItem : pidItem.second) { + std::string tname = tidItem.second.first; + std::vector linenos = tidItem.second.second; + int prio = 120; + + bool switchInFakeLog = false; + bool switchOutFakeLog = false; + int taskRunning = -1; + + for (auto lineno : linenos) { + std::string &log = context_[lineno]; + HandleMarks(log, lineno, pidItem.first); + HandleSchedSwitch(log, tidItem.first, prio); + + std::string cpuId = ExtractCpuId(log); + std::string timestamp = ExtractTimeStr(log); + FakeLogArgs fakArg{pidItem.first, tidItem.first, taskRunning, prio, lineno, + switchInFakeLog, switchOutFakeLog, log, tname, + taskLabels[pidItem.first][taskRunning], cpuId, timestamp}; + HandlePreLineno(fakArg, wakeLogs, taskLabels, traceBeginMark, traceEndMark); + } + } +} + +void FfrtConverter::GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs, TaskLabels &taskLabels) +{ + static std::string traceBeginMark = tracingMarkerKey_ + "B"; + static std::string traceEndMark = tracingMarkerKey_ + "E"; + for (auto &pidItem : ffrtPids) { + ExceTaskLabelOhos(taskLabels, ffrtWakeLogs, pidItem, traceBeginMark, traceEndMark); + } +} + +void FfrtConverter::ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs) +{ + QueueTaskInfo queueTaskInfo; + FindQueueTaskInfo(ffrtPids, queueTaskInfo); + + FfrtQueueTasks ffrtQueueTasks; + GenFfrtQueueTasks(ffrtQueueTasks, queueTaskInfo); + HandleFfrtQueueTasks(ffrtQueueTasks, ffrtWakeLogs); + + TaskLabels taskLabels; + taskLabels.reserve(ffrtPids.size()); + GenTaskLabelsOhos(ffrtPids, ffrtWakeLogs, taskLabels); +} + +bool FfrtConverter::HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, WakeLogs &wakeLogs, TaskLabels &taskLabels, + std::string label, std::unordered_map &schedWakeFlag) +{ + static const int spaceNum = 7; + if (fakeArgs.log.find("|FFRT") == std::string::npos) { return false; } std::string missLog; - if (gid != WAKE_EVENT_DEFAULT_VALUE) { - missLog = MakeEndFakeLog(line, gid, prio, threadInfo); - auto timestamp = ExtractTimeStr(line); - auto cpuId = ExtractCpuId(line); - std::unique_ptr result = std::make_unique(MAX_LEN); - (void)sprintf_s(result.get(), MAX_LEN, " %s-%d (%7d) [%s] .... %s: %sE|%d\n", threadInfo.name.c_str(), - threadInfo.tid, threadInfo.pid, cpuId.c_str(), timestamp.c_str(), tracingMarkerKey_.c_str(), - threadInfo.pid); - missLog = missLog + result.get(); - memset_s(result.get(), MAX_LEN, 0, MAX_LEN); - } - auto beginPos = line.rfind("|"); - if (beginPos == std::string::npos || !IsDigit(line.substr(beginPos + 1))) { - return false; + if (fakeArgs.taskRunning != -1) { + missLog = MakeCoyieldFakeLog(fakeArgs); + std::stringstream ss; + ss << " " << fakeArgs.tname << "-" << fakeArgs.tid << " (" << + std::setw(spaceNum) << std::right << fakeArgs.pid << ") [" << + fakeArgs.cpuId << "] .... " << fakeArgs.timestamp << ": " << + tracingMarkerKey_ << "E|" << fakeArgs.pid << "\n"; + missLog += ss.str(); } - gid = stoll(line.substr(beginPos + 1)); - if (taskLabels_[threadInfo.pid].count(gid) == 0) { - taskLabels_[threadInfo.pid][gid] = label; + if (label.find("executor_task") != std::string::npos) { return true; } + int gid = -1; + size_t pos = fakeArgs.log.find_last_of('|'); + if (pos != std::string::npos) { + if (pos + 1 >= fakeArgs.log.size()) { return true; } + std::string gidStr = fakeArgs.log.substr(pos + 1); + auto [ptr, ec] = std::from_chars(gidStr.data(), gidStr.data() + gidStr.size(), gid); + if (ec != std::errc{}) { return true; } } - context_[index] = MakeBeginFakeLog(line, gid, prio, threadInfo); + if (taskLabels[fakeArgs.pid].find(gid) == taskLabels[fakeArgs.pid].end()) { + taskLabels[fakeArgs.pid][gid] = label; + } + fakeArgs.taskRunning = gid; + FakeLogArgs fakArg2{fakeArgs.pid, fakeArgs.tid, fakeArgs.taskRunning, fakeArgs.prio, fakeArgs.lineno, + fakeArgs.switchInFakeLog, fakeArgs.switchOutFakeLog, fakeArgs.log, fakeArgs.tname, + taskLabels[fakeArgs.pid][fakeArgs.taskRunning], fakeArgs.cpuId, fakeArgs.timestamp}; + std::string fakeLog = MakeCostartFakeLog(fakArg2); + context_[fakeArgs.lineno] = fakeLog; if (!missLog.empty()) { - context_[index] = missLog + context_[index]; + context_[fakeArgs.lineno] = missLog + context_[fakeArgs.lineno]; + } + FakeLogArgs fakArg3{fakeArgs.pid, fakeArgs.tid, fakeArgs.taskRunning, fakeArgs.prio, fakeArgs.lineno, + fakeArgs.switchInFakeLog, fakeArgs.switchOutFakeLog, fakeArgs.log, fakeArgs.tname, + taskLabels[fakeArgs.pid][fakeArgs.taskRunning], fakeArgs.cpuId, fakeArgs.timestamp}; + if (wakeLogs.find(fakeArgs.taskRunning) != wakeLogs.end()) { + int prevIndex = FindGreaterThan(wakeLogs[fakeArgs.taskRunning], fakeArgs.lineno); + if (prevIndex > 0) { + int linenoWake = wakeLogs[fakeArgs.taskRunning][prevIndex - 1]; + if (schedWakeFlag.find(linenoWake) == schedWakeFlag.end()) { + context_[linenoWake] = MakeWakeupFakeLog(context_[linenoWake], fakArg3, tracingMarkerKey_); + schedWakeFlag[linenoWake] = 0; + } + } } return true; } -bool FfrtConverter::DeleteRedundance(bool &switchInFakeLog, bool &switchOutFakeLog, const int index) + +static bool IsFfrtTaskBlockOrFinishNohos(ConStr &log) { - static const std::regex CoPattern = std::regex(R"( F\|(\d+)\|Co\|(\d+))"); - static const std::regex HCoPattern = std::regex(R"( F\|(\d+)\|H:Co\s(\d+))"); - if (std::regex_search(context_[index], CoPattern) || std::regex_search(context_[index], HCoPattern)) { - context_[index].clear(); - if (switchInFakeLog) { - switchInFakeLog = false; - return false; - } else { - switchOutFakeLog = true; - return false; + static const std::string fStr = " F|"; + size_t fPos = log.find(fStr); + if (fPos == std::string::npos) { return false; } + size_t firstNumberEndPos = log.find('|', fPos + fStr.size()); + if (firstNumberEndPos == std::string::npos) { return false; } + std::string firstNumber = log.substr(fPos + 3, firstNumberEndPos - (fPos + fStr.size())); + bool isValidNumber = true; + for (char c : firstNumber) { + if (!std::isdigit(c)) { + isValidNumber = false; + break; } } - if (switchInFakeLog && (context_[index].find(tracingMarkerKey_ + "B") != std::string::npos)) { - context_[index].clear(); - return false; + if (!isValidNumber) { return false; } + size_t typePos = firstNumberEndPos + 1; + if (typePos < log.length() && (log[typePos] == 'B' || log[typePos] == 'F')) { + size_t thirdPipePos = log.find('|', typePos + 1); + if (thirdPipePos != std::string::npos) { + size_t secondNumberPos = thirdPipePos + 1; + if (secondNumberPos < log.length() && std::isdigit(log[secondNumberPos])) { + return true; + } + } } - if (switchOutFakeLog && (context_[index].find(tracingMarkerKey_ + "E") != std::string::npos)) { - context_[index].clear(); - return false; + return false; +} + +bool FfrtConverter::HandlePreLinenoNohos(FakeLogArgs &fakArg, WakeLogs &wakeLogs, + TaskLabels &taskLabels, std::unordered_map &schedWakeFlag) +{ + std::string label = ExtractTaskLable(fakArg.log); + if (HandleHFfrtTaskExecute(fakArg, wakeLogs, taskLabels, label, schedWakeFlag)) { + return true; + } + if (fakArg.taskRunning != -1) { + if (IsFfrtTaskBlockOrFinishNohos(fakArg.log)) { + std::string fakeLog = MakeCoyieldFakeLog(fakArg); + context_[fakArg.lineno] = fakeLog; + fakArg.taskRunning = -1; + return true; + } + label = taskLabels[fakArg.pid][fakArg.taskRunning]; + std::string fakeLog = ConvertWorkerLogToTask(fakArg.log, fakArg.pid, fakArg.tid, fakArg.taskRunning, label); + context_[fakArg.lineno] = fakeLog; + return true; + } + return false; +} +void FfrtConverter::ExceTaskLabelNohos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, std::unordered_map &schedWakeFlag) +{ + bool oneF = false; + bool twoF = false; + taskLabels[pidItem.first] = {}; + WakeLogs tmp = {}; + WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) + ? ffrtWakeLogs[pidItem.first] : tmp; + + for (auto& tidItem : pidItem.second) { + std::string tname = tidItem.second.first; + std::vector linenos = tidItem.second.second; + int prio = 120; + int taskRunning = -1; + + for (auto lineno : linenos) { + std::string& log = context_[lineno]; + + HandleMarks(log, lineno, pidItem.first); + HandleSchedSwitch(log, tidItem.first, prio); + + std::string cpuId = ExtractCpuId(log); + std::string timestamp = ExtractTimeStr(log); + std::string label = ExtractTaskLable(log); + + FakeLogArgs fakArg{pidItem.first, tidItem.first, taskRunning, prio, lineno, + oneF, twoF, log, tname, + taskLabels[pidItem.first][taskRunning], cpuId, timestamp}; + HandlePreLinenoNohos(fakArg, wakeLogs, taskLabels, schedWakeFlag); + } + } +} + +void FfrtConverter::ConvertFrrtThreadToFfrtTaskNohos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs) +{ + TaskLabels taskLabels; + std::unordered_map schedWakeFlag; + taskLabels.reserve(ffrtPids.size()); + schedWakeFlag.reserve(ffrtWakeLogs.size()); + + for (auto &pidItem : ffrtPids) { + ExceTaskLabelNohos(taskLabels, ffrtWakeLogs, pidItem, schedWakeFlag); } - return true; } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/rpc/ffrt_converter.h b/trace_streamer/src/rpc/ffrt_converter.h index c45ef9246f85ecaa3f8e3a92001a8fdd7a765b4d..9eb76cf8462cd7329134c20788faaceb0079d71d 100644 --- a/trace_streamer/src/rpc/ffrt_converter.h +++ b/trace_streamer/src/rpc/ffrt_converter.h @@ -14,94 +14,120 @@ */ #ifndef FFRT_CONVERTER_H #define FFRT_CONVERTER_H -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include #include "ts_common.h" namespace SysTuning { namespace TraceStreamer { -using namespace std; -constexpr int32_t WAKE_EVENT_DEFAULT_VALUE = -1; -constexpr int32_t STR_LEGH = 2; -constexpr int32_t STR_LEN = 8; -constexpr int32_t MAX_LEN = 256; -struct FfrtContent { - std::string name; - std::vector indices; + + using ConStr = const std::string; + +struct tidInfo { + std::vector begin; + int end; + int gid; + int qid; }; -struct WakeEvent { - std::string state = "none"; - int prevWakLine = WAKE_EVENT_DEFAULT_VALUE; - std::string prevWakeLog; + +using PidMap = std::unordered_map>; +using FfrtTidMap = std::unordered_map>>; +using FfrtPids = std::unordered_map; +using WakeLogs = std::unordered_map>; +using FfrtWakeLogs = std::unordered_map; +using QueueTaskInfo = std::unordered_map>; +using FfrtQueueTasks = std::unordered_map>>; +using TaskLabels = std::unordered_map>; + +struct LogInfo { + ConStr &log; + int lineno; + int pid; + int tid; + LogInfo(ConStr &log, int lineno, int pid, int tid) : log(log), lineno(lineno), pid(pid), tid(tid) {} }; -struct ThreadInfo { + +struct FakeLogArgs { int pid; int tid; - std::string name; + int &taskRunning; + int prio; + int lineno; + bool &switchInFakeLog; + bool &switchOutFakeLog; + std::string &log; + std::string &tname; + std::string &taskLabel; + std::string &cpuId; + std::string ×tamp; }; + +struct ContextUpdate { + size_t position; + std::vector new_logs; +}; + class FfrtConverter { public: FfrtConverter() = default; ~FfrtConverter() = default; - bool RecoverTraceAndGenerateNewFile(const std::string &ffrtFileName, std::ofstream &outFile); -private: - void Clear(); - using TypeFfrtPid = std::unordered_map>; - int ExtractProcessId(const size_t index); - std::string ExtractTimeStr(const std::string &log); - std::string ExtractCpuId(const std::string &log); - void ClassifyContextForFfrtWorker(); - void FindFfrtProcessAndClassify(const size_t index, std::unordered_map> &traceMap); - void ClassifySchedSwitchData(const size_t index, std::unordered_map> &traceMap); - int FindIntNumberAfterStr(const size_t index, const string &str); - std::string FindSubStrAfterStr(const size_t index, const string &str); - std::string GetLabel(const std::string &line); - void ConvertFfrtThreadToFfrtTask(); - void ProcessMarkWithSchedSwitch(const int tid, int &prio, const size_t index); - bool ProcessMarkWithFFRT(const int index, int &prio, int32_t &gid, const ThreadInfo &threadInfo); - bool DeleteRedundance(bool &switchInFakeLog, bool &switchOutFakeLog, const int index); - std::string MakeBeginFakeLog(const std::string &mark, - const long long gid, - const int prio, - const ThreadInfo &threadInfo); - std::string MakeEndFakeLog(const std::string &mark, - const long long gid, - const int prio, - const ThreadInfo &threadInfo); - std::string ReplaceSchedSwitchLog(std::string &fakeLog, - const std::string &mark, - const int pid, - const long long gid, - const int tid); - std::string ReplaceSchedWakeLog(std::string &fakeLog, const std::string &label, const int pid, const long long gid); - std::string ReplaceSchedBlockLog(std::string &fakeLog, const int pid, const long long gid); - std::string ReplaceTracingMarkLog(std::string &fakeLog, - const std::string &label, - const int pid, - const long long gid); - std::string ConvertWorkerLogToTask(const std::string &mark, const int pid, const long long gid, const int tid); - std::string GetTaskId(int pid, long long gid); - bool IsDigit(const std::string &str); - void InitTracingMarkerKey(); + bool RecoverTraceAndGenerateNewFile(ConStr &ffrtFileName, std::ofstream &outFile); private: - const std::regex indexPattern_ = std::regex(R"(\(.+\)\s+\[\d)"); - const std::regex matchPattern_ = std::regex(R"( \(.+\)\s+\[\d)"); - const int uint32MaxLength_ = 10; - std::string tracingMarkerKey_ = "tracing_mark_write: "; + + void SetOSPlatformKey(const std::unordered_map>> &ffrt_tid_map); + void FindFfrtProcClassifyLogs(LogInfo logInfo, WakeLogs &traceMap, PidMap &pidMap, + FfrtTidMap &ffrtTidMap, FfrtWakeLogs &ffrtWakeLogs); + void ClassifyLogsForFfrtWorker(FfrtPids &ffrt_pids, FfrtWakeLogs &ffrt_wake_logs); + + void ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs); + void ConvertFrrtThreadToFfrtTaskNohos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs); + + // trace content std::vector context_ = {}; - TypeFfrtPid ffrtPidMap_ = {}; - std::unordered_map> taskLabels_ = {}; + std::string tracingMarkerKey_; + std::string osPlatformKet_ = "ohos"; + + void FindQueueTaskInfo(FfrtPids &ffrtPids, QueueTaskInfo &queueTaskInfo); + + void HandleFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, FfrtWakeLogs& ffrtWakeLogs); + + void HandleMarks(ConStr &log, int lineno, int pid); + + bool HandleFfrtTaskCo(ConStr &log, int lineno, bool &switchInFakeLog, bool &switchOutFakeLog); + + bool HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wakeLogs, + TaskLabels &taskLabels, std::string &label); + + void GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs, TaskLabels &taskLabels); + + bool HandlePreLineno(FakeLogArgs &fakArg, WakeLogs &wakeLogs, + TaskLabels &taskLabels, ConStr traceBeginMark, ConStr traceEndMark); + + void SetTracingMarkerKey(LogInfo logInfo); + + void ExceQueTaskInfoPreLog(std::vector &linenos, int pid, QueueTaskInfo &queueTaskInfo); + + void ExceTaskGroups(std::vector &group, WakeLogs &wakeLogs, int firstGid); + + void HandleTaskGroups(std::vector> &taskGroups, WakeLogs &wakeLogs); + + void ExceTaskLabelOhos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, std::pair pidItem, + std::string traceBeginMark, std::string traceEndMark); + + bool HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, WakeLogs &wakeLogs, TaskLabels &taskLabels, + std::string label, std::unordered_map &schedWakeFlag); + + bool HandlePreLinenoNohos(FakeLogArgs &fakArg, WakeLogs &wakeLogs, + TaskLabels &taskLabels, std::unordered_map &schedWakeFlag); + + void ExceTaskLabelNohos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, std::unordered_map &schedWakeFlag); }; } // namespace TraceStreamer } // namespace SysTuning -#endif // FFRT_CONVERTER_H +#endif // FFRT_CONVERTER_H \ No newline at end of file diff --git a/trace_streamer/src/rpc/rpc_server.cpp b/trace_streamer/src/rpc/rpc_server.cpp index 396aa27c469337c4f14f411d2a06928757fdd25f..ec7bcab88a8404e0e174cd10716987e00f2cc3dc 100644 --- a/trace_streamer/src/rpc/rpc_server.cpp +++ b/trace_streamer/src/rpc/rpc_server.cpp @@ -724,7 +724,7 @@ bool RpcServer::WriteToFile(const std::string &fileName, const uint8_t *data, si return false; } -bool RpcServer::ClearPathFile(string &symbolsPath, int32_t finish, ParseELFFileCallBack &parseELFFile) +bool RpcServer::ClearPathFile(std::string &symbolsPath, int32_t finish, ParseELFFileCallBack &parseELFFile) { if (finish) { if (!ts_->ReloadSymbolFiles(symbolsPath, symbolsPathFiles_)) { diff --git a/trace_streamer/src/rpc/rpc_server.h b/trace_streamer/src/rpc/rpc_server.h index dcba5d4227cbe578045ad031325e67356ba68b5f..0a9f2a9356788940279f825ab88b515a729af23e 100644 --- a/trace_streamer/src/rpc/rpc_server.h +++ b/trace_streamer/src/rpc/rpc_server.h @@ -85,7 +85,7 @@ public: bool SendConvertedFfrtFile(const std::string &fileName, ResultCallBack resultCallBack); void CreateFilePath(const std::string &filePath); bool WriteToFile(const std::string &fileName, const uint8_t *data, size_t len); - bool ClearPathFile(string &symbolsPath, int32_t finish, ParseELFFileCallBack &parseELFFile); + bool ClearPathFile(std::string &symbolsPath, int32_t finish, ParseELFFileCallBack &parseELFFile); bool DownloadELFCallback(const std::string &fileName, size_t totalLen, const uint8_t *data,