1134 lines
46 KiB
Diff
1134 lines
46 KiB
Diff
From 96c61b8356e328fa7f44902b6760e5abfb6320c7 Mon Sep 17 00:00:00 2001
|
|
From: LHesperus <2639350497@qq.com>
|
|
Date: Sat, 2 Dec 2023 19:42:43 +0800
|
|
Subject: [PATCH] restrict function, redesign trace check proc
|
|
|
|
---
|
|
extra-tools/da-tool/analysis/config.cpp | 1 +
|
|
extra-tools/da-tool/analysis/config.h | 1 +
|
|
extra-tools/da-tool/analysis/function_stack.h | 3 +-
|
|
.../da-tool/analysis/sched_analysis.cpp | 139 +++++++----
|
|
extra-tools/da-tool/analysis/sched_analysis.h | 34 ++-
|
|
extra-tools/da-tool/analysis/time_pair.cpp | 97 +++++---
|
|
extra-tools/da-tool/analysis/time_pair.h | 18 +-
|
|
.../da-tool/analysis/trace_resolve.cpp | 233 ++++++++++++++----
|
|
extra-tools/da-tool/analysis/trace_resolve.h | 50 +++-
|
|
extra-tools/da-tool/main.cpp | 1 -
|
|
extra-tools/da-tool/script/da-tool.sh | 54 ++--
|
|
11 files changed, 450 insertions(+), 181 deletions(-)
|
|
|
|
diff --git a/extra-tools/da-tool/analysis/config.cpp b/extra-tools/da-tool/analysis/config.cpp
|
|
index d84cc5b..23eee95 100644
|
|
--- a/extra-tools/da-tool/analysis/config.cpp
|
|
+++ b/extra-tools/da-tool/analysis/config.cpp
|
|
@@ -47,6 +47,7 @@ void Config::pathInit()
|
|
filename[FILE_TYPE_OUTPUT_RUN_LOG] = pathOutputDebug + "/run.log";
|
|
filename[FILE_TYPE_DEBUG_TIME_PAIE] = pathOutputDebug + "/debug_time_pair";
|
|
filename[FILE_TYPE_DEBUG_TRACE] = pathOutputDebug + "/debug_trace";
|
|
+ filename[FILE_TYPE_DEBUG_TRACE_FUNCPAIRMAP] = pathOutputDebug + "/debug_trace_funcpair";
|
|
filename[FILE_TYPE_DEBUG_FUNC_STACK_TRACE] = pathOutputDebug + "/debug_funcstk_trace";
|
|
filename[FILE_TYPE_DEBUG_REGEX] = pathOutputDebug + "/debug_resolve_function_trace";
|
|
filename[FILE_TYPE_DEBUG_CONFIG] = pathOutputDebug + "/debug_config_resolve";
|
|
diff --git a/extra-tools/da-tool/analysis/config.h b/extra-tools/da-tool/analysis/config.h
|
|
index e1a5d4a..bbf339e 100644
|
|
--- a/extra-tools/da-tool/analysis/config.h
|
|
+++ b/extra-tools/da-tool/analysis/config.h
|
|
@@ -33,6 +33,7 @@ typedef enum {
|
|
FILE_TYPE_DEBUG_CONFIG,
|
|
FILE_TYPE_DEBUG_TIME_PAIR_MARK,
|
|
// debug 2
|
|
+ FILE_TYPE_DEBUG_TRACE_FUNCPAIRMAP,
|
|
// debug 3
|
|
FILE_TYPE_DEBUG_TRACE,
|
|
FILE_TYPE_DEBUG_REGEX,
|
|
diff --git a/extra-tools/da-tool/analysis/function_stack.h b/extra-tools/da-tool/analysis/function_stack.h
|
|
index 9f6e2d7..1306cbc 100644
|
|
--- a/extra-tools/da-tool/analysis/function_stack.h
|
|
+++ b/extra-tools/da-tool/analysis/function_stack.h
|
|
@@ -27,8 +27,7 @@ typedef enum {
|
|
FS_DELAY_TYPE_MAX,
|
|
} FS_DELAY_TYPE;
|
|
|
|
-class FsDelayInfo // function stack delay info
|
|
-{
|
|
+class FsDelayInfo { // function stack delay info
|
|
public:
|
|
std::vector<int> delay[FS_DELAY_TYPE_MAX];
|
|
std::vector<uintptr_t> retVal;
|
|
diff --git a/extra-tools/da-tool/analysis/sched_analysis.cpp b/extra-tools/da-tool/analysis/sched_analysis.cpp
|
|
index aea3d25..9aef4b7 100644
|
|
--- a/extra-tools/da-tool/analysis/sched_analysis.cpp
|
|
+++ b/extra-tools/da-tool/analysis/sched_analysis.cpp
|
|
@@ -24,9 +24,9 @@ SchedAnalysis::SchedAnalysis()
|
|
|
|
}
|
|
|
|
-void SchedAnalysis::processSchedAnalysisLoop(const int &pid, const int ×tamp, const int &coreIndex)
|
|
+void SchedAnalysis::processSchedAnalysisLoop(const int &pid, const int ×tamp, const int &coreIndex, const bool &isRet)
|
|
{
|
|
- if (processSchedMap.count(pid) != 0) {
|
|
+ if (processSchedMap.count(pid) == 0) {
|
|
ProcessSchedInfo tmp;
|
|
processSchedMap.emplace(pid, tmp);
|
|
}
|
|
@@ -34,9 +34,16 @@ void SchedAnalysis::processSchedAnalysisLoop(const int &pid, const int ×tam
|
|
ProcessCoreTrace pct;
|
|
pct.startTime = timestamp;
|
|
pct.endTime = timestamp;
|
|
- pct.coreIndex = coreIndex;
|
|
- if (size != 0) {
|
|
+ pct.startCoreId = coreIndex;
|
|
+ pct.endCoreId = coreIndex;
|
|
+ pct.startIsRet = isRet;
|
|
+ pct.endIsRet = isRet;
|
|
+ pct.coreTraceType = CORE_TRACE_INVALID;
|
|
+
|
|
+ if (size > 0) {
|
|
processSchedMap[pid].coreTrace[size - 1].endTime = timestamp;
|
|
+ processSchedMap[pid].coreTrace[size - 1].endCoreId = coreIndex;
|
|
+ processSchedMap[pid].coreTrace[size - 1].endIsRet = isRet;
|
|
}
|
|
processSchedMap[pid].coreTrace.emplace_back(pct);
|
|
}
|
|
@@ -65,45 +72,75 @@ void SchedAnalysis::schedInfoProc()
|
|
|
|
if (functionIndex == sched_switch_funcidx) {
|
|
int nextPid = line_info_tmp.schedSwitchLine.nextPid;
|
|
- processSchedAnalysisLoop(pid, timestamp, -1); // pid1 - > pidn
|
|
- processSchedAnalysisLoop(nextPid, timestamp, coreIndex); // pidm - > pid1
|
|
+ processSchedAnalysisLoop(pid, timestamp, coreIndex, false); // pid1 - > pidn
|
|
+ processSchedAnalysisLoop(nextPid, timestamp, coreIndex, true); // pidm - > pid1
|
|
+ }
|
|
+ }
|
|
+ // last coreTrace always invalid
|
|
+ for (auto &sched_tmp : processSchedMap) {
|
|
+ if (!sched_tmp.second.coreTrace.empty()) {
|
|
+ sched_tmp.second.coreTrace.pop_back();
|
|
}
|
|
}
|
|
}
|
|
|
|
-void SchedAnalysis::schedInfoAnalysis()
|
|
+void SchedAnalysis::schedInfoVaildMark()
|
|
{
|
|
for (auto &sched_tmp : processSchedMap) {
|
|
- int lastCoreIndex = -1;
|
|
- int delaySum = 0;
|
|
- int delaySched = 0;
|
|
- int schedSwitchTimes = 0;
|
|
- int cpuSwitchTimes = 0;
|
|
for (auto &coreTrace : sched_tmp.second.coreTrace) {
|
|
- int delay = coreTrace.endTime - coreTrace.startTime;
|
|
- int coreIndex = coreTrace.coreIndex;
|
|
- delaySum += delay;
|
|
- if (coreIndex == -1) {
|
|
- delaySched += delay;
|
|
- schedSwitchTimes++;
|
|
- } else {
|
|
- sched_tmp.second.runTimeOfCore[coreIndex] += delay;
|
|
+ if (!coreTrace.startIsRet && coreTrace.endIsRet) {
|
|
+ coreTrace.coreTraceType = CORE_TRACE_SCHEDULING;
|
|
}
|
|
|
|
- if (lastCoreIndex == -1 && coreIndex != -1) {
|
|
- lastCoreIndex = coreIndex;
|
|
+ if (coreTrace.startIsRet && !coreTrace.endIsRet && (coreTrace.startCoreId == coreTrace.endCoreId)) {
|
|
+ coreTrace.coreTraceType = CORE_TRACE_ONCORE;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+void SchedAnalysis::schedInfoAnalysis()
|
|
+{
|
|
+ for (auto &sched_tmp : processSchedMap) {
|
|
+ int delaySum[SCHED_SUMMARY_MAX] = { 0 };
|
|
+ int schedSwitchTimes[SCHED_SUMMARY_MAX] = { 0 };
|
|
+ int cpuSwitchTimes[SCHED_SUMMARY_MAX] = { 0 };
|
|
+ int vaildDelaySched = 0; // Invalid scheduling cannot be analyzed
|
|
+ for (const auto &coreTrace : sched_tmp.second.coreTrace) {
|
|
+ int delay = coreTrace.endTime - coreTrace.startTime;
|
|
+ delaySum[SCHED_SUMMARY_ALL] += delay;
|
|
+ if (!coreTrace.startIsRet) { // count pid1->pidn times
|
|
+ schedSwitchTimes[SCHED_SUMMARY_ALL]++;
|
|
+ }
|
|
+ if (coreTrace.startCoreId != coreTrace.endCoreId) {
|
|
+ cpuSwitchTimes[SCHED_SUMMARY_ALL]++;
|
|
+ }
|
|
+ if (coreTrace.coreTraceType != CORE_TRACE_INVALID) {
|
|
+ delaySum[SCHED_SUMMARY_VAILD] += delay;
|
|
+ }
|
|
+ if (coreTrace.coreTraceType == CORE_TRACE_ONCORE) {
|
|
+ int coreIndex = coreTrace.startCoreId;
|
|
+ sched_tmp.second.runTimeOfCore[coreIndex] += delay;
|
|
}
|
|
|
|
- if (lastCoreIndex != coreIndex && coreIndex != -1) {
|
|
- cpuSwitchTimes++;
|
|
- lastCoreIndex = coreTrace.coreIndex;
|
|
+ if (coreTrace.coreTraceType == CORE_TRACE_SCHEDULING) {
|
|
+ vaildDelaySched += delay;
|
|
+ schedSwitchTimes[SCHED_SUMMARY_VAILD]++;
|
|
+ if (coreTrace.startCoreId != coreTrace.endCoreId) {
|
|
+ // CPU switching only occurs during scheduling
|
|
+ cpuSwitchTimes[SCHED_SUMMARY_VAILD]++;
|
|
+ }
|
|
}
|
|
}
|
|
- sched_tmp.second.schedSwitchDelay = delaySched;
|
|
- sched_tmp.second.schedSwitchTimes = schedSwitchTimes;
|
|
- sched_tmp.second.percentageSchedSwitch = delaySum == 0? 0.0 : delaySched * 1.0 / delaySum;
|
|
- sched_tmp.second.cpuSwitchTimes = cpuSwitchTimes;
|
|
- sched_tmp.second.delaySum = delaySum;
|
|
+ sched_tmp.second.vaildSchedSwitchDelay = vaildDelaySched;
|
|
+ sched_tmp.second.validPercentSchedSwitch = delaySum[SCHED_SUMMARY_VAILD] == 0 ? 0.0 : vaildDelaySched * 1.0 / delaySum[SCHED_SUMMARY_VAILD];
|
|
+ sched_tmp.second.schedSwitchTimes[SCHED_SUMMARY_VAILD] = schedSwitchTimes[SCHED_SUMMARY_VAILD];
|
|
+ sched_tmp.second.schedSwitchTimes[SCHED_SUMMARY_ALL] = schedSwitchTimes[SCHED_SUMMARY_ALL];
|
|
+ sched_tmp.second.cpuSwitchTimes[SCHED_SUMMARY_VAILD] = cpuSwitchTimes[SCHED_SUMMARY_VAILD];
|
|
+ sched_tmp.second.cpuSwitchTimes[SCHED_SUMMARY_ALL] = cpuSwitchTimes[SCHED_SUMMARY_ALL];
|
|
+ sched_tmp.second.delaySum[SCHED_SUMMARY_VAILD] = delaySum[SCHED_SUMMARY_VAILD];
|
|
+ sched_tmp.second.delaySum[SCHED_SUMMARY_ALL] = delaySum[SCHED_SUMMARY_ALL];
|
|
}
|
|
}
|
|
|
|
@@ -121,12 +158,15 @@ void SchedAnalysis::saveSchedInfoToFile()
|
|
if (pid == 0) {
|
|
continue;
|
|
}
|
|
- file << "pid," << pid << ",";
|
|
- file << "delaySum," << sched_tmp.second.delaySum << ",";
|
|
- file << "schedSwitchDelay," << sched_tmp.second.schedSwitchDelay << ",";
|
|
- file << "runtime," << sched_tmp.second.delaySum - sched_tmp.second.schedSwitchDelay << ",";
|
|
- file << "cpuSwitchTimes," << sched_tmp.second.cpuSwitchTimes << ",";
|
|
- file << std::endl;
|
|
+ file << "pid," << pid << "," << std::endl;
|
|
+ file << "cpuSwitchTimes," << sched_tmp.second.cpuSwitchTimes[SCHED_SUMMARY_ALL] << ",";
|
|
+ file << "schedSwitchTimes," << sched_tmp.second.schedSwitchTimes[SCHED_SUMMARY_ALL] << ",";
|
|
+ file << "delaySum," << sched_tmp.second.delaySum[SCHED_SUMMARY_ALL] << "," << std::endl;
|
|
+ file << "vaildCpuSwitchTimes," << sched_tmp.second.cpuSwitchTimes[SCHED_SUMMARY_VAILD] << ",";
|
|
+ file << "vaildSchedSwitchTimes," << sched_tmp.second.schedSwitchTimes[SCHED_SUMMARY_VAILD] << ",";
|
|
+ file << "validDelaySum," << sched_tmp.second.delaySum[SCHED_SUMMARY_VAILD] << ",";
|
|
+ file << "vaildSchedSwitchDelay," << sched_tmp.second.vaildSchedSwitchDelay << ",";
|
|
+ file << "validRuntime," << sched_tmp.second.delaySum[SCHED_SUMMARY_VAILD] - sched_tmp.second.vaildSchedSwitchDelay << "," << std::endl;
|
|
for (int coreIndex = 0; coreIndex < sched_tmp.second.runTimeOfCore.size(); coreIndex++) {
|
|
int run_time = sched_tmp.second.runTimeOfCore[coreIndex];
|
|
if (run_time != 0) {
|
|
@@ -137,7 +177,16 @@ void SchedAnalysis::saveSchedInfoToFile()
|
|
for (const auto &coreTrace : sched_tmp.second.coreTrace) {
|
|
file << "startTime," << std::fixed << std::setprecision(6) << slv.convertTimeIntToDouble(coreTrace.startTime) << ",";
|
|
file << "endTime," << std::fixed << std::setprecision(6) << slv.convertTimeIntToDouble(coreTrace.endTime) << ",";
|
|
- file << "coreIndex," << coreTrace.coreIndex;
|
|
+ file << "startCoreId," << coreTrace.startCoreId << ",";
|
|
+ file << "endCoreId," << coreTrace.endCoreId << ",";
|
|
+ file << "coreTraceType,";
|
|
+ if (coreTrace.coreTraceType == CORE_TRACE_INVALID) {
|
|
+ file << "invalid";
|
|
+ } else if (coreTrace.coreTraceType == CORE_TRACE_SCHEDULING) {
|
|
+ file << "scheduling";
|
|
+ } else if (coreTrace.coreTraceType == CORE_TRACE_ONCORE) {
|
|
+ file << "running";
|
|
+ }
|
|
file << std::endl;
|
|
}
|
|
file << std::endl;
|
|
@@ -154,8 +203,7 @@ void SchedAnalysis::saveSchedInfoSummaryToFile()
|
|
std::cout << "file open failed:" << cfg.filename[FILE_TYPE_OUTPUT_SUMMARY_SCHED_INFO] << std::endl;
|
|
return;
|
|
}
|
|
- file << "pid,delaySum,schedSwitchDelay,schedSwitchPercentage,schedSwitchTimes,cpuSwitchTimes";
|
|
- file << std::endl;
|
|
+ file << "pid,validDelaySum,vaildSchedSwitchDelay,validSchedSwitchPercentage,validSchedSwitchTimes,validCpuSwitchTimes" << std::endl;
|
|
TraceResolve &slv = TraceResolve::getInstance();
|
|
for (const auto &sched_tmp : processSchedMap) {
|
|
int pid = sched_tmp.first;
|
|
@@ -163,12 +211,11 @@ void SchedAnalysis::saveSchedInfoSummaryToFile()
|
|
continue;
|
|
}
|
|
file << pid << ",";
|
|
- file << sched_tmp.second.delaySum << ",";
|
|
- file << sched_tmp.second.schedSwitchDelay << ",";
|
|
- file << std::fixed << std::setprecision(3) << sched_tmp.second.percentageSchedSwitch * 100 << "%,";
|
|
- file << sched_tmp.second.schedSwitchTimes << ",";
|
|
- file << sched_tmp.second.cpuSwitchTimes << ",";
|
|
- file << std::endl;
|
|
+ file << sched_tmp.second.delaySum[SCHED_SUMMARY_VAILD] << ",";
|
|
+ file << sched_tmp.second.vaildSchedSwitchDelay << ",";
|
|
+ file << std::fixed << std::setprecision(3) << sched_tmp.second.validPercentSchedSwitch * 100 << "%,";
|
|
+ file << sched_tmp.second.schedSwitchTimes[SCHED_SUMMARY_VAILD] << ",";
|
|
+ file << sched_tmp.second.cpuSwitchTimes[SCHED_SUMMARY_VAILD] << "," << std::endl;
|
|
}
|
|
|
|
file.close();
|
|
@@ -177,6 +224,8 @@ void SchedAnalysis::saveSchedInfoSummaryToFile()
|
|
void SchedAnalysis::schedAnalysisProc()
|
|
{
|
|
schedInfoProc();
|
|
+ schedInfoVaildMark();
|
|
+
|
|
schedInfoAnalysis();
|
|
saveSchedInfoToFile();
|
|
saveSchedInfoSummaryToFile();
|
|
diff --git a/extra-tools/da-tool/analysis/sched_analysis.h b/extra-tools/da-tool/analysis/sched_analysis.h
|
|
index 85036ce..2d2a9ed 100644
|
|
--- a/extra-tools/da-tool/analysis/sched_analysis.h
|
|
+++ b/extra-tools/da-tool/analysis/sched_analysis.h
|
|
@@ -20,11 +20,29 @@
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
+typedef enum {
|
|
+ CORE_TRACE_INVALID, // valid when (s sr) or (sr s and startcore = endcore)
|
|
+ CORE_TRACE_SCHEDULING, // (s sr)
|
|
+ CORE_TRACE_ONCORE, // (sr s and startcore = endcore)
|
|
+ CORE_TRACE_MAX,
|
|
+} CORE_TRACE_E;
|
|
+
|
|
+typedef enum {
|
|
+ SCHED_SUMMARY_VAILD,
|
|
+ SCHED_SUMMARY_ALL, // "all" means "valid" + "invalid"
|
|
+ SCHED_SUMMARY_MAX,
|
|
+} SCHED_SUMMARY_E;
|
|
+
|
|
class ProcessCoreTrace {
|
|
public:
|
|
int startTime;
|
|
int endTime;
|
|
- int coreIndex; // -1 means sched_switch
|
|
+ int startCoreId;
|
|
+ int endCoreId;
|
|
+ bool startIsRet; // pid1->pid2 ret for pid2, not ret for pid1
|
|
+ bool endIsRet;
|
|
+
|
|
+ CORE_TRACE_E coreTraceType;
|
|
};
|
|
|
|
class ProcessSchedInfo {
|
|
@@ -33,11 +51,12 @@ public:
|
|
std::vector<int>(CPU_CORE_NUM_MAX, 0)}; // Time running on each CPU
|
|
std::vector<ProcessCoreTrace>
|
|
coreTrace; // CPU information of pid in each time period
|
|
- int schedSwitchDelay;
|
|
- int schedSwitchTimes;
|
|
- double percentageSchedSwitch;
|
|
- int cpuSwitchTimes;
|
|
- int delaySum;
|
|
+
|
|
+ int vaildSchedSwitchDelay;
|
|
+ double validPercentSchedSwitch; // valid / valid
|
|
+ int schedSwitchTimes[SCHED_SUMMARY_MAX];
|
|
+ int cpuSwitchTimes[SCHED_SUMMARY_MAX];
|
|
+ int delaySum[SCHED_SUMMARY_MAX];
|
|
};
|
|
|
|
class CpuSchedTrace {
|
|
@@ -70,8 +89,9 @@ private: // process sched info
|
|
std::unordered_map<int, ProcessSchedInfo> processSchedMap; // [pid]
|
|
// std::vector <std::vector<CpuSchedInfo>> allCpuSchedInfo; // [coreIndex]
|
|
void processSchedAnalysisLoop(const int &pid, const int ×tamp,
|
|
- const int &coreIndex);
|
|
+ const int &coreIndex, const bool &isRet);
|
|
void schedInfoProc();
|
|
+ void schedInfoVaildMark();
|
|
void schedInfoAnalysis();
|
|
void saveSchedInfoToFile();
|
|
void saveSchedInfoSummaryToFile();
|
|
diff --git a/extra-tools/da-tool/analysis/time_pair.cpp b/extra-tools/da-tool/analysis/time_pair.cpp
|
|
index 52aa6aa..024bbf6 100644
|
|
--- a/extra-tools/da-tool/analysis/time_pair.cpp
|
|
+++ b/extra-tools/da-tool/analysis/time_pair.cpp
|
|
@@ -153,20 +153,6 @@ void TimePair::timePairUpdateLoop(const int &pid, const int &functionIndex, cons
|
|
timePairMap[pid].emplace(functionIndex, infoTmp);
|
|
}
|
|
|
|
- Config &cfg = Config::getInstance();
|
|
- bool isCfgSchedSwitch = cfg.funcCfgMap.count("sched_switch") > 0;
|
|
- int sched_switch_funcidx = -1;
|
|
- if (isCfgSchedSwitch) {
|
|
- sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex;
|
|
- const TraceResolve &trace_resolve_inst = TraceResolve::getInstance();
|
|
- const FirstInfo &firstInfo = trace_resolve_inst.getTraceFirstInfo();
|
|
- int coreIndex = line_info_tmp.core;
|
|
- // This process cannot find the starting sched switch on this core, ignore trace after timestamp
|
|
- if (timestamp <= firstInfo.schedSwitchTime[coreIndex] && functionIndex != sched_switch_funcidx && coreIndex != firstInfo.coreId) {
|
|
- timePairMap[pid][functionIndex].minEndTimeInvalid = timestamp;
|
|
- }
|
|
- }
|
|
-
|
|
if (isRet) {
|
|
if (timePairMap[pid][functionIndex].startTime.size() == 0) { // fist is endtime ,startime=endtime
|
|
timePairMap[pid][functionIndex].startTime.emplace_back(timestamp);
|
|
@@ -219,7 +205,6 @@ void TimePair::timePairAlignment()
|
|
for (auto &processInfo : timePairMap) {
|
|
for (auto &funcInfo : processInfo.second) {
|
|
int diffLen = funcInfo.second.startTime.size() - funcInfo.second.endTime.size();
|
|
- bool updateEndTimeInvalid = false;
|
|
if (diffLen == 0) {
|
|
if (isOutputDebugFile) {
|
|
file << diffLen << "," << processInfo.first << " ," << funcInfo.first << " ," << \
|
|
@@ -247,9 +232,8 @@ void TimePair::timePairAlignment()
|
|
for (int i = 0; i < diffLen; i++) {
|
|
int endTime = funcInfo.second.startTime[funcInfo.second.startTime.size() - diffLen + i];
|
|
funcInfo.second.endTime.emplace_back(endTime);
|
|
- if (updateEndTimeInvalid == false) {
|
|
+ if (funcInfo.second.minEndTimeInvalid > endTime) {
|
|
funcInfo.second.minEndTimeInvalid = endTime;
|
|
- updateEndTimeInvalid = true;
|
|
}
|
|
}
|
|
}
|
|
@@ -303,8 +287,9 @@ void TimePair::timePairMarkInvalidData()
|
|
}
|
|
}
|
|
}
|
|
- validTimeOfPid[pid].validStartTime = validStartTime;
|
|
- validTimeOfPid[pid].validEndTime = validEndTime;
|
|
+ validTimeOfPid[pid].procStartTime = validStartTime;
|
|
+ validTimeOfPid[pid].procEndTime = validEndTime;
|
|
+ validTimeOfPid[pid].procTime = validEndTime - validStartTime;
|
|
}
|
|
|
|
Config &cfg = Config::getInstance();
|
|
@@ -315,8 +300,8 @@ void TimePair::timePairMarkInvalidData()
|
|
return;
|
|
}
|
|
for (const auto &range_info : validTimeOfPid) {
|
|
- file << "pid," << range_info.first << ",validStartTime ," << range_info.second.validStartTime << \
|
|
- ", validEndTime ," << range_info.second.validEndTime << std::endl;
|
|
+ file << "pid," << range_info.first << ",procStartTime ," << range_info.second.procStartTime << \
|
|
+ ", procEndTime ," << range_info.second.procEndTime << std::endl;
|
|
}
|
|
file.close();
|
|
}
|
|
@@ -347,15 +332,17 @@ void TimePair::timePairMatching()
|
|
int functionIndex = cfg.funcCfgMap[functionName].functionIndex;
|
|
int isRet = cfg.funcCfgMap[functionName].isRet;
|
|
int debugPos = 0;
|
|
- int fatherFunction = getFatherFunctionIdLoop(pid, functionIndex, isRet, debugPos);
|
|
- saveFuncStkDebugToFile(file, pid, functionIndex, isRet, timestamp, fatherFunction, debugPos);
|
|
- timePairUpdateLoop(pid, functionIndex, isRet, timestamp, fatherFunction, line_info_tmp);
|
|
+ if (line_info_tmp.traceValid[TRACE_VALID_FUNC] || line_info_tmp.traceValid[TRACE_VALID_SCHED_SWITCH_PREV]) {
|
|
+ int fatherFunction = getFatherFunctionIdLoop(pid, functionIndex, isRet, debugPos);
|
|
+ saveFuncStkDebugToFile(file, pid, functionIndex, isRet, timestamp, fatherFunction, debugPos);
|
|
+ timePairUpdateLoop(pid, functionIndex, isRet, timestamp, fatherFunction, line_info_tmp);
|
|
+ }
|
|
|
|
- if (isCfgSchedSwitch && functionIndex == sched_switch_funcidx) // pid1->pid2 : pid1->sched() sched_ret()->pid2
|
|
+ if (isCfgSchedSwitch && functionIndex == sched_switch_funcidx && line_info_tmp.traceValid[TRACE_VALID_SCHED_SWITCH_NEXT]) // pid1->pid2 : pid1->sched() sched_ret()->pid2
|
|
{
|
|
int nextPid = line_info_tmp.schedSwitchLine.nextPid;
|
|
isRet = 1;
|
|
- fatherFunction = getFatherFunctionIdLoop(nextPid, functionIndex, isRet, debugPos);
|
|
+ int fatherFunction = getFatherFunctionIdLoop(nextPid, functionIndex, isRet, debugPos);
|
|
saveFuncStkDebugToFile(file, nextPid, functionIndex, isRet, timestamp, fatherFunction, debugPos);
|
|
timePairUpdateLoop(nextPid, functionIndex, isRet, timestamp, fatherFunction, line_info_tmp);
|
|
}
|
|
@@ -363,6 +350,23 @@ void TimePair::timePairMatching()
|
|
file.close();
|
|
}
|
|
|
|
+void TimePair::functionDelayUpdateValidTimeLoop(const int &pid, const int ×tamp, const bool &valid)
|
|
+{
|
|
+
|
|
+ int lastTimeValid = validTimeOfPid[pid].lastTimeValid;
|
|
+ if (!lastTimeValid && valid) {
|
|
+ validTimeOfPid[pid].validStartTime.emplace_back(timestamp);
|
|
+ validTimeOfPid[pid].validEndTime.emplace_back(timestamp);
|
|
+ }
|
|
+
|
|
+ int size = validTimeOfPid[pid].validEndTime.size();
|
|
+ if (valid && size > 0) {
|
|
+ validTimeOfPid[pid].validEndTime[size - 1] = timestamp;
|
|
+ }
|
|
+
|
|
+ validTimeOfPid[pid].lastTimeValid = valid;
|
|
+}
|
|
+
|
|
void TimePair::functionDelayUpdate()
|
|
{
|
|
for (auto &processInfo : timePairMap) {
|
|
@@ -372,6 +376,33 @@ void TimePair::functionDelayUpdate()
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+ Config &cfg = Config::getInstance();
|
|
+ int sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex;
|
|
+ TraceResolve &trace_resolve_inst = TraceResolve::getInstance();
|
|
+ for (const auto &line_info_tmp : trace_resolve_inst.getTraceLine()) {
|
|
+ std::string functionName = line_info_tmp.functionName;
|
|
+ if (cfg.funcCfgMap.count(functionName) == 0) {
|
|
+ continue;
|
|
+ }
|
|
+ int pid = line_info_tmp.pid;
|
|
+ int timestamp = line_info_tmp.timestamp;
|
|
+ int functionIndex = cfg.funcCfgMap[functionName].functionIndex;
|
|
+ if (functionIndex == sched_switch_funcidx) {
|
|
+ int nextPid = line_info_tmp.schedSwitchLine.nextPid;
|
|
+ functionDelayUpdateValidTimeLoop(pid, timestamp, line_info_tmp.traceValid[TRACE_VALID_SCHED_SWITCH_PREV]);
|
|
+ functionDelayUpdateValidTimeLoop(nextPid, timestamp, line_info_tmp.traceValid[TRACE_VALID_SCHED_SWITCH_NEXT]);
|
|
+ } else {
|
|
+ functionDelayUpdateValidTimeLoop(pid, timestamp, line_info_tmp.traceValid[TRACE_VALID_FUNC]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (auto &processInfo : validTimeOfPid) {
|
|
+ int pid = processInfo.first;
|
|
+ for (int i = 0; i < processInfo.second.validStartTime.size(); i++) {
|
|
+ validTimeOfPid[pid].validTime += (processInfo.second.validEndTime[i] - processInfo.second.validStartTime[i]);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
void TimePair::functionStatisticsAnalysis()
|
|
@@ -448,7 +479,7 @@ void TimePair::saveTimePairToFile()
|
|
file << "maxStartTimeInvaild:" << funcInfo.second.maxStartTimeInvaild << ",";
|
|
file << "minEndTimeInvalid:" << funcInfo.second.minEndTimeInvalid << "," << std::endl;
|
|
file << "info num," << funcInfo.second.startTime.size() << ",valid info num," << funcInfo.second.summary.callTimes[DELAY_INFO_ALL] << ",";
|
|
- file << "validStartTime," << validTimeOfPid[pid].validStartTime << ",validEndTime," << validTimeOfPid[pid].validEndTime << std::endl;
|
|
+ file << "procStartTime," << validTimeOfPid[pid].procStartTime << ",procEndTime," << validTimeOfPid[pid].procEndTime << std::endl;
|
|
file << "startTime" << ",";
|
|
for (const auto &startTime : funcInfo.second.startTime) {
|
|
file << std::fixed << std::setprecision(6) << startTime << ",";
|
|
@@ -544,14 +575,22 @@ void TimePair::saveDelayInfoToFile()
|
|
}
|
|
|
|
|
|
-int TimePair::getProcessValidTime(const int &pid)
|
|
+int TimePair::getProcessTime(const int &pid)
|
|
{
|
|
if (validTimeOfPid.count(pid) != 0) {
|
|
- return validTimeOfPid[pid].validEndTime - validTimeOfPid[pid].validStartTime;
|
|
+ return validTimeOfPid[pid].procTime;
|
|
} else {
|
|
return 0;
|
|
}
|
|
+}
|
|
|
|
+int TimePair::getProcessValidTime(const int &pid)
|
|
+{
|
|
+ if (validTimeOfPid.count(pid) != 0) {
|
|
+ return validTimeOfPid[pid].validTime;
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
}
|
|
|
|
void TimePair::timePairAnalysis()
|
|
diff --git a/extra-tools/da-tool/analysis/time_pair.h b/extra-tools/da-tool/analysis/time_pair.h
|
|
index ba0b784..925a017 100644
|
|
--- a/extra-tools/da-tool/analysis/time_pair.h
|
|
+++ b/extra-tools/da-tool/analysis/time_pair.h
|
|
@@ -23,8 +23,16 @@
|
|
|
|
class VaildRange {
|
|
public:
|
|
- int validStartTime;
|
|
- int validEndTime;
|
|
+ // Invalid timestamps divide the trace into several valid parts
|
|
+ std::vector<int> validStartTime;
|
|
+ std::vector<int> validEndTime;
|
|
+
|
|
+ int procStartTime{0};
|
|
+ int procEndTime{0};
|
|
+ int procTime{0};
|
|
+ int validTime{0};
|
|
+ // tmp var
|
|
+ bool lastTimeValid{false};
|
|
};
|
|
|
|
typedef enum {
|
|
@@ -67,7 +75,7 @@ public:
|
|
std::vector<int> fatherFuncPos;
|
|
std::vector<int> childFuncTimes; // Number of calls to other functions.
|
|
std::vector<uintptr_t> retVal; // return value
|
|
- std::vector<bool> isInvalid; // isInvalid=true indicates that there is no
|
|
+ std::vector<bool> isInvalid; // isInvalid=true indicates that there is no
|
|
// complete call stack data
|
|
std::vector<std::string> strFunctionStk;
|
|
|
|
@@ -90,7 +98,6 @@ public:
|
|
~TimePair() {}
|
|
|
|
private:
|
|
- // [pid].start/end Record the start and end times of valid traces
|
|
std::unordered_map<int, VaildRange> validTimeOfPid;
|
|
// Store function call stacks for each pid
|
|
std::unordered_map<int, std::vector<int>> funcStkMap;
|
|
@@ -109,6 +116,8 @@ private:
|
|
const int ×tamp, const int &fatherFunction,
|
|
const int &debugPos);
|
|
void functionDelayUpdate();
|
|
+ void functionDelayUpdateValidTimeLoop(const int &pid, const int ×tamp,
|
|
+ const bool &valid);
|
|
void functionStatisticsAnalysis();
|
|
|
|
void timePairMatching();
|
|
@@ -122,6 +131,7 @@ public:
|
|
const std::unordered_map<int, std::unordered_map<int, TimePairInfo>> &
|
|
getTimePairMap() const;
|
|
int getProcessValidTime(const int &pid);
|
|
+ int getProcessTime(const int &pid);
|
|
void timePairAnalysis();
|
|
};
|
|
|
|
diff --git a/extra-tools/da-tool/analysis/trace_resolve.cpp b/extra-tools/da-tool/analysis/trace_resolve.cpp
|
|
index 61f0a74..ae86773 100644
|
|
--- a/extra-tools/da-tool/analysis/trace_resolve.cpp
|
|
+++ b/extra-tools/da-tool/analysis/trace_resolve.cpp
|
|
@@ -56,12 +56,6 @@ const std::vector<TraceLineReslove> &TraceResolve::getTraceLine() const
|
|
return traceLineVec;
|
|
}
|
|
|
|
-const FirstInfo &TraceResolve::getTraceFirstInfo() const
|
|
-{
|
|
- return firstInfo;
|
|
-}
|
|
-
|
|
-
|
|
void SchedSwitchLine::processStateToEnum(std::string state)
|
|
{
|
|
if (state == "R") {
|
|
@@ -74,7 +68,8 @@ void SchedSwitchLine::processStateToEnum(std::string state)
|
|
}
|
|
}
|
|
|
|
-int countLines(const std::string& filename) {
|
|
+int countLines(const std::string &filename)
|
|
+{
|
|
std::ifstream file(filename);
|
|
if (!file.is_open()) {
|
|
std::cout << "file open failed:" << filename << std::endl;
|
|
@@ -130,7 +125,7 @@ void TraceResolve::resolveTrace()
|
|
continue;
|
|
}
|
|
if (line_num % 10000 == 0) {
|
|
- double rate = (line_num - cfg.readTraceBegin) * 1.0/ readTraceLen;
|
|
+ double rate = (line_num - cfg.readTraceBegin) * 1.0 / readTraceLen;
|
|
std::cout << "\r" << "[Resolve] " << std::fixed << std::setprecision(3) << rate * 100 << "%, ";
|
|
std::cout << "Match " << regex_num;
|
|
std::cout.flush();
|
|
@@ -178,9 +173,6 @@ void TraceResolve::resolveTrace()
|
|
if (isMatch) {
|
|
if (isFirstMatch) {
|
|
startTimeIntPart = std::stoi(match[TRACE_INFO_TIMESTAMP_INT].str());
|
|
- firstInfo.coreId = std::stoi(match[TRACE_INFO_CPU].str());
|
|
- firstInfo.startTime = (std::stoi(match[TRACE_INFO_TIMESTAMP_INT].str()) - startTimeIntPart) * MICRO_PER_SEC \
|
|
- + std::stoi(match[TRACE_INFO_TIMESTAMP_FLOAT].str());
|
|
isFirstMatch = false;
|
|
}
|
|
match_info.timestamp = (std::stoi(match[TRACE_INFO_TIMESTAMP_INT].str()) - startTimeIntPart) * MICRO_PER_SEC \
|
|
@@ -190,6 +182,10 @@ void TraceResolve::resolveTrace()
|
|
match_info.functionName = match[TRACE_INFO_FUNCNAME].str();
|
|
match_info.traceLineNum = line_num;
|
|
|
|
+ match_info.traceValid[TRACE_VALID_FUNC] = false;
|
|
+ match_info.traceValid[TRACE_VALID_SCHED_SWITCH_PREV] = false;
|
|
+ match_info.traceValid[TRACE_VALID_SCHED_SWITCH_NEXT] = false;
|
|
+
|
|
traceLineVec.emplace_back(match_info);
|
|
regex_num++;
|
|
}
|
|
@@ -224,15 +220,22 @@ void TraceResolve::saveTraceRegexRstToFile()
|
|
return;
|
|
}
|
|
|
|
- file << "traceLineNum" << "," << "pid" << "," << "core" << "," << "timestamp" << "," << "functionName" << std::endl;
|
|
+ file << "traceLineNum,pid,core,timestamp,functionName,";
|
|
+ file << "prevPid,prevPrio,prevState,nextPid,nextPrio,";
|
|
+ file << "funcValid,schedPrevValid,schedNextValid" << std::endl;
|
|
for (const auto &row : traceLineVec) {
|
|
file << row.traceLineNum << ",";
|
|
- file << row.pid << "," << row.core << "," << "," << std::fixed << std::setprecision(6) << \
|
|
+ file << row.pid << "," << row.core << "," << std::fixed << std::setprecision(6) << \
|
|
row.timestamp * 1.0 / MICRO_PER_SEC + startTimeIntPart << "," << row.functionName;
|
|
if (row.functionName == "sched_switch") {
|
|
file << "," << row.schedSwitchLine.prevPid << "," << row.schedSwitchLine.prevPrio << "," << \
|
|
row.schedSwitchLine.prevState << "," << row.schedSwitchLine.nextPid << "," << row.schedSwitchLine.nextPrio;
|
|
+ } else {
|
|
+ file << ",,,,,";
|
|
}
|
|
+ file << "," << row.traceValid[TRACE_VALID_FUNC];
|
|
+ file << "," << row.traceValid[TRACE_VALID_SCHED_SWITCH_PREV];
|
|
+ file << "," << row.traceValid[TRACE_VALID_SCHED_SWITCH_NEXT];
|
|
file << std::endl;
|
|
}
|
|
|
|
@@ -245,64 +248,188 @@ double TraceResolve::convertTimeIntToDouble(const int ×tamp)
|
|
return timestamp * 1.0 / MICRO_PER_SEC + startTimeIntPart;
|
|
}
|
|
|
|
-void TraceResolve::firstSchedSwitchTimeAnalysis()
|
|
+void FuncValid::addToVectors(int traceId, bool isR, bool val)
|
|
+{
|
|
+ traceLineIndex.emplace_back(traceId);
|
|
+ isRet.emplace_back(isR);
|
|
+ valid.emplace_back(val);
|
|
+}
|
|
+
|
|
+void TraceResolve::creatEmptyFuncPairMap(const int &pid, const int &funcIndex)
|
|
{
|
|
+ if (funcPairMap.count(pid) == 0) {
|
|
+ std::unordered_map<int, FuncValid> funcValidMapTmp;
|
|
+ funcPairMap.emplace(pid, funcValidMapTmp);
|
|
+ }
|
|
+
|
|
+ if (funcPairMap[pid].count(funcIndex) == 0) {
|
|
+ FuncValid funcVaildTmp;
|
|
+ funcPairMap[pid].emplace(funcIndex, funcVaildTmp);
|
|
+ }
|
|
+}
|
|
+
|
|
+void TraceResolve::funcPairMapInit()
|
|
+{
|
|
+ // [pid][func]
|
|
Config &cfg = Config::getInstance();
|
|
- bool isCfgSchedSwitch = cfg.funcCfgMap.count("sched_switch") > 0;
|
|
- int sched_switch_funcidx = -1;
|
|
- if (isCfgSchedSwitch) {
|
|
- sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex;
|
|
- } else {
|
|
+ for (int traceId = 0; traceId < traceLineVec.size(); traceId++) {
|
|
+ int pid = traceLineVec[traceId].pid;
|
|
+ std::string functionName = traceLineVec[traceId].functionName;
|
|
+ int functionIndex = cfg.funcCfgMap[functionName].functionIndex;
|
|
+ int isRet = cfg.funcCfgMap[functionName].isRet == 0 ? false : true;
|
|
+
|
|
+ creatEmptyFuncPairMap(pid, functionIndex);
|
|
+ funcPairMap[pid][functionIndex].addToVectors(traceId, isRet, false);
|
|
+
|
|
+ if (traceLineVec[traceId].functionName == "sched_switch") {
|
|
+ int nextPid = traceLineVec[traceId].schedSwitchLine.nextPid;
|
|
+ creatEmptyFuncPairMap(nextPid, functionIndex);
|
|
+ funcPairMap[nextPid][functionIndex].addToVectors(traceId, true, false);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (auto &processInfo : funcPairMap) {
|
|
+ for (auto &funcInfo : processInfo.second) {
|
|
+ for (int i = 0; i < funcInfo.second.isRet.size() - 1; i++) {
|
|
+ // a a a a a_r a_r a_r, a a_r is valid trace
|
|
+ if (!funcInfo.second.isRet[i] && funcInfo.second.isRet[i + 1]) {
|
|
+ funcInfo.second.valid[i] = true;
|
|
+ funcInfo.second.valid[i + 1] = true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ saveFuncPairMapToFile();
|
|
+}
|
|
+
|
|
+void TraceResolve::saveFuncPairMapToFile()
|
|
+{
|
|
+ Config &cfg = Config::getInstance();
|
|
+ if (cfg.getDebugLevel() < DEBUG_LEVEL_2) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ std::ofstream file(cfg.filename[FILE_TYPE_DEBUG_TRACE_FUNCPAIRMAP], std::ios::out | std::ios::trunc);
|
|
+ if (!file) {
|
|
+ std::cout << "file open failed:" << cfg.filename[FILE_TYPE_DEBUG_TRACE_FUNCPAIRMAP] << std::endl;
|
|
return;
|
|
}
|
|
|
|
- firstInfo.schedSwitchTime.resize(CPU_CORE_NUM_MAX, INT_MAX);
|
|
- firstInfo.coreTime.resize(CPU_CORE_NUM_MAX, INT_MAX);
|
|
- firstInfo.schedSwitchTime[firstInfo.coreId] = firstInfo.startTime;
|
|
- firstInfo.coreTime[firstInfo.coreId] = firstInfo.startTime;
|
|
+ for (const auto &processInfo : funcPairMap) {
|
|
|
|
- for (const auto &line_info_tmp : traceLineVec) {
|
|
- std::string functionName = line_info_tmp.functionName;
|
|
- int pid = line_info_tmp.pid;
|
|
- if (cfg.funcCfgMap.count(functionName) == 0) {
|
|
- continue;
|
|
+ for (const auto &funcInfo : processInfo.second) {
|
|
+ int funcIndex = funcInfo.first;
|
|
+ file << "pid," << processInfo.first;
|
|
+ file << ",funcid," << funcIndex;
|
|
+ file << ",funcName," << cfg.IndexToFunction[funcIndex] << std::endl;
|
|
+ file << "isRet,";
|
|
+ for (int i = 0; i < funcInfo.second.isRet.size(); i++) {
|
|
+ file << funcInfo.second.isRet[i] << ",";
|
|
+ }
|
|
+ file << std::endl;
|
|
+ file << "valid,";
|
|
+ for (int i = 0; i < funcInfo.second.valid.size(); i++) {
|
|
+ file << funcInfo.second.valid[i] << ",";
|
|
+ }
|
|
+ file << std::endl;
|
|
+ file << "traceLineIndex,";
|
|
+ for (int i = 0; i < funcInfo.second.traceLineIndex.size(); i++) {
|
|
+ file << funcInfo.second.traceLineIndex[i] << ",";
|
|
+ }
|
|
+ file << std::endl;
|
|
}
|
|
+ }
|
|
|
|
- int timestamp = line_info_tmp.timestamp;
|
|
- int coreIndex = line_info_tmp.core;
|
|
- int functionIndex = cfg.funcCfgMap[functionName].functionIndex;
|
|
- // first appearance of coreIndex in trace
|
|
- if (firstInfo.coreTime[coreIndex] == INT_MAX) {
|
|
- firstInfo.coreTime[coreIndex] = timestamp;
|
|
- }
|
|
- // first appearance of sched_switch in coreIndex's trace
|
|
- if (functionIndex == sched_switch_funcidx && firstInfo.schedSwitchTime[coreIndex] == INT_MAX) {
|
|
- firstInfo.schedSwitchTime[coreIndex] = timestamp;
|
|
+ file.close();
|
|
+}
|
|
+
|
|
+void TraceResolve::markTraceIsValid()
|
|
+{
|
|
+ Config &cfg = Config::getInstance();
|
|
+ int sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex;
|
|
+
|
|
+ for (auto &processInfo : funcPairMap) {
|
|
+ for (auto &funcInfo : processInfo.second) {
|
|
+ int functionIndex = funcInfo.first;
|
|
+ for (int i = 0; i < funcInfo.second.valid.size(); i++) {
|
|
+ bool validTmp = funcInfo.second.valid[i];
|
|
+ int traceId = funcInfo.second.traceLineIndex[i];
|
|
+ if (functionIndex == sched_switch_funcidx) {
|
|
+ // pid1 -> s s_r ->pid2
|
|
+ if (funcInfo.second.isRet[i]) {
|
|
+ traceLineVec[traceId].traceValid[TRACE_VALID_SCHED_SWITCH_NEXT] = validTmp;
|
|
+ } else {
|
|
+ traceLineVec[traceId].traceValid[TRACE_VALID_SCHED_SWITCH_PREV] = validTmp;
|
|
+ }
|
|
+ } else {
|
|
+ traceLineVec[traceId].traceValid[TRACE_VALID_FUNC] = validTmp;
|
|
+ }
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
|
|
-void TraceResolve::trace_resolve_proc()
|
|
+void TraceResolve::markFuncStkValidLoop(const int &pid, const int &funcIndex, const int &traceId, const TRACE_VALID_E &validType)
|
|
{
|
|
- resolveTrace();
|
|
- saveTraceRegexRstToFile();
|
|
+ if (funcStkValidMap.count(pid) == 0) {
|
|
+ FuncStkValid funcStkVaildTmp;
|
|
+ funcStkValidMap.emplace(pid, funcStkVaildTmp);
|
|
+ }
|
|
+
|
|
+ bool traceValid = traceLineVec[traceId].traceValid[validType];
|
|
+ if (!traceValid) {
|
|
+ funcStkValidMap[pid].isInvalid = true;
|
|
+ } else {
|
|
+ funcStkValidMap[pid].traceIndex.emplace_back(traceId);
|
|
+ funcStkValidMap[pid].vaildType.emplace_back(validType);
|
|
+ if (!funcStkValidMap[pid].funcStk.empty() && funcIndex == funcStkValidMap[pid].funcStk.back()) {
|
|
+ funcStkValidMap[pid].funcStk.pop_back();
|
|
+ } else {
|
|
+ funcStkValidMap[pid].funcStk.emplace_back(funcIndex);
|
|
+ }
|
|
+ }
|
|
|
|
- firstSchedSwitchTimeAnalysis();
|
|
+ if (funcStkValidMap[pid].funcStk.size() == 0) {
|
|
+ if (funcStkValidMap[pid].isInvalid) {
|
|
+ for (int i = 0; i < funcStkValidMap[pid].traceIndex.size(); i++) {
|
|
+ int traceIndexTmp = funcStkValidMap[pid].traceIndex[i];
|
|
+ TRACE_VALID_E vaildTypeTmp = funcStkValidMap[pid].vaildType[i];
|
|
+ traceLineVec[traceIndexTmp].traceValid[vaildTypeTmp] = false;
|
|
+ }
|
|
+ }
|
|
+ // clear history
|
|
+ funcStkValidMap[pid].traceIndex.resize(0);
|
|
+ funcStkValidMap[pid].vaildType.resize(0);
|
|
+ funcStkValidMap[pid].isInvalid = false;
|
|
+ }
|
|
}
|
|
|
|
-void TraceResolve::trace_check_show()
|
|
+void TraceResolve::markFuncStkValid()
|
|
{
|
|
Config &cfg = Config::getInstance();
|
|
- for (int coreId = 0; coreId < CPU_CORE_NUM_MAX; coreId++) {
|
|
- int firstSchedSwitchTime = firstInfo.schedSwitchTime[coreId];
|
|
- int firstCoreTime = firstInfo.coreTime[coreId];
|
|
- if (cfg.getDebugLevel() >= DEBUG_LEVEL_1) {
|
|
- std::cout << "coreId:" << coreId;
|
|
- std::cout << ",firstSchedSwitchTime:" << firstSchedSwitchTime;
|
|
- std::cout << ",firstCoreTime:" << firstCoreTime << std::endl;
|
|
- }
|
|
- if (firstSchedSwitchTime != firstCoreTime) {
|
|
- std::cout << "[ERROR] core " << coreId << " missing starting scheduling information, result maybe error!!!" << std::endl;
|
|
+ int sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex;
|
|
+ for (int traceId = 0; traceId < traceLineVec.size(); traceId++) {
|
|
+ int pid = traceLineVec[traceId].pid;
|
|
+ std::string functionName = traceLineVec[traceId].functionName;
|
|
+ int functionIndex = cfg.funcCfgMap[functionName].functionIndex;
|
|
+ if (functionIndex == sched_switch_funcidx) {
|
|
+ int nextPid = traceLineVec[traceId].schedSwitchLine.nextPid;
|
|
+ markFuncStkValidLoop(pid, functionIndex, traceId, TRACE_VALID_SCHED_SWITCH_PREV);
|
|
+ markFuncStkValidLoop(nextPid, functionIndex, traceId, TRACE_VALID_SCHED_SWITCH_NEXT);
|
|
+ } else {
|
|
+ markFuncStkValidLoop(pid, functionIndex, traceId, TRACE_VALID_FUNC);
|
|
}
|
|
}
|
|
+}
|
|
+
|
|
+void TraceResolve::trace_resolve_proc()
|
|
+{
|
|
+ resolveTrace();
|
|
+ // trace valid check
|
|
+ funcPairMapInit();
|
|
+ markTraceIsValid();
|
|
+ markFuncStkValid();
|
|
+
|
|
+ saveTraceRegexRstToFile();
|
|
}
|
|
\ No newline at end of file
|
|
diff --git a/extra-tools/da-tool/analysis/trace_resolve.h b/extra-tools/da-tool/analysis/trace_resolve.h
|
|
index e943d20..4b8ba89 100644
|
|
--- a/extra-tools/da-tool/analysis/trace_resolve.h
|
|
+++ b/extra-tools/da-tool/analysis/trace_resolve.h
|
|
@@ -21,11 +21,10 @@
|
|
#include <vector>
|
|
|
|
// include\linux\sched.h
|
|
-typedef enum
|
|
-{
|
|
- PROCESS_STATE_TASK_RUNNING, // R
|
|
- PROCESS_STATE_TASK_INTERRUPTIBLE, // S
|
|
- PROCESS_STATE_MAX,
|
|
+typedef enum {
|
|
+ PROCESS_STATE_TASK_RUNNING, // R
|
|
+ PROCESS_STATE_TASK_INTERRUPTIBLE, // S
|
|
+ PROCESS_STATE_MAX,
|
|
} PROCESS_STATE_E;
|
|
|
|
class SchedSwitchLine {
|
|
@@ -40,6 +39,13 @@ public:
|
|
void processStateToEnum(std::string state);
|
|
};
|
|
|
|
+typedef enum {
|
|
+ TRACE_VALID_FUNC,
|
|
+ TRACE_VALID_SCHED_SWITCH_PREV,
|
|
+ TRACE_VALID_SCHED_SWITCH_NEXT,
|
|
+ TRACE_VALID_MAX,
|
|
+} TRACE_VALID_E;
|
|
+
|
|
class TraceLineReslove {
|
|
public:
|
|
int traceLineNum;
|
|
@@ -52,14 +58,24 @@ public:
|
|
|
|
// after convert
|
|
int functionIndex;
|
|
+ bool traceValid[TRACE_VALID_MAX];
|
|
+};
|
|
+
|
|
+class FuncValid {
|
|
+public:
|
|
+ std::vector<int> traceLineIndex;
|
|
+ std::vector<bool> isRet;
|
|
+ std::vector<bool> valid; // rst
|
|
+
|
|
+ void addToVectors(int traceId, bool isR, bool val);
|
|
};
|
|
|
|
-class FirstInfo {
|
|
+class FuncStkValid {
|
|
public:
|
|
- std::vector<int> schedSwitchTime; // [coreId]
|
|
- std::vector<int> coreTime; // [coreId]
|
|
- int coreId; // first core in trace
|
|
- int startTime;
|
|
+ std::vector<int> funcStk;
|
|
+ std::vector<int> traceIndex;
|
|
+ std::vector<TRACE_VALID_E> vaildType; // size() = traceIndex.size();
|
|
+ bool isInvalid{false}; // tmp rst
|
|
};
|
|
|
|
class TraceResolve {
|
|
@@ -80,12 +96,20 @@ private: // regex
|
|
void saveTraceRegexRstToFile();
|
|
|
|
private:
|
|
- FirstInfo firstInfo;
|
|
- void firstSchedSwitchTimeAnalysis();
|
|
+ // [pid][functionIndex] mark unmatch func => invalid
|
|
+ std::unordered_map<int, std::unordered_map<int, FuncValid>> funcPairMap;
|
|
+ // [pid] if funcstk have invalid data, mark all funcstk invalid
|
|
+ std::unordered_map<int, FuncStkValid> funcStkValidMap;
|
|
+ void creatEmptyFuncPairMap(const int &pid, const int &funcIndex);
|
|
+ void funcPairMapInit();
|
|
+ void markTraceIsValid();
|
|
+ void markFuncStkValid();
|
|
+ void markFuncStkValidLoop(const int &pid, const int &funcIndex,
|
|
+ const int &traceId, const TRACE_VALID_E &validType);
|
|
+ void saveFuncPairMapToFile();
|
|
|
|
public:
|
|
const std::vector<TraceLineReslove> &getTraceLine() const;
|
|
- const FirstInfo &getTraceFirstInfo() const;
|
|
double convertTimeIntToDouble(const int ×tamp);
|
|
void trace_resolve_proc();
|
|
void trace_check_show();
|
|
diff --git a/extra-tools/da-tool/main.cpp b/extra-tools/da-tool/main.cpp
|
|
index 34652f0..abc1004 100644
|
|
--- a/extra-tools/da-tool/main.cpp
|
|
+++ b/extra-tools/da-tool/main.cpp
|
|
@@ -37,7 +37,6 @@ int main(int argc, char *argv[])
|
|
FunctionStack &fstk = FunctionStack::getInstance();
|
|
fstk.function_stack_proc();
|
|
|
|
- trace_resolve_inst.trace_check_show();
|
|
cout << "[STEP 2-2] analysis finish" << endl;
|
|
return 0;
|
|
}
|
|
\ No newline at end of file
|
|
diff --git a/extra-tools/da-tool/script/da-tool.sh b/extra-tools/da-tool/script/da-tool.sh
|
|
index 2b38bc8..3bfa366 100755
|
|
--- a/extra-tools/da-tool/script/da-tool.sh
|
|
+++ b/extra-tools/da-tool/script/da-tool.sh
|
|
@@ -31,8 +31,9 @@ cd $base_dir
|
|
mkdir -p tmp
|
|
|
|
# extern para
|
|
-sleep_time=10
|
|
-sleep_time_max=100
|
|
+sleep_time_default=1
|
|
+sleep_time=$sleep_time_default
|
|
+sleep_time_max=10
|
|
|
|
# base para
|
|
declare -a kernel_symbols
|
|
@@ -79,10 +80,18 @@ function usage() {
|
|
echo "usage: da-tool.sh [OPTIONS] [ARGS]"
|
|
echo ""
|
|
echo "The most commonly used da-tool.sh options are:"
|
|
- echo " -t <duration> set tracing duration, unit: seconds, 1<=duration<=100, default is 10"
|
|
+ echo " -t <duration> set tracing duration, unit: seconds, 1<=duration<=$sleep_time_max, default is $sleep_time_default"
|
|
echo " -h show usage"
|
|
}
|
|
|
|
+function sleep_time_check() {
|
|
+ if [ $sleep_time -ge $((sleep_time_max + 1)) ] || [ $sleep_time -le 0 ]; then
|
|
+ echo "sampling time should > 0 and <= $sleep_time_max"
|
|
+ usage
|
|
+ exit 1
|
|
+ fi
|
|
+}
|
|
+
|
|
# get opt
|
|
# while getopts "b:l:t:p:as" opt; do # debug
|
|
while getopts "t:h" opt; do
|
|
@@ -99,9 +108,9 @@ while getopts "t:h" opt; do
|
|
if [[ $OPTARG =~ ^[0-9]{1,3}$ ]]; then
|
|
sleep_time=$OPTARG
|
|
else
|
|
- usage
|
|
- exit 1
|
|
+ sleep_time=0
|
|
fi
|
|
+ sleep_time_check
|
|
;;
|
|
p)
|
|
parameter="$OPTARG"
|
|
@@ -161,7 +170,7 @@ function arr_repet_ele_check() {
|
|
for element in "${arr[@]}"; do
|
|
count=$(printf '%s\n' "${arr[@]}" | grep -c -w "$element")
|
|
if [ $count -ge 2 ]; then
|
|
- echo " '$element' duplicate configuration, please check '$config_file'!!!"
|
|
+ echo " '$element' duplicate configuration"
|
|
exit 1
|
|
fi
|
|
done
|
|
@@ -172,7 +181,7 @@ function arr_check_function_support() {
|
|
local symbols_tmp=("$@")
|
|
for symbol in "${symbols_tmp[@]}"; do
|
|
if [[ $symbol =~ \. ]]; then
|
|
- echo "$symbol have '.', not support, please check '$config_file!!!'" | tee -a $sample_log
|
|
+ echo "$symbol have '.', not support" | tee -a $sample_log
|
|
exit 1
|
|
fi
|
|
done
|
|
@@ -181,12 +190,18 @@ function arr_check_function_support() {
|
|
# kernel symbols should be found in '/proc/kallsyms'
|
|
function arr_check_kernel_symbols_exist() {
|
|
local symbols_tmp=("$@")
|
|
+ kernel_symbols=()
|
|
for symbol in "${symbols_tmp[@]}"; do
|
|
if grep -e "^[0-9a-fA-F]* [a-zA-Z] $symbol$" /proc/kallsyms >/dev/null; then
|
|
echo "$symbol exist in /proc/kallsyms" >>$sample_log
|
|
+ # first version
|
|
+ # (1) only support kernel symbols
|
|
+ # (2) can't config /etc/da-tool.conf
|
|
+ # (3) if symbols not in /proc/kallsyms, then continue(not exit)
|
|
+ kernel_symbols[${#kernel_symbols[*]}]+=$symbol
|
|
else
|
|
- echo "$symbol does not exist in /proc/kallsyms or not support, please check '$config_file'!!!" | tee -a $sample_log
|
|
- exit 1
|
|
+ echo "$symbol does not exist in /proc/kallsyms or not support" | tee -a $sample_log
|
|
+ # exit 1 # after first version
|
|
fi
|
|
done
|
|
}
|
|
@@ -199,7 +214,7 @@ function arr_check_user_symbols_exist() {
|
|
if nm "$binary" | grep -q "\<$symbol\>"; then
|
|
echo "$symbol dost exist in $binary" >>$sample_log
|
|
else
|
|
- echo "$symbol does not exist in $binary, please check '$config_file'!!!" | tee -a $sample_log
|
|
+ echo "$symbol does not exist in $binary" | tee -a $sample_log
|
|
exit 1
|
|
fi
|
|
done
|
|
@@ -211,7 +226,7 @@ function arr_check_sched() {
|
|
if [[ $sched == "sched_switch" ]]; then
|
|
echo "sched_switch match" >>$sample_log
|
|
else
|
|
- echo "s only support sched_switch, please check '$config_file'!!!" | tee -a $sample_log
|
|
+ echo "s only support sched_switch" | tee -a $sample_log
|
|
exit 1
|
|
fi
|
|
done
|
|
@@ -301,20 +316,6 @@ function gen_config_for_analysis() {
|
|
done
|
|
}
|
|
|
|
-function opt_check() {
|
|
- if [ $is_uprobe_sample = false ] && [ $is_kprobe_sample = false ]; then
|
|
- echo "use -m u|k|uk to set uprobe/kprobe/both"
|
|
- usage
|
|
- exit 1
|
|
- fi
|
|
-
|
|
- if [ $sleep_time -ge $((sleep_time_max + 1)) ] || [ $sleep_time -le 0 ]; then
|
|
- echo "sampling time should > 0 and <= $sleep_time_max"
|
|
- usage
|
|
- exit 1
|
|
- fi
|
|
-}
|
|
-
|
|
function clear_env() {
|
|
echo "[INFO] clear env..."
|
|
echo 0 >/sys/kernel/debug/tracing/tracing_on
|
|
@@ -369,6 +370,7 @@ function sample_init() {
|
|
echo >/sys/kernel/debug/tracing/trace
|
|
echo 40960 >/sys/kernel/debug/tracing/buffer_size_kb
|
|
|
|
+
|
|
echo >/sys/kernel/debug/tracing/uprobe_events
|
|
echo >/sys/kernel/debug/tracing/kprobe_events
|
|
}
|
|
@@ -538,8 +540,6 @@ if [ $is_clear = true ]; then
|
|
exit 1
|
|
fi
|
|
|
|
-opt_check
|
|
-
|
|
if [ $is_analysis_only_mode = true ]; then # only analysis
|
|
trace_analysis
|
|
exit 1
|
|
--
|
|
2.33.0
|
|
|